]> git.mxchange.org Git - flightgear.git/commitdiff
Complete C++ rewrite of all cockpit code by Charlie Hotchkiss.
authorcurt <curt>
Mon, 11 May 1998 18:13:10 +0000 (18:13 +0000)
committercurt <curt>
Mon, 11 May 1998 18:13:10 +0000 (18:13 +0000)
Cockpit/cockpit.cxx
Cockpit/cockpit.hxx
Cockpit/hud.cxx
Cockpit/hud.hxx

index 736847e3ef599aa6537800ee8b958abb4c8dc8e2..daa2116e6ff9b277cee9ac5ba3ae35b2a7555e07 100644 (file)
 
 #include <stdlib.h>
 
-#include <Include/fg_constants.h>
-
 #include <Aircraft/aircraft.h>
 #include <Debug/fg_debug.h>
+#include <Include/fg_constants.h>
+#include <Include/general.h>
 #include <Math/fg_random.h>
 #include <Math/mat3.h>
 #include <Math/polar3d.h>
 
 #include "cockpit.hxx"
 
+
 // This is a structure that contains all data related to
 // cockpit/panel/hud system
 
-static fgCOCKPIT *aircraft_cockpit;
+static pCockpit ac_cockpit;
 
-fgCOCKPIT *fgCockpitInit( fgAIRCRAFT *cur_aircraft )
+// The following routines obtain information concerntin the aircraft's
+// current state and return it to calling instrument display routines.
+// They should eventually be member functions of the aircraft.
+//
+
+double get_throttleval( void )
 {
-       fgCOCKPIT *cockpit;
-       Hptr hud;
+       fgCONTROLS *pcontrols;
 
-       fgPrintf( FG_COCKPIT, FG_INFO, "Initializing cockpit subsystem\n");
+  pcontrols = current_aircraft.controls;
+  return pcontrols->throttle[0];     // Hack limiting to one engine
+}
 
-       cockpit = (fgCOCKPIT *)calloc(sizeof(fgCOCKPIT),1);
-       if( cockpit == NULL )
-               return( NULL );
+double get_aileronval( void )
+{
+       fgCONTROLS *pcontrols;
 
-       cockpit->code = 1;      /* It will be aircraft dependent */
-       cockpit->status = 0;
+  pcontrols = current_aircraft.controls;
+  return pcontrols->aileron;
+}
 
-       // If aircraft has HUD
-       hud = fgHUDInit( cur_aircraft );  // Color no longer in parameter list
-       if( hud == NULL )
-               return( NULL );
+double get_elevatorval( void )
+{
+       fgCONTROLS *pcontrols;
 
-       cockpit->hud = hud;
+  pcontrols = current_aircraft.controls;
+  return pcontrols->elevator;
+}
 
-       aircraft_cockpit = cockpit;
+double get_elev_trimval( void )
+{
+       fgCONTROLS *pcontrols;
 
-       fgPrintf( FG_COCKPIT, FG_INFO,
-                 "  Code %d  Status %d\n", 
-                 cockpit->hud->code, cockpit->hud->status );
+  pcontrols = current_aircraft.controls;
+  return pcontrols->elevator_trim;
+}
+
+double get_rudderval( void )
+{
+       fgCONTROLS *pcontrols;
+
+  pcontrols = current_aircraft.controls;
+  return pcontrols->rudder;
+}
+
+double get_speed( void )
+{
+       fgFLIGHT *f;
+
+       f = current_aircraft.flight;
+       return( FG_V_equiv_kts );    // Make an explicit function call.
+}
+
+double get_aoa( void )
+{
+       fgFLIGHT *f;
+              
+       f = current_aircraft.flight;
+       return( FG_Gamma_vert_rad * RAD_TO_DEG );
+}
+
+double get_roll( void )
+{
+       fgFLIGHT *f;
+
+       f = current_aircraft.flight;
+       return( FG_Phi );
+}
+
+double get_pitch( void )
+{
+       fgFLIGHT *f;
+              
+       f = current_aircraft.flight;
+       return( FG_Theta );
+}
+
+double get_heading( void )
+{
+       fgFLIGHT *f;
+
+       f = current_aircraft.flight;
+       return( FG_Psi * RAD_TO_DEG );
+}
+
+double get_altitude( void )
+{
+       fgFLIGHT *f;
+       // double rough_elev;
+
+       f = current_aircraft.flight;
+       // rough_elev = mesh_altitude(FG_Longitude * RAD_TO_ARCSEC,
+       //                                 FG_Latitude  * RAD_TO_ARCSEC);
+
+       return( FG_Altitude * FEET_TO_METER /* -rough_elev */ );
+}
+
+double get_sideslip( void )
+{
+        fgFLIGHT *f;
+        
+        f = current_aircraft.flight;
+        
+        return( FG_Beta );
+}
 
-       return( cockpit );
+double get_frame_rate( void )
+{
+    fgGENERAL *g;                                                               
+    g = &general;                     
+    return g->frame_rate;                                                      
 }
 
-fgCOCKPIT *fgCockpitAddHUD( fgCOCKPIT *cockpit, HUD *hud )
+bool fgCockpitInit( fgAIRCRAFT *cur_aircraft )
 {
-       cockpit->hud = hud;
-       return(cockpit);
+       fgPrintf( FG_COCKPIT, FG_INFO, "Initializing cockpit subsystem\n");
+
+//     cockpit->code = 1;      /* It will be aircraft dependent */
+//     cockpit->status = 0;
+
+       // If aircraft has HUD specified we will get the specs from its def
+  // file. For now we will depend upon hard coding in hud?
+
+  // We must insure that the existing instrument link is purged.
+  // This is done by deleting the links in the list.
+
+  // HI_Head is now a null pointer so we can generate a new list from the
+  // current aircraft.
+
+  fgHUDInit( cur_aircraft );
+  ac_cockpit = new fg_Cockpit();
+
+       fgPrintf( FG_COCKPIT, FG_INFO,
+                 "  Code %d  Status %d\n",
+                 ac_cockpit->code(), ac_cockpit->status() );
+
+       return true;
 }
 
 void fgCockpitUpdate( void )
 {
 
        fgPrintf( FG_COCKPIT, FG_DEBUG,
-                 "Cockpit: code %d   status %d\n", 
-                 aircraft_cockpit->code, aircraft_cockpit->status );
-       if( aircraft_cockpit->hud != NULL ) {
-           // That is, if the aircraft has a HUD, then draw it.
-           fgUpdateHUD( aircraft_cockpit->hud );
-       }
+                 "Cockpit: code %d   status %d\n",
+                 ac_cockpit->code(), ac_cockpit->status() );
+       fgUpdateHUD();  // This will check the global hud linked list pointer.
+                  // If these is anything to draw it will.
 }
 
-
 /* $Log$
-/* Revision 1.4  1998/05/03 00:46:45  curt
-/* polar.h -> polar3d.h
+/* Revision 1.5  1998/05/11 18:13:10  curt
+/* Complete C++ rewrite of all cockpit code by Charlie Hotchkiss.
 /*
+ * Revision 1.4  1998/05/03 00:46:45  curt
+ * polar.h -> polar3d.h
+ *
  * Revision 1.3  1998/04/30 12:36:02  curt
  * C++-ifying a couple source files.
  *
@@ -139,7 +245,7 @@ void fgCockpitUpdate( void )
  * Added MetroWorks patches from Carmen Volpe.
  *
  * Revision 1.7  1998/01/27 00:47:51  curt
- * Incorporated Paul Bleisch's <pbleisch@acm.org> new debug message
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
  * system and commandline/config file processing code.
  *
  * Revision 1.6  1998/01/19 19:27:01  curt
index f57750bfa79c92512955ee81ca8a14efed076fca..718f1e0b55fc92b453995538cb15cf086a255034 100644 (file)
 # error This library requires C++
 #endif                                   
 
+//typedef struct  {
+//     int code;
+//     Hptr hud;
+//     // As above.
+//     // PANEL *panel;
+//     int status;
+//}fgCOCKPIT, *pfgCockpit;
 
 // And in the future (near future i hope).
 // #include <Cockpit/panel.h>
+// Class fg_Cockpit          This class is a holder for the heads up display
+//                          and is initialized with a
+class fg_Cockpit  {
+  private:
+    int  Code;
+    int  Status;
 
-typedef struct  {
-       int code;
-       Hptr hud;
-       // As above.
-       // PANEL *panel;
-       int status;
-}fgCOCKPIT, *pfgCockpit;
+  public:
+    fg_Cockpit   () : Code(1), Status(0) {};
+    int   code  ( void ) { return Code; }
+    int   status( void ) { return Status; }
+};
 
-fgCOCKPIT *fgCockpitInit( fgAIRCRAFT *cur_aircraft );
+typedef fg_Cockpit * pCockpit;
+
+bool fgCockpitInit( fgAIRCRAFT *cur_aircraft );
 void fgCockpitUpdate( void );
 
 
@@ -55,9 +68,12 @@ void fgCockpitUpdate( void );
 
 
 /* $Log$
-/* Revision 1.1  1998/04/24 00:45:55  curt
-/* C++-ifing the code a bit.
+/* Revision 1.2  1998/05/11 18:13:10  curt
+/* Complete C++ rewrite of all cockpit code by Charlie Hotchkiss.
 /*
+ * Revision 1.1  1998/04/24 00:45:55  curt
+ * C++-ifing the code a bit.
+ *
  * Revision 1.8  1998/04/22 13:26:19  curt
  * C++ - ifing the code a bit.
  *
index a23170a57f2d369acfc52457d7830f9558aeff54..f07b2f2f93c44aba0c840dcd167f86ba244d2a29 100644 (file)
@@ -1,5 +1,5 @@
 /**************************************************************************
- * hud.c -- hud defines and prototypes
+ * hud.cxx -- hud defines and prototypes
  *
  * Written by Michele America, started September 1997.
  *
@@ -22,7 +22,7 @@
  * $Id$
  * (Log is kept at end of this file)
  **************************************************************************/
+
 
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
@@ -43,7 +43,6 @@
 #include <Aircraft/aircraft.h>
 #include <Debug/fg_debug.h>
 #include <Include/fg_constants.h>
-#include <Include/general.h>
 #include <Math/fg_random.h>
 #include <Math/mat3.h>
 #include <Math/polar3d.h>
 
 #include "hud.hxx"
 
-// #define DEBUG
-
-#define drawOneLine(x1,y1,x2,y2)  glBegin(GL_LINES);  \
-       glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();
-
-
 // The following routines obtain information concerntin the aircraft's
 // current state and return it to calling instrument display routines.
 // They should eventually be member functions of the aircraft.
 //
 
-double get_frame_rate(void) {
-    fgGENERAL *g;
+//using namespace std;
+
+/*
 
-    g = &general;
+class instr_ptr {
+  private:
+    instr_item *pHI;
 
-    return g->frame_rate;
+  public:
+    instr_ptr ( instr_item * pHudInstr = 0) : pHI( pHudInstr){}
+    ~instr_ptr() { if( pHI ) delete pHI; }
+    instr_ptr & operator = (const instr_ptr & rhs);
+    instr_ptr( const instr_ptr & image );
 }
 
-double get_throttleval( void )
+instr_ptr &
+instr_ptr ::
+operator = ( const instr_ptr & rhs )
 {
-       fgCONTROLS *pcontrols;
-
-  pcontrols = current_aircraft.controls;
-  return pcontrols->throttle[0];     // Hack limiting to one engine
+  if( !(this == &rhs )) {
+    pHI = new instr_item( *(rhs.pHI));
+    }
+  return *this;
 }
 
-double get_aileronval( void )
+instr_ptr ::
+instr_ptr ( const instr_ptr & image ) :
 {
-       fgCONTROLS *pcontrols;
-
-  pcontrols = current_aircraft.controls;
-  return pcontrols->aileron;
+  pHI = new instr_item( *(image.pHI));
 }
+*/
+deque< instr_item * > HUD_deque;
 
-double get_elevatorval( void )
-{
-       fgCONTROLS *pcontrols;
+class locRECT {
+  public:
+    RECT rect;
 
-  pcontrols = current_aircraft.controls;
-  return pcontrols->elevator;
-}
+    locRECT( UINT left, UINT top, UINT right, UINT bottom);
+    RECT get_rect(void) { return rect;}
+};
 
-double get_elev_trimval( void )
+locRECT :: locRECT( UINT left, UINT top, UINT right, UINT bottom)
 {
-       fgCONTROLS *pcontrols;
+  rect.left   =  left;
+  rect.top    =  top;
+  rect.right  =  right;
+  rect.bottom =  bottom;
 
-  pcontrols = current_aircraft.controls;
-  return pcontrols->elevator_trim;
 }
+// #define DEBUG
 
-double get_rudderval( void )
-{
-       fgCONTROLS *pcontrols;
+// #define drawOneLine(x1,y1,x2,y2)  glBegin(GL_LINES);
+//   glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();
+//
 
-  pcontrols = current_aircraft.controls;
-  return pcontrols->rudder;
+void drawOneLine( UINT x1, UINT y1, UINT x2, UINT y2)
+{
+  glBegin(GL_LINES);
+  glVertex2f(x1, y1);
+  glVertex2f(x2, y2);
+  glEnd();
 }
 
-double get_speed( void )
+void drawOneLine( RECT &rect)
 {
-       fgFLIGHT *f;
+  glBegin(GL_LINES);
+  glVertex2f(rect.left, rect.top);
+  glVertex2f(rect.right, rect.bottom);
+  glEnd();
+}
+
+//
+// The following code deals with painting the "instrument" on the display
+//
+   /* textString - Bitmap font string */
 
-       f = current_aircraft.flight;
-       return( FG_V_equiv_kts );    // Make an explicit function call.
+static void textString(int x, int y, char *msg, void *font)
+{
+       glRasterPos2f(x, y);
+       while (*msg) {
+               glutBitmapCharacter(font, *msg);
+               msg++;
+    }
 }
 
-double get_aoa( void )
+/* strokeString - Stroke font string */
+/*
+static void strokeString(int x, int y, char *msg, void *font)
 {
-       fgFLIGHT *f;
-              
-       f = current_aircraft.flight;
-       return( FG_Gamma_vert_rad * RAD_TO_DEG );
+       glPushMatrix();
+       glTranslatef(x, y, 0);
+       glScalef(.04, .04, .04);
+       while (*msg) {
+               glutStrokeCharacter(font, *msg);
+               msg++;
+       }
+       glPopMatrix();
 }
+*/
+
+
 
-double get_roll( void )
+// Abstract Base Class instr_item
+//
+UINT instr_item :: instances;  // Initial value of zero
+
+// constructor    ( No default provided )
+
+instr_item  ::
+   instr_item( RECT             scr_pos,
+               DBLFNPTR         data_source,
+               ReadOriented     orientation,
+               bool             working) :
+                      handle         ( ++instances  ),
+                      scrn_pos       ( scr_pos      ),
+                      load_value_fn  ( data_source  ),
+                      oriented       ( orientation  ),
+                      is_enabled     ( working      ),
+                      broken         ( FALSE        ),
+                      brightness     ( BRT_DARK     )
 {
-       fgFLIGHT *f;
+int hitemp, widetemp;
+int xtemp;
+
+         // Check for inverted rect coords.  We must have top/right > bottom
+         // left corners or derived classes will draw their boxes very oddly.
+         // This is the only place we can reliably validate this data. Note
+         // that the box may be entirely or partly located off the screen.
+         // This needs consideration and possibly a member function to move
+         // the box, a keen idea for supporting "editing" of the HUD.
+  if( scrn_pos.top < scrn_pos.bottom ) {
+    xtemp           = scrn_pos.bottom;
+    scrn_pos.bottom = scrn_pos.top;
+    scrn_pos.top    = xtemp;
+    }
+  if( scrn_pos.left > scrn_pos.right ) {
+    xtemp           = scrn_pos.left;
+    scrn_pos.left   = scrn_pos.right;
+    scrn_pos.right  = xtemp;
+    }
+
+         // Insure that the midpoint marker will fall exactly at the
+         // middle of the bar.
+  if( !((scr_pos.top-scr_pos.bottom) % 2)) {
+    scrn_pos.top++;
+    }
+  if( !((scr_pos.right - scr_pos.left ) % 2)) {
+    scrn_pos.right++;
+    }
+         // Set up convenience values for centroid of the box and
+         // the span values according to orientation
 
-       f = current_aircraft.flight;
-       return( FG_Phi );
+  hitemp   = scr_pos.top - scr_pos.bottom;
+  widetemp = scr_pos.right - scr_pos.left;
+  if((orientation == ReadTOP) || (orientation == ReadBOTTOM)) {
+    scr_span = widetemp;
+    }
+  else {
+    scr_span = hitemp;
+    }
+         // Here we work out the centroid for the corrected box.
+  mid_span.x = scr_pos.left   + ((scr_pos.right - scr_pos.left) >> 1);
+  mid_span.y = scr_pos.bottom + ((scr_pos.top - scr_pos.bottom) >> 1);
 }
 
-double get_pitch( void )
+// copy constructor
+instr_item  ::
+     instr_item ( const instr_item & image ):
+                         handle       ( ++instances        ),
+                         scrn_pos     ( image.scrn_pos     ),
+                         load_value_fn( image.load_value_fn),
+                         oriented     ( image.oriented     ),
+                         is_enabled   ( image.is_enabled   ),
+                         broken       ( image.broken       ),
+                         brightness   ( image.brightness   ),
+                         scr_span     ( image.scr_span     ),
+                         mid_span     ( image.mid_span     )
 {
-       fgFLIGHT *f;
-              
-       f = current_aircraft.flight;
-       return( FG_Theta );
 }
 
-double get_heading( void )
+// assignment operator
+
+instr_item & instr_item :: operator = ( const instr_item & rhs )
 {
-       fgFLIGHT *f;
+  if( !(this == &rhs )) { // Not an identity assignment
+    scrn_pos      = rhs.scrn_pos;
+    load_value_fn = rhs.load_value_fn;
+    oriented      = rhs.oriented;
+    is_enabled    = rhs.is_enabled;
+    broken        = rhs.broken;
+    brightness    = rhs.brightness;
+    }
+  return *this;
+}
 
-       f = current_aircraft.flight;
-       return( FG_Psi * RAD_TO_DEG );
+// destructor
+
+instr_item :: ~instr_item ()
+{
+  if( instances ) {
+    instances--;
+    }
 }
 
-double get_altitude( void )
+void instr_item ::
+    update( void )
 {
-       fgFLIGHT *f;
-       // double rough_elev;
+}
 
-       f = current_aircraft.flight;
-       // rough_elev = mesh_altitude(FG_Longitude * RAD_TO_ARCSEC,
-       //                                 FG_Latitude  * RAD_TO_ARCSEC);
+// break_display       This is emplaced to provide hooks for making
+//                     instruments unreliable. The default behavior is
+// to simply not display, but more sophisticated behavior is available
+// by over riding the function which is virtual in this class.
 
-       return( FG_Altitude * FEET_TO_METER /* -rough_elev */ );
+void instr_item ::
+    break_display ( bool bad )
+{
+  broken = !!bad;
+  is_enabled = FALSE;
 }
 
-double get_sideslip( void )
+void instr_item ::
+    SetBrightness  ( int level  )
 {
-        fgFLIGHT *f;
-        
-        f = current_aircraft.flight;
-        
-        return( FG_Beta );
+  brightness = level;   // This is all we will do for now. Later the
+                        // brightness levels will be sensitive both to
+                        // the control knob and the outside light levels
+                        // to emulated night vision effects.
 }
 
-/****************************************************************************/
-/* Convert degrees to dd mm.mmm' (DMM-Format)                               */
-/****************************************************************************/
-#if 0
-char *toDM(double a)
+UINT instr_item :: get_Handle( void )
 {
-  short        neg = 0;
-  double       d, m;
-  static char  dm[13];
-  
-  if (a < 0.0) {
-    a = -a;
-    neg = 1;
-  }
-
-  d = (double) ( (int) a);
-  m = (a - d) * 60.0;
-  
-  if (m > 59.5) {
-    m  = 0.0;
-    d += 1.0;
-  }
-  if (neg) d = -d;
-  
-  sprintf(dm, "%.0f°%06.3f'", d, m);
-  return dm;
+  return handle;
 }
-#endif // 0
-double get_latitude( void )
-{
-       fgFLIGHT *f;
-       f = current_aircraft.flight;
 
-//     return( toDM(FG_Latitude * RAD_TO_DEG) );
-       return((double)((int)( FG_Latitude * RAD_TO_DEG)) );    
-}
-double get_lat_min( void )
+//======================= Top of instr_label class =========================
+instr_label ::
+         instr_label( RECT          region,
+                      DBLFNPTR      data_source,
+                      const char   *label_format,
+                      const char   *pre_label_string,
+                      const char   *post_label_string,
+                      ReadOriented  orientation,
+                      fgLabelJust   justification,
+                      int           font_size,
+                      int           blinking,
+                      bool          working ):
+                           instr_item( region, data_source,
+                                            orientation, working ),
+                           pformat  ( label_format      ),
+                           pre_str  ( pre_label_string  ),
+                           post_str ( post_label_string ),
+                           justify  ( justification     ),
+                           fontSize ( font_size         ),
+                           blink    ( blinking          )
 {
-       fgFLIGHT *f;
-       double      a, d;
-
-       f = current_aircraft.flight;
-       
-       a = FG_Latitude * RAD_TO_DEG;   
-       if (a < 0.0) {
-               a = -a;
-       }
-       d = (double) ( (int) a);
-       return( (a - d) * 60.0);
 }
 
+// I put this in to make it easy to construct a class member using the current
+// C code.
 
-double get_longitude( void )
+
+instr_label :: ~instr_label()
 {
-       fgFLIGHT *f;
-       f = current_aircraft.flight;
+}
 
-//     return( toDM(FG_Longitude * RAD_TO_DEG) );
-       return((double)((int) (FG_Longitude * RAD_TO_DEG)) );
+// Copy constructor
+instr_label :: instr_label( const instr_label & image) :
+                              instr_item((const instr_item &)image),
+                              pformat    ( image.pformat    ),
+                              pre_str  ( image.pre_str  ),
+                              post_str ( image.post_str ),
+                              blink    ( image.blink    )
+{
 }
-double get_long_min( void )
+
+instr_label & instr_label ::operator = (const instr_label & rhs )
 {
-       fgFLIGHT *f;
-       double  a, d;
-
-       f = current_aircraft.flight;
-       
-       a = FG_Longitude * RAD_TO_DEG;  
-       if (a < 0.0) {
-               a = -a;
-       }
-       d = (double) ( (int) a);
-       return( (a - d) * 60.0);
+  if( !(this == &rhs)) {
+    instr_item::operator = (rhs);
+    pformat      = rhs.pformat;
+    fontSize   = rhs.fontSize;
+    blink      = rhs.blink;
+    justify    = rhs.justify;
+    pre_str    = rhs.pre_str;
+    post_str   = rhs.post_str;
+    }
+       return *this;
 }
 
+
 //
-// The following code deals with painting the "instrument" on the display
+// draw                    Draws a label anywhere in the HUD
 //
-   /* textString - Bitmap font string */
+//
+void instr_label ::
+draw( void )       // Required method in base class
+{
+  char format_buffer[80];
+  char label_buffer[80];
+  int posincr;
+  int lenstr;
+  RECT  scrn_rect = get_location();
 
-static void textString(int x, int y, char *msg, void *font)
+  if( pre_str != NULL) {
+    if( post_str != NULL ) {
+      sprintf( format_buffer, "%s%s%s", pre_str, pformat, post_str );
+      }
+    else {
+      sprintf( format_buffer, "%s%s",   pre_str, pformat );
+      }
+    }
+  else {
+    if( post_str != NULL ) {
+      sprintf( format_buffer, "%s%s",   pformat, post_str );
+      }
+    } // else do nothing if both pre and post strings are nulls. Interesting.
+
+  sprintf( label_buffer, format_buffer, get_value() );
+#ifdef DEBUGHUD
+       fgPrintf( FG_COCKPIT, FG_DEBUG,  format_buffer );
+       fgPrintf( FG_COCKPIT, FG_DEBUG,  "\n" );
+       fgPrintf( FG_COCKPIT, FG_DEBUG, label_buffer );
+       fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
+#endif
+  lenstr = strlen( label_buffer );
+
+  posincr = 0;   //  default to RIGHT_JUST ... center located calc: -lenstr*8;
+
+  if( justify == CENTER_JUST ) {
+    posincr =  - (lenstr << 2); //  -lenstr*4;
+    }
+  else {
+    if( justify == LEFT_JUST ) {
+      posincr = - (lenstr << 8);  // 0;
+      }
+    }
+
+  if( fontSize == SMALL ) {
+    textString( scrn_rect.left + posincr, scrn_rect.bottom,
+                label_buffer, GLUT_BITMAP_8_BY_13);
+    }
+  else  {
+    if( fontSize == LARGE ) {
+      textString( scrn_rect.left + posincr, scrn_rect.bottom,
+                  label_buffer, GLUT_BITMAP_9_BY_15);
+      }
+    }
+}
+
+//============== Top of instr_scale class memeber definitions ===============
+//
+// Notes:
+// 1. instr_scales divide the specified location into half and then
+//    the half opposite the read direction in half again. A bar is
+//    then drawn along the second divider. Scale ticks are drawn
+//    between the middle and quarter section lines (minor division
+//    markers) or just over the middle line.
+//
+// 2.  This class was not intended to be instanciated. See moving_scale
+//     and guage_instr classes.
+//============================================================================
+instr_scale ::
+instr_scale ( RECT         the_box,
+              DBLFNPTR     load_fn,
+              ReadOriented orient,
+              int          show_range,
+              int          maxValue,
+              int          minValue,
+              UINT         major_divs,
+              UINT         minor_divs,
+              UINT         rollover,
+              bool         working ) :
+                instr_item( the_box, load_fn, orient, working),
+                range_shown  ( show_range ),
+                Maximum_value( maxValue   ),
+                Minimum_value( minValue   ),
+                Maj_div      ( major_divs ),
+                Min_div      ( minor_divs ),
+                Modulo       ( rollover   )
 {
-       glRasterPos2f(x, y);
-       while (*msg) {
-               glutBitmapCharacter(font, *msg);
-               msg++;
+int temp;
+
+  scale_factor   = (double)get_span() / range_shown;
+  if( show_range < 0 ) {
+    range_shown = -range_shown;
+    }
+  temp = (Maximum_value - Minimum_value) / 100;
+  if( range_shown < temp ) {
+    range_shown = temp;
     }
 }
 
-/* strokeString - Stroke font string */
-/*
-static void strokeString(int x, int y, char *msg, void *font)
+instr_scale ::
+  instr_scale( const instr_scale & image ) :
+            instr_item( (const instr_item &) image),
+            range_shown  ( image.range_shown   ),
+            Maximum_value( image.Maximum_value ),
+            Minimum_value( image.Minimum_value ),
+            Maj_div      ( image.Maj_div       ),
+            Min_div      ( image.Min_div       ),
+            Modulo       ( image.Modulo        ),
+            scale_factor ( image.scale_factor  )
 {
-       glPushMatrix();
-       glTranslatef(x, y, 0);
-       glScalef(.04, .04, .04);
-       while (*msg) {
-               glutStrokeCharacter(font, *msg);
-               msg++;
-       }
-       glPopMatrix();
 }
-*/
 
-/*
+instr_scale & instr_scale :: operator = (const instr_scale & rhs )
+{
+  if( !(this == &rhs)) {
+    instr_item::operator = (rhs);
+    Minimum_value = rhs.Minimum_value;
+    Maximum_value = rhs.Maximum_value;
+    Maj_div       = rhs.Maj_div;
+    Min_div       = rhs.Min_div;
+    Modulo        = rhs.Modulo;
+    scale_factor  = rhs.scale_factor;
+    range_shown   = rhs.range_shown;
+    }
+  return *this;
+}
+
+instr_scale :: ~ instr_scale () {}
+
+//========== Top of moving_scale_instr class member definitions =============
+
+moving_scale ::
+moving_scale( RECT         the_box,
+              DBLFNPTR     data_source,
+              ReadOriented orientation,
+              int          max_value,
+              int          min_value,
+              UINT         major_divs,
+              UINT         minor_divs,
+              UINT         modulus,
+              double       value_span,
+              bool         working) :
+                instr_scale( the_box,
+                             data_source, orientation,
+                             (int)value_span,
+                             max_value, min_value,
+                             major_divs, minor_divs, modulus,
+                             working),
+                val_span   ( value_span)
+{
+  half_width_units = range_to_show() / 2.0;
+}
 
-       Draws a measuring scale anywhere on the HUD
+moving_scale ::
+~moving_scale() { }
 
+moving_scale ::
+moving_scale( const moving_scale & image):
+      instr_scale( (const instr_scale & ) image)
+{
+}
 
-       Needs: HUD_scale struct
+moving_scale & moving_scale ::
+operator = (const moving_scale & rhs )
+{
+  if( !( this == &rhs)){
+    instr_scale::operator = (rhs);
+    }
+  return *this;
+}
 
-*/
-static void drawscale( HUD_scale * pscale )
+void moving_scale ::
+draw( void ) //  (HUD_scale * pscale )
 {
   double vmin, vmax;
   int marker_x;
@@ -293,127 +531,391 @@ static void drawscale( HUD_scale * pscale )
   register i;
   char TextScale[80];
   int condition;
-  double cur_value = (*(pscale->load_value))();
   int disp_val;
+  POINT mid_scr = get_centroid();
+  POINT bias_bar;                  // eliminates some orientation checks
+  double cur_value = get_value();
+  RECT   scrn_rect = get_location();
+  ReadOriented orientation = get_orientation();
 
-  vmin = cur_value - pscale->half_width_units; // width units == needle travel
-  vmax = cur_value + pscale->half_width_units; // or picture unit span.
+  vmin = cur_value - half_width_units; // width units == needle travel
+  vmax = cur_value + half_width_units; // or picture unit span.
 
 
-  if( pscale->type == VERTICAL )     // Vertical scale
+  if( (orientation == ReadLEFT) ||( orientation == ReadRIGHT))  // Vertical scale
     {
-      drawOneLine( pscale->scrn_pos.right,    // Vertical scale bar
-                   pscale->scrn_pos.bottom,
-                   pscale->scrn_pos.right,
-                   pscale->scrn_pos.top );
-
-    if( pscale->orientation == LEFT )     // Calculate x marker offset
-      marker_x = pscale->scrn_pos.left - 6;
-    else
-      if( pscale->orientation == RIGHT )
-        marker_x = pscale->scrn_pos.right;
+    if( orientation == ReadLEFT ) {    // Calculate x marker offset
+      marker_x = scrn_rect.left - 6;
+      bias_bar.x = ((scrn_rect.right - mid_scr.x)>>1) + mid_scr.x;
+      }
+    else {                             // We'll default this for now.
+      marker_x = mid_scr.x;            // scrn_rect.right;
+      bias_bar.x = ((mid_scr.x - scrn_rect.left)>>1) + scrn_rect.left;
+      }
 
     // Draw the basic markings for the scale...
 
-    if( pscale->orientation == LEFT )
+    drawOneLine( bias_bar.x,    // Vertical scale bar
+                 scrn_rect.bottom,
+                 bias_bar.x,
+                 scrn_rect.top );
+
+
+    if( orientation == ReadLEFT )
       {
 
-      drawOneLine( pscale->scrn_pos.right - 3,     // Bottom tick bar
-                   pscale->scrn_pos.bottom,
-                   pscale->scrn_pos.right,
-                   pscale->scrn_pos.bottom );
+      drawOneLine( bias_bar.x,     // Bottom tick bar
+                   scrn_rect.bottom,
+                   mid_scr.x,
+                   scrn_rect.bottom );
 
-      drawOneLine( pscale->scrn_pos.right - 3,     // Top tick bar
-                   pscale->scrn_pos.top,
-                   pscale->scrn_pos.right,
-                   pscale->scrn_pos.top );
+      drawOneLine( bias_bar.x,     // Top tick bar
+                   scrn_rect.top,
+                   mid_scr.x,
+                   scrn_rect.top );
 
-      drawOneLine( pscale->scrn_pos.right,       // Middle tick bar /Index
-                   pscale->mid_scr,
-                   pscale->scrn_pos.right + 6,
-                   pscale->mid_scr );
+      drawOneLine( scrn_rect.right,       // Middle tick bar /Index
+                   mid_scr.y,
+                   bias_bar.x,
+                   mid_scr.y );
 
       }
-    else
-      if( pscale->orientation == RIGHT )
-        {
-        drawOneLine( pscale->scrn_pos.right,
-                     pscale->scrn_pos.bottom,
-                     pscale->scrn_pos.right+3,
-                     pscale->scrn_pos.bottom );
-
-        drawOneLine( pscale->scrn_pos.right,
-                     pscale->scrn_pos.top,
-                     pscale->scrn_pos.right+3,
-                     pscale->scrn_pos.top );
-
-        drawOneLine( pscale->scrn_pos.right,
-                     pscale->mid_scr,
-                     pscale->scrn_pos.right-6,
-                     pscale->mid_scr );
-        }
+    else       { // ReadRight
+      drawOneLine( bias_bar.x,
+                   scrn_rect.bottom,
+                   mid_scr.x,
+                   scrn_rect.bottom );
+
+      drawOneLine( bias_bar.x,
+                   scrn_rect.top,
+                   mid_scr.x,
+                   scrn_rect.top );
+
+      drawOneLine( scrn_rect.left,
+                   mid_scr.y,
+                   bias_bar.x,
+                   mid_scr.y );
+      }
 
     // Work through from bottom to top of scale. Calculating where to put
     // minor and major ticks.
 
-    for( i = (int)(vmin); i <= (int)(vmax); i++ )
+    for( i = (int)vmin; i <= (int)vmax; i++ )
       {
-      if( pscale->sub_type == LIMIT ) {           // Don't show ticks
-        condition = (i >= pscale->minimum_value); // below Minimum value.
-        }
-      else {
-        if( pscale->sub_type == NOLIMIT ) {
-          condition = 1;
-          }
-        }
+//      if( sub_type == LIMIT ) {           // Don't show ticks
+        condition = (i >= min_val()); // below Minimum value.
+//        }
+//      else {
+//        if( sub_type == NOLIMIT ) {
+//          condition = 1;
+//          }
+//        }
       if( condition )   // Show a tick if necessary
         {
         // Calculate the location of this tick
-        marker_y = (int)(pscale->scrn_pos.bottom + (i - vmin) * pscale->factor);
+        marker_y = scrn_rect.bottom + (int)((i - vmin) * factor());
 
         // Block calculation artifact from drawing ticks below min coordinate.
         // Calculation here accounts for text height.
 
-        if( marker_y < (pscale->scrn_pos.bottom + 4)) {  // Magic number!!!
+        if( marker_y < (scrn_rect.bottom + 4)) {  // Magic number!!!
           continue;
           }
-        if( (i%pscale->div_min) == 0) {
-          if( pscale->orientation == LEFT )
+        if( div_min()) {
+          if( (i%div_min()) == 0) {
+//            if( orientation == ReadLEFT )
+//              {
+//              drawOneLine( marker_x + 3, marker_y, marker_x + 6, marker_y );
+              drawOneLine( bias_bar.x, marker_y, mid_scr.x, marker_y );
+//              }
+//            else {
+//              if( orientation == ReadRIGHT )
+//                {
+//                drawOneLine( marker_x, marker_y, marker_x + 3, marker_y );
+//                drawOneLine( bias_bar.x, marker_y, mid_scr.x, marker_y );
+//                }
+//              }
+            }
+          }
+        if( div_max()) {
+          if( (i%div_max()) == 0 )            {
+//            drawOneLine( marker_x,     marker_y,
+//                         marker_x + 6, marker_y );
+            if(modulo()) {
+              disp_val = i % modulo();
+              if( disp_val < 0) {
+                disp_val += modulo();
+                }
+              }
+            else {
+              disp_val = i;
+              }
+            sprintf( TextScale, "%d", disp_val );
+            if( orientation == ReadLEFT )              {
+              drawOneLine( mid_scr.x - 3, marker_y, bias_bar.x, marker_y );
+
+              textString( marker_x -  8 * strlen(TextScale) - 2, marker_y - 4,
+                          TextScale, GLUT_BITMAP_8_BY_13 );
+              }
+            else  {
+              drawOneLine( mid_scr.x + 3, marker_y, bias_bar.x, marker_y );
+              textString( marker_x + 10,                         marker_y - 4,
+                          TextScale, GLUT_BITMAP_8_BY_13 );
+              } // Else read oriented right
+            } // End if modulo division by major interval is zero
+          }  // End if major interval divisor non-zero
+        } // End if condition
+      } // End for range of i from vmin to vmax
+    }  // End if VERTICAL SCALE TYPE
+  else {                                // Horizontal scale by default
+    {
+    if( orientation == ReadTOP ) {
+      bias_bar.y = ((mid_scr.y - scrn_rect.bottom)>>1 ) + scrn_rect.bottom;
+      marker_y = bias_bar.y;  // Don't use now
+      }
+    else {  // We will assume no other possibility at this time.
+      bias_bar.y = ((scrn_rect.top - mid_scr.y)>>1 ) + mid_scr.y;
+      marker_y = bias_bar.y;  // Don't use now
+      }
+
+    drawOneLine( scrn_rect.left,
+                 bias_bar.y,
+                 scrn_rect.right,
+                 bias_bar.y );
+
+    if( orientation == ReadTOP )
+      {
+      drawOneLine( scrn_rect.left,
+                   bias_bar.y,
+                   scrn_rect.left,
+                   mid_scr.y);
+
+      drawOneLine( scrn_rect.right,
+                   bias_bar.y,
+                   scrn_rect.right,
+                   mid_scr.y );
+
+      drawOneLine( mid_scr.x,
+                   scrn_rect.bottom,
+                   mid_scr.x,
+                   bias_bar.y );
+
+      }
+    else {
+      if( orientation == ReadBOTTOM )
+        {
+        drawOneLine( scrn_rect.left,
+                     bias_bar.y,
+                     scrn_rect.left,
+                     mid_scr.y );
+
+        drawOneLine( scrn_rect.right,
+                     bias_bar.y,
+                     scrn_rect.right,
+                     mid_scr.y );
+
+        drawOneLine( mid_scr.x,
+                     scrn_rect.top,
+                     mid_scr.x,
+                     bias_bar.y );
+        }
+      }
+
+    for( i = (int)vmin; i <= (int)vmax; i++ )  // increment is faster than addition
+      {
+//      if( sub_type == LIMIT ) {
+        condition = (i >= min_val());
+//        }
+//      else {
+//        if( sub_type == NOLIMIT ) {
+//          condition = 1;
+//          }
+//        }
+      if( condition )        {
+        marker_x = scrn_rect.left + (int)((i - vmin) * factor());
+        if( div_min()){
+          if( (i%(int)div_min()) == 0 ) {
+//            if( orientation == ReadTOP )
+//              {
+//              drawOneLine( marker_x, marker_y, marker_x, marker_y + 3 );
+              drawOneLine( marker_x, bias_bar.y, marker_x, mid_scr.y );
+//              }
+//            else {
+//            drawOneLine( marker_x, marker_y + 3, marker_x, marker_y + 6 );
+//              drawOneLine( marker_x, bias_bar.y, marker_x, mid_scr.y );
+//              }
+            }
+           }
+        if( div_max()) {
+          if( (i%(int)div_max())==0 )
+            {
+            if(modulo()) {
+              disp_val = i % modulo();
+              if( disp_val < 0) {
+                disp_val += modulo();
+                }
+              }
+            else {
+              disp_val = i;
+              }
+              sprintf( TextScale, "%d", disp_val );
+            if( orientation == ReadTOP )
+              {
+//              drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
+              drawOneLine( marker_x, mid_scr.y + 3,marker_x, bias_bar.y );
+              textString ( marker_x - 4 * strlen(TextScale), marker_y + 14,
+                           TextScale, GLUT_BITMAP_8_BY_13 );
+              }
+            else {
+//            drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
+              drawOneLine( marker_x, mid_scr.y - 3,marker_x, bias_bar.y );
+              textString ( marker_x - 4 * strlen(TextScale), mid_scr.y - 14,
+                           TextScale, GLUT_BITMAP_8_BY_13 );
+              }
+            }
+          }  
+        }
+      }
+    }
+   }
+}
+
+//============== Top of guage_instr class member definitions ==============
+
+guage_instr ::
+    guage_instr( RECT         the_box,
+                 DBLFNPTR     load_fn,
+                 ReadOriented readway,
+                 int          maxValue,
+                 int          minValue,
+                 UINT         major_divs,
+                 UINT         minor_divs,
+                 UINT         modulus,
+                 bool         working) :
+           instr_scale( the_box,
+                        load_fn, readway,
+                        maxValue, maxValue, minValue,
+                        major_divs, minor_divs,
+                        modulus,
+                        working)
+{
+}
+
+guage_instr ::
+   ~guage_instr()
+{
+}
+
+guage_instr ::
+    guage_instr( const guage_instr & image):
+       instr_scale( (instr_scale &) image)
+{
+}
+
+guage_instr & guage_instr ::
+    operator = (const guage_instr & rhs )
+{
+  if( !(this == &rhs)) {
+    instr_scale::operator = (rhs);
+    }
+  return *this;
+}
+
+// As implemented, draw only correctly draws a horizontal or vertical
+// scale. It should contain a variation that permits clock type displays.
+// Now is supports "tickless" displays such as control surface indicators.
+// This routine should be worked over before using. Current value would be
+// fetched and not used if not commented out. Clearly that is intollerable.
+
+void guage_instr :: draw (void)
+{
+  int marker_x;
+  int marker_y;
+  register i;
+  char TextScale[80];
+//  int condition;
+  int disp_val;
+  double vmin              = min_val();
+  double vmax              = max_val();
+  POINT mid_scr            = get_centroid();
+//  double cur_value         = get_value();
+  RECT   scrn_rect         = get_location();
+  ReadOriented orientation = get_orientation();
+
+  if( (orientation == ReadLEFT) ||( orientation == ReadRIGHT))  // Vertical scale
+    {
+    mid_scr = get_centroid();
+    if( orientation == ReadLEFT )     // Calculate x marker offset
+      marker_x = scrn_rect.left - 6;
+    else                              // We'll default this for now.
+      marker_x = scrn_rect.right;
+
+    // Draw the basic markings for the scale...
+
+    if( orientation == ReadLEFT )
+      {
+
+      drawOneLine( scrn_rect.right - 3,     // Bottom tick bar
+                   scrn_rect.bottom,
+                   scrn_rect.right,
+                   scrn_rect.bottom );
+
+      drawOneLine( scrn_rect.right - 3,     // Top tick bar
+                   scrn_rect.top,
+                   scrn_rect.right,
+                   scrn_rect.top );
+      }
+    else       {
+      drawOneLine( scrn_rect.right,
+                   scrn_rect.bottom,
+                   scrn_rect.right+3,
+                   scrn_rect.bottom );
+
+      drawOneLine( scrn_rect.right,
+                   scrn_rect.top,
+                   scrn_rect.right+3,
+                   scrn_rect.top );
+      }
+
+    // Work through from bottom to top of scale. Calculating where to put
+    // minor and major ticks.
+
+    for( i = (int)vmin; i <= (int)vmax; i++ )
+      {
+        // Calculate the location of this tick
+      marker_y = scrn_rect.bottom + (int)((i - vmin) * factor());
+
+      if( div_min()) {
+        if( (i%div_min()) == 0) {
+          if( orientation == ReadLEFT )
             {
             drawOneLine( marker_x + 3, marker_y, marker_x + 6, marker_y );
             }
           else {
-            if( pscale->orientation == RIGHT )
-              {
-              drawOneLine( marker_x, marker_y, marker_x + 3, marker_y );
-              }
+            drawOneLine( marker_x, marker_y, marker_x + 3, marker_y );
             }
           }
-        if( (i%pscale->div_max) == 0 )            {
+        }
+      if( div_max()) {
+        if( (i%div_max()) == 0 )            {
           drawOneLine( marker_x,     marker_y,
                        marker_x + 6, marker_y );
-          if(pscale->modulo) {
-            disp_val = i % pscale->modulo;
-            if( !disp_val ) {
-              disp_val = pscale->modulo;
-              }
+          if(modulo()) {
+            disp_val = i % modulo();
             if( disp_val < 0) {
-              disp_val += pscale->modulo;
-              }
-            if( disp_val == pscale->modulo ) {
-              disp_val = 0;
+              disp_val += modulo();
               }
             }
           else {
             disp_val = i;
             }
           sprintf( TextScale, "%d", disp_val );
-          if( pscale->orientation == LEFT )              {
+          if( orientation == ReadLEFT )              {
             textString( marker_x -  8 * strlen(TextScale) - 2, marker_y - 4,
                         TextScale, GLUT_BITMAP_8_BY_13 );
             }
           else  {
-            if( pscale->orientation == RIGHT )              {
+            if( orientation == ReadRIGHT )              {
             textString( marker_x + 10,                         marker_y - 4,
                         TextScale, GLUT_BITMAP_8_BY_13 );
               }
@@ -422,353 +924,212 @@ static void drawscale( HUD_scale * pscale )
         } // End if condition
       } // End for range of i from vmin to vmax
     }  // End if VERTICAL SCALE TYPE
-  if( pscale->type == HORIZONTAL )     // Horizontal scale
+  else {                                // Horizontal scale by default
     {
-    if( pscale->orientation == TOP ) {
-      marker_y = pscale->scrn_pos.bottom;
+    if( orientation == ReadTOP ) {
+      marker_y = scrn_rect.bottom;
       }
     else {
-      if( pscale->orientation == BOTTOM ) {
-        marker_y = pscale->scrn_pos.bottom - 6;
+      if( orientation == ReadBOTTOM ) {
+        marker_y = scrn_rect.bottom - 6;
         }
       }
-    drawOneLine( pscale->scrn_pos.left,
-                 pscale->scrn_pos.bottom,
-                 pscale->scrn_pos.right,
-                 pscale->scrn_pos.bottom );
+    drawOneLine( scrn_rect.left,
+                 scrn_rect.bottom,
+                 scrn_rect.right,
+                 scrn_rect.bottom );
 
-    if( pscale->orientation == TOP )
+    if( orientation == ReadTOP )
       {
-      drawOneLine( pscale->scrn_pos.left,
-                   pscale->scrn_pos.bottom,
-                   pscale->scrn_pos.left,
-                   pscale->scrn_pos.bottom + 3 );
-
-      drawOneLine( pscale->scrn_pos.right,
-                   pscale->scrn_pos.bottom,
-                   pscale->scrn_pos.right,
-                   pscale->scrn_pos.bottom + 6 );
-
-      drawOneLine( pscale->mid_scr,
-                   pscale->scrn_pos.bottom,
-                   pscale->mid_scr,
-                   pscale->scrn_pos.bottom - 6 );
-
+      drawOneLine( scrn_rect.left,
+                   scrn_rect.bottom,
+                   scrn_rect.left,
+                   scrn_rect.bottom + 3 );
+
+      drawOneLine( scrn_rect.right,
+                   scrn_rect.bottom,
+                   scrn_rect.right,
+                   scrn_rect.bottom + 6 );
       }
     else {
-      if( pscale->orientation == BOTTOM )
+      if( orientation == ReadBOTTOM )
         {
-        drawOneLine( pscale->scrn_pos.left,
-                     pscale->scrn_pos.bottom,
-                     pscale->scrn_pos.left,
-                     pscale->scrn_pos.bottom - 6 );
-
-        drawOneLine( pscale->scrn_pos.right,
-                     pscale->scrn_pos.bottom,
-                     pscale->scrn_pos.right,
-                     pscale->scrn_pos.bottom - 6 );
-
-        drawOneLine( pscale->mid_scr,
-                     pscale->scrn_pos.bottom,
-                     pscale->mid_scr,
-                     pscale->scrn_pos.bottom + 6 );
+        drawOneLine( scrn_rect.left,
+                     scrn_rect.bottom,
+                     scrn_rect.left,
+                     scrn_rect.bottom - 6 );
+
+        drawOneLine( scrn_rect.right,
+                     scrn_rect.bottom,
+                     scrn_rect.right,
+                     scrn_rect.bottom - 6 );
         }
       }
 
-    for( i = (int)(vmin); i <= (int)(vmax); i++ )  // increment is faster than addition
+    for( i = (int)vmin; i <= (int)vmax; i++ )  // increment is faster than addition
       {
-      if( pscale->sub_type == LIMIT ) {
-        condition = (i >= pscale->minimum_value);
-        }
-      else {
-        if( pscale->sub_type == NOLIMIT ) {
-          condition = 1;
-          }
-        }
-      if( condition )        {
-        marker_x = (int)(pscale->scrn_pos.left + (i - vmin) * pscale->factor);
-        if( (i%pscale->div_min) == 0 ) {
-          if( pscale->orientation == TOP )
+      marker_x = scrn_rect.left + (int)((i - vmin) * factor());
+      if( div_min()) {
+        if( (i%div_min()) == 0 ) {
+          if( orientation == ReadTOP )
             {
             drawOneLine( marker_x, marker_y, marker_x, marker_y + 3 );
             }
           else {
-            if( pscale->orientation == BOTTOM )
+            if( orientation == ReadBOTTOM )
               {
               drawOneLine( marker_x, marker_y + 3, marker_x, marker_y + 6 );
               }
             }
-          }
-        if( (i%pscale->div_max)==0 )
+          }  // End if minor tick called for.
+        }  // End if minor ticks are of interest
+      if( div_max()) {
+        if( (i%div_max())==0 )
           {
-          if(pscale->modulo) {
-            disp_val = i % pscale->modulo;
-            if( !disp_val ) {
-              disp_val = pscale->modulo;
-              }
+          // Modulo implies a "clock" style instrument. Needs work.
+          if(modulo()) {
+            disp_val = i % modulo();
             if( disp_val < 0) {
-              disp_val += pscale->modulo;
-              }
-            if( disp_val == pscale->modulo ) {
-              disp_val = 0;
+              disp_val += modulo();
               }
             }
-          else {
+          else {   // Scale doesn't roll around.
             disp_val = i;
             }
             sprintf( TextScale, "%d", disp_val );
-          if( pscale->orientation == TOP )
+          if( orientation == ReadTOP )
             {
             drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
             textString ( marker_x - 4 * strlen(TextScale), marker_y + 14,
                          TextScale, GLUT_BITMAP_8_BY_13 );
             }
           else {
-            if( pscale->orientation == BOTTOM )
+            if( orientation == ReadBOTTOM )
               {
               drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
               textString ( marker_x - 4 * strlen(TextScale), marker_y - 14,
                            TextScale, GLUT_BITMAP_8_BY_13 );
-              }
-            }
-          }
-        }
+              } // End if bottom
+            } // End else if not ReadTOP
+          } // End if major division point.
+        } // End if major divisions of interest.
       }
     }
-
+   }
 }
 
-//
-//     Draws a climb ladder in the center of the HUD
-//
+//============ Top of dual_instr_item class member definitions ============
 
-static void drawladder( HUD_ladder *ladder )
+dual_instr_item ::
+  dual_instr_item ( RECT         the_box,
+                    DBLFNPTR     chn1_source,
+                    DBLFNPTR     chn2_source,
+                    bool         working,
+                    ReadOriented readway ):
+                  instr_item( the_box, chn1_source, readway, working),
+                  alt_data_source( chn2_source )
 {
-  double vmin, vmax;
-  double roll_value, pitch_value;
-  int marker_x, marker_y;
-#ifdef DEBUGHUD
-  int mid_scr;
-#endif
-  int scr_min, scr_max;
-  int x_ini, x_end;
-  int y_ini, y_end;
-  int new_x_ini, new_x_end;
-  int new_y_ini, new_y_end;
-  register i;
-  double factor;
-  char TextLadder[80];
-  int condition;
-
-  double cos_roll_value, sin_roll_value;
-//  double cos_pitch_value, sin_pitch_value;
-
-  roll_value = (*ladder->load_roll)();
-  sin_roll_value = sin(roll_value);
-  cos_roll_value = cos(roll_value);
-  
-  pitch_value = (*ladder->load_pitch)()*RAD_TO_DEG;
+}
 
-  vmin = pitch_value - ladder->width_units/2;
-  vmax = pitch_value + ladder->width_units/2;
+dual_instr_item ::
+  dual_instr_item( const dual_instr_item & image) :
+                 instr_item ((instr_item &) image ),
+                 alt_data_source( image.alt_data_source)
+{
+}
 
-  scr_min = ladder->scrn_pos.y - (ladder->scr_height/2);
-  scr_max = scr_min       + ladder->scr_height;
+dual_instr_item & dual_instr_item ::
+  operator = (const dual_instr_item & rhs )
+{
+  if( !(this == &rhs)) {
+    instr_item::operator = (rhs);
+    alt_data_source = rhs.alt_data_source;
+    }
+  return *this;
+}
 
-#ifdef DEBUGHUD
-  mid_scr = scr_min       + (scr_max-scr_min)/2;
-#endif
+//============ Top of fgTBI_instr class member definitions ==============
+
+fgTBI_instr ::
+fgTBI_instr( RECT      the_box,
+             DBLFNPTR  chn1_source,
+             DBLFNPTR  chn2_source,
+             UINT      maxBankAngle,
+             UINT      maxSlipAngle,
+             UINT      gap_width,
+             bool      working ) :
+               dual_instr_item( the_box,
+                                chn1_source,
+                                chn2_source,
+                                working,
+                                ReadTOP),
+               BankLimit      (maxBankAngle),
+               SlewLimit      (maxSlipAngle),
+               scr_hole       (gap_width   )
+{
+}
 
-  marker_x = ladder->scrn_pos.x - ladder->scr_width/2;
+fgTBI_instr :: ~fgTBI_instr() {}
 
-  factor = (scr_max-scr_min)/ladder->width_units;
+fgTBI_instr :: fgTBI_instr( const fgTBI_instr & image):
+                 dual_instr_item( (const dual_instr_item &) image),
+                 BankLimit( image.BankLimit),
+                 SlewLimit( image.SlewLimit),
+                 scr_hole ( image.scr_hole )
+{
+}
 
-  for( i=(int)(vmin); i<=(int)(vmax); i+=1 )
-    {
-    condition = 1;
-    if( condition )
-      {
-      marker_y = (int)(scr_min+(i-vmin)*factor);
-      if( i%ladder->div_units==0 )
-        {
-        sprintf( TextLadder, "%d", i );
-        if( ladder->scr_hole == 0 )
-          {
-          if( i ) {
-            x_ini = ladder->scrn_pos.x - ladder->scr_width/2;
-            }
-          else {
-            x_ini = ladder->scrn_pos.x - ladder->scr_width/2 - 10;
-            }
-          y_ini = marker_y;
-          x_end = ladder->scrn_pos.x + ladder->scr_width/2;
-          y_end = marker_y;
-          new_x_ini = (int)(ladder->scrn_pos.x +                             \
-                      (x_ini - ladder->scrn_pos.x) * cos_roll_value - \
-                      (y_ini - ladder->scrn_pos.y) * sin_roll_value);
-          new_y_ini = (int)(ladder->scrn_pos.y +                             \
-                      (x_ini - ladder->scrn_pos.x) * sin_roll_value + \
-                      (y_ini - ladder->scrn_pos.y) * cos_roll_value);
-          new_x_end = (int)(ladder->scrn_pos.x +                             \
-                      (x_end - ladder->scrn_pos.x) * cos_roll_value - \
-                      (y_end - ladder->scrn_pos.y) * sin_roll_value);
-          new_y_end = (int)(ladder->scrn_pos.y +                             \
-                      (x_end - ladder->scrn_pos.x) * sin_roll_value + \
-                      (y_end - ladder->scrn_pos.y) * cos_roll_value);
-
-          if( i >= 0 )
-            {
-            drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
-            }
-          else
-            {
-            glEnable(GL_LINE_STIPPLE);
-            glLineStipple( 1, 0x00FF );
-            drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
-            glDisable(GL_LINE_STIPPLE);
-            }
-          textString( new_x_ini -  8 * strlen(TextLadder) - 8,
-                      new_y_ini -  4,
-                      TextLadder, GLUT_BITMAP_8_BY_13 );
-          textString( new_x_end + 10,
-                      new_y_end -  4,
-                      TextLadder, GLUT_BITMAP_8_BY_13 );
-          }
-        else
-          {
-          if( i != 0 )  {
-            x_ini = ladder->scrn_pos.x - ladder->scr_width/2;
-            }
-          else          {
-            x_ini = ladder->scrn_pos.x - ladder->scr_width/2 - 10;
-            }
-          y_ini = marker_y;
-          x_end = ladder->scrn_pos.x - ladder->scr_width/2 + ladder->scr_hole/2;
-          y_end = marker_y;
-          new_x_ini = (int)(ladder->scrn_pos.x+                             \
-                      (x_ini - ladder->scrn_pos.x) * cos_roll_value -\
-                      (y_ini - ladder->scrn_pos.y) * sin_roll_value);
-          new_y_ini = (int)(ladder->scrn_pos.y+                             \
-                      (x_ini - ladder->scrn_pos.x) * sin_roll_value +\
-                      (y_ini - ladder->scrn_pos.y) * cos_roll_value);
-          new_x_end = (int)(ladder->scrn_pos.x+                             \
-                      (x_end - ladder->scrn_pos.x) * cos_roll_value -\
-                      (y_end - ladder->scrn_pos.y) * sin_roll_value);
-          new_y_end = (int)(ladder->scrn_pos.y+                             \
-                      (x_end - ladder->scrn_pos.x) * sin_roll_value +\
-                      (y_end - ladder->scrn_pos.y) * cos_roll_value);
-
-          if( i >= 0 )
-            {
-            drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
-            }
-          else
-            {
-            glEnable(GL_LINE_STIPPLE);
-            glLineStipple( 1, 0x00FF );
-            drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
-            glDisable(GL_LINE_STIPPLE);
-            }
-          textString( new_x_ini - 8 * strlen(TextLadder) - 8,
-                      new_y_ini - 4,
-                      TextLadder, GLUT_BITMAP_8_BY_13 );
-
-          x_ini = ladder->scrn_pos.x + ladder->scr_width/2 - ladder->scr_hole/2;
-          y_ini = marker_y;
-          if( i != 0 )  {
-            x_end = ladder->scrn_pos.x + ladder->scr_width/2;
-            }
-          else          {
-            x_end = ladder->scrn_pos.x + ladder->scr_width/2 + 10;
-            }
-          y_end = marker_y;
-          new_x_ini = (int)(ladder->scrn_pos.x +                        \
-                      (x_ini-ladder->scrn_pos.x)*cos_roll_value -\
-                      (y_ini-ladder->scrn_pos.y)*sin_roll_value);
-          new_y_ini = (int)(ladder->scrn_pos.y +                        \
-                      (x_ini-ladder->scrn_pos.x)*sin_roll_value +\
-                      (y_ini-ladder->scrn_pos.y)*cos_roll_value);
-          new_x_end = (int)(ladder->scrn_pos.x +                        \
-                      (x_end-ladder->scrn_pos.x)*cos_roll_value -\
-                     (y_end-ladder->scrn_pos.y)*sin_roll_value);
-          new_y_end = (int)(ladder->scrn_pos.y +                        \
-                      (x_end-ladder->scrn_pos.x)*sin_roll_value +\
-                      (y_end-ladder->scrn_pos.y)*cos_roll_value);
-
-          if( i >= 0 )
-            {
-            drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
-            }
-          else
-            {
-            glEnable(GL_LINE_STIPPLE);
-            glLineStipple( 1, 0x00FF );
-            drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
-            glDisable(GL_LINE_STIPPLE);
-            }
-          textString( new_x_end+10, new_y_end-4,
-                      TextLadder, GLUT_BITMAP_8_BY_13 );
-          }
-        }
-            /* if( i%pscale->div_max==0 )
-            {
-               drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
-                sprintf( TextScale, "%d", i );
-                if( pscale->orientation == LEFT )
-                {
-                       textString( marker_x-8*strlen(TextScale)-2, marker_y-4,
-                              TextScale, GLUT_BITMAP_8_BY_13 );
-                }
-                else if( pscale->orientation == RIGHT )
-                {
-                       textString( marker_x+10, marker_y-4,
-                              TextScale, GLUT_BITMAP_8_BY_13 );
-                }
-            } */
-        }
+fgTBI_instr & fgTBI_instr ::
+operator = (const fgTBI_instr & rhs )
+{
+  if( !(this == &rhs)) {
+    dual_instr_item::operator = (rhs);
+    BankLimit = rhs.BankLimit;
+    SlewLimit = rhs.SlewLimit;
+    scr_hole  = rhs.scr_hole;
     }
-
+   return *this;
 }
 
 //
-//     Draws an artificial horizon line in the center of the HUD
-//     (with or without a center hole)
-//
-//     Needs: x_center, y_center, length, hole
+//     Draws a Turn Bank Indicator on the screen
 //
 
-static void drawhorizon( HUD_horizon *horizon )
+ void fgTBI_instr :: draw( void )
 {
   int x_inc1, y_inc1;
   int x_inc2, y_inc2;
   int x_t_inc1, y_t_inc1;
-  
+
   int d_bottom_x, d_bottom_y;
   int d_right_x, d_right_y;
   int d_top_x, d_top_y;
   int d_left_x, d_left_y;
-  
+
   int inc_b_x, inc_b_y;
   int inc_r_x, inc_r_y;
   int inc_t_x, inc_t_y;
   int inc_l_x, inc_l_y;
+  RECT My_box = get_location();
+  POINT centroid = get_centroid();
+  int tee_height = My_box.top - My_box.bottom; // Hack, hack.
   
 //     struct fgFLIGHT *f = &current_aircraft.flight;
   double sin_bank, cos_bank;
   double bank_angle, sideslip_angle;
   double ss_const; // sideslip angle pixels per rad
 
-  bank_angle     = (*horizon->load_roll)();     // Roll limit +/- 30 degrees
+  bank_angle     = current_ch2();  // Roll limit +/- 30 degrees
   if( bank_angle < -FG_PI_2/3 ) {
     bank_angle = -FG_PI_2/3;
   }else if( bank_angle > FG_PI_2/3 ) {
     bank_angle = FG_PI_2/3;
   }
-  sideslip_angle = (*horizon->load_sideslip)(); // Sideslip limit +/- 5 degrees
-  if( sideslip_angle < -FG_PI/36.0 ) {
-    sideslip_angle = -FG_PI/36.0;
-  } else if( sideslip_angle > FG_PI/36.0 ) {
-    sideslip_angle = FG_PI/36.0;
+  sideslip_angle = current_ch1(); // Sideslip limit +/- 20 degrees
+  if( sideslip_angle < -FG_PI/9 ) {
+    sideslip_angle = -FG_PI/9;
+  } else if( sideslip_angle > FG_PI/9 ) {
+    sideslip_angle = FG_PI/9;
   }
 
        // sin_bank = sin( FG_2PI-FG_Phi );
@@ -776,24 +1137,24 @@ static void drawhorizon( HUD_horizon *horizon )
   sin_bank = sin(FG_2PI-bank_angle);
   cos_bank = cos(FG_2PI-bank_angle);
   
-  x_inc1 = (int)(horizon->scr_width * cos_bank);
-  y_inc1 = (int)(horizon->scr_width * sin_bank);
-  x_inc2 = (int)(horizon->scr_hole  * cos_bank);
-  y_inc2 = (int)(horizon->scr_hole  * sin_bank);
+  x_inc1 = (int)(get_span() * cos_bank);
+  y_inc1 = (int)(get_span() * sin_bank);
+  x_inc2 = (int)(scr_hole  * cos_bank);
+  y_inc2 = (int)(scr_hole  * sin_bank);
 
-  x_t_inc1 = (int)(horizon->tee_height * sin_bank);
-  y_t_inc1 = (int)(horizon->tee_height * cos_bank);
+  x_t_inc1 = (int)(tee_height * sin_bank);
+  y_t_inc1 = (int)(tee_height * cos_bank);
   
   d_bottom_x = 0;
-  d_bottom_y = (int)(-horizon->scr_hole);
-  d_right_x  = (int)(horizon->scr_hole);
+  d_bottom_y = (int)(-scr_hole);
+  d_right_x  = (int)(scr_hole);
   d_right_y  = 0;
   d_top_x    = 0;
-  d_top_y    = (int)(horizon->scr_hole);
-  d_left_x   = (int)(-horizon->scr_hole);
+  d_top_y    = (int)(scr_hole);
+  d_left_x   = (int)(-scr_hole);
   d_left_y   = 0;
-  
-  ss_const = (horizon->scr_width*2)/(FG_2PI/36.0);// width represents 10 degrees
+
+  ss_const = (get_span()*2)/(FG_2PI/9);  // width represents 40 degrees
 
   d_bottom_x += (int)(sideslip_angle*ss_const);
   d_right_x  += (int)(sideslip_angle*ss_const);
@@ -808,233 +1169,301 @@ static void drawhorizon( HUD_horizon *horizon )
   inc_t_y = (int)(d_top_x*sin_bank+d_top_y*cos_bank);
   inc_l_x = (int)(d_left_x*cos_bank-d_left_y*sin_bank);
   inc_l_y = (int)(d_left_x*sin_bank+d_left_y*cos_bank);
-  
-  if( horizon->scr_hole == 0 )
+
+  if( scr_hole == 0 )
     {
-    drawOneLine( horizon->scrn_pos.x - x_inc1, horizon->scrn_pos.y - y_inc1, \
-                 horizon->scrn_pos.x + x_inc1, horizon->scrn_pos.y + y_inc1 );
+    drawOneLine( centroid.x - x_inc1, centroid.y - y_inc1, \
+                 centroid.x + x_inc1, centroid.y + y_inc1 );
     }
   else
     {
-    drawOneLine( horizon->scrn_pos.x - x_inc1, horizon->scrn_pos.y - y_inc1, \
-                 horizon->scrn_pos.x - x_inc2, horizon->scrn_pos.y - y_inc2 );
-    drawOneLine( horizon->scrn_pos.x + x_inc2, horizon->scrn_pos.y + y_inc2, \
-                 horizon->scrn_pos.x + x_inc1, horizon->scrn_pos.y + y_inc1 );
+    drawOneLine( centroid.x - x_inc1, centroid.y - y_inc1, \
+                 centroid.x - x_inc2, centroid.y - y_inc2 );
+    drawOneLine( centroid.x + x_inc2, centroid.y + y_inc2, \
+                 centroid.x + x_inc1, centroid.y + y_inc1 );
     }
 
-  // draw teemarks (?)
-  drawOneLine( horizon->scrn_pos.x + x_inc2, horizon->scrn_pos.y + y_inc2, \
-               horizon->scrn_pos.x + x_inc2 + x_t_inc1, horizon->scrn_pos.y + y_inc2 - y_t_inc1 );
-  drawOneLine( horizon->scrn_pos.x - x_inc2, horizon->scrn_pos.y - y_inc2, \
-               horizon->scrn_pos.x - x_inc2 + x_t_inc1, horizon->scrn_pos.y - y_inc2 - y_t_inc1 );
+  // draw teemarks
+  drawOneLine( centroid.x + x_inc2,            \
+                 centroid.y + y_inc2,          \
+               centroid.x + x_inc2 + x_t_inc1, \
+                 centroid.y + y_inc2 - y_t_inc1 );
+  drawOneLine( centroid.x - x_inc2,            \
+                 centroid.y - y_inc2,          \
+               centroid.x - x_inc2 + x_t_inc1, \
+                 centroid.y - y_inc2 - y_t_inc1 );
                
   // draw sideslip diamond (it is not yet positioned correctly )
-  drawOneLine( horizon->scrn_pos.x + inc_b_x, \
-               horizon->scrn_pos.y + inc_b_y, \
-               horizon->scrn_pos.x + inc_r_x, \
-               horizon->scrn_pos.y + inc_r_y )
-  drawOneLine( horizon->scrn_pos.x + inc_r_x, \
-               horizon->scrn_pos.y + inc_r_y, \
-               horizon->scrn_pos.x + inc_t_x, \
-               horizon->scrn_pos.y + inc_t_y );
-  drawOneLine( horizon->scrn_pos.x + inc_t_x, \
-               horizon->scrn_pos.y + inc_t_y, \
-               horizon->scrn_pos.x + inc_l_x, \
-               horizon->scrn_pos.y + inc_l_y );
-  drawOneLine( horizon->scrn_pos.x + inc_l_x, \
-               horizon->scrn_pos.y + inc_l_y, \
-               horizon->scrn_pos.x + inc_b_x, \
-               horizon->scrn_pos.y + inc_b_y );
-  
-  /* drawOneLine( horizon->scrn_pos.x + inc_b_x, \
-               horizon->scrn_pos.y + inc_b_y, \
-               horizon->scrn_pos.x + inc_r_x, \
-               horizon->scrn_pos.y + inc_r_y )
-  drawOneLine( horizon->scrn_pos.x + inc_r_x, \
-               horizon->scrn_pos.y + inc_r_y, \
-               horizon->scrn_pos.x + inc_t_x, \
-               horizon->scrn_pos.y + inc_t_y );
-  drawOneLine( horizon->scrn_pos.x + inc_t_x, \
-               horizon->scrn_pos.y + inc_t_y, \
-               horizon->scrn_pos.x + inc_l_x, \
-               horizon->scrn_pos.y + inc_l_y );
-  drawOneLine( horizon->scrn_pos.x + inc_l_x, \
-               horizon->scrn_pos.y + inc_l_y, \
-               horizon->scrn_pos.x + inc_b_x, \
-               horizon->scrn_pos.y + inc_b_y ); */
-}
+  drawOneLine( centroid.x + inc_b_x, \
+               centroid.y + inc_b_y, \
+               centroid.x + inc_r_x, \
+               centroid.y + inc_r_y );
+  drawOneLine( centroid.x + inc_r_x, \
+               centroid.y + inc_r_y, \
+               centroid.x + inc_t_x, \
+               centroid.y + inc_t_y );
+  drawOneLine( centroid.x + inc_t_x, \
+               centroid.y + inc_t_y, \
+               centroid.x + inc_l_x, \
+               centroid.y + inc_l_y );
+  drawOneLine( centroid.x + inc_l_x, \
+               centroid.y + inc_l_y, \
+               centroid.x + inc_b_x, \
+               centroid.y + inc_b_y );
 
-//  drawControlSurfaces()
-//     Draws a representation of the control surfaces in their current state
-//     anywhere in the HUD
-//
+}
 
-static void drawControlSurfaces( HUD_control_surfaces *ctrl_surf )
+//====================== Top of HudLadder Class =======================
+HudLadder ::
+  HudLadder(  RECT      the_box,
+              DBLFNPTR  ptch_source,
+              DBLFNPTR  roll_source,
+              UINT      span_units,
+              int       major_div,
+              UINT      minor_div,
+              UINT      screen_hole,
+              UINT      lbl_pos,
+              bool      working) :
+               dual_instr_item( the_box,
+                                ptch_source,
+                                roll_source,
+                                working,
+                                ReadRIGHT ),
+               width_units    ( span_units   ),
+               div_units      ( major_div < 0? -major_div: major_div ),
+               minor_div      ( minor_div    ),
+               label_pos      ( lbl_pos      ),
+               scr_hole       ( screen_hole  ),
+               vmax           ( span_units/2 ),
+               vmin           ( -vmax        )
 {
-       int x_ini, y_ini;
-       int x_end, y_end;
-       /* int x_1, y_1; */
-       /* int x_2, y_2; */
-       fgCONTROLS *pCtls;
-       int tmp;
-
-       x_ini = ctrl_surf->scrn_pos.x;
-       y_ini = ctrl_surf->scrn_pos.y;
-       x_end = x_ini + 150;
-       y_end = y_ini + 60;
-
-       drawOneLine( x_ini, y_ini, x_end, y_ini );
-       drawOneLine( x_ini, y_ini, x_ini, y_end );
-       drawOneLine( x_ini, y_end, x_end, y_end );
-       drawOneLine( x_end, y_end, x_end, y_ini );
-       drawOneLine( x_ini + 30, y_ini, x_ini + 30, y_end );
-       drawOneLine( x_ini + 30, y_ini + 30, x_ini + 90, y_ini + 30 );
-       drawOneLine( x_ini + 90, y_ini, x_ini + 90, y_end );
-       drawOneLine( x_ini + 120, y_ini, x_ini + 120, y_end );
-
-       pCtls = current_aircraft.controls;
-
-       /* Draw elevator diagram */
-       textString( x_ini + 1, y_end-11, "E", GLUT_BITMAP_8_BY_13 );
-       drawOneLine( x_ini + 15, y_ini + 5, x_ini + 15, y_ini + 55 );
-       drawOneLine( x_ini + 14, y_ini + 30, x_ini + 16, y_ini + 30 );
-       tmp = y_ini + 5 + (int)(((pCtls->elevator + 1.0)/2)*50.0);
-       if( pCtls->elevator <= -0.01 || pCtls->elevator >= 0.01 )
-       {
-               drawOneLine( x_ini + 10, tmp, x_ini + 20, tmp );
-       }
-       else
-       {
-               drawOneLine( x_ini + 7, tmp, x_ini + 23, tmp);
-       }
-
-       /* Draw aileron diagram */
-       textString( x_ini + 30 + 1, y_end-11, "A", GLUT_BITMAP_8_BY_13 );
-       drawOneLine( x_ini + 35, y_end-15, x_ini + 85, y_end-15 );
-       drawOneLine( x_ini + 60, y_end-14, x_ini + 60, y_end-16 );
-       tmp = x_ini + 35 + (int)(((pCtls->aileron + 1.0)/2)*50.0);
-       if( pCtls->aileron <= -0.01 || pCtls->aileron >= 0.01 )
-       {
-               drawOneLine( tmp, y_end-20, tmp, y_end-10 );
-       }
-       else
-       {
-               drawOneLine( tmp, y_end - 25, tmp, y_end -  5 );
-       }
-
-       /* Draw rudder diagram */
-       textString ( x_ini + 30 + 1, y_ini + 21, "R", GLUT_BITMAP_8_BY_13 );
-       drawOneLine( x_ini + 35, y_ini + 15, x_ini + 85, y_ini + 15 );
-       drawOneLine( x_ini + 60, y_ini + 14, x_ini + 60, y_ini + 16 );
-
-       tmp = x_ini + 35 + (int)(((pCtls->rudder + 1.0) / 2) * 50.0);
-       if( pCtls->rudder <= -0.01 || pCtls->rudder >= 0.01 )
-       {
-               drawOneLine( tmp, y_ini + 20, tmp, y_ini + 10 );
-       }
-       else
-       {
-               drawOneLine( tmp, y_ini + 25, tmp, y_ini +  5 );
-       }
-
-
-       /* Draw throttle diagram */
-       textString( x_ini + 90 + 1, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
-       textString( x_ini + 90 + 1, y_end-21, "r", GLUT_BITMAP_8_BY_13 );
-       drawOneLine( x_ini + 105, y_ini + 5, x_ini + 105, y_ini + 55 );
-       tmp = y_ini + 5 + (int)(pCtls->throttle[0]*50.0);
-       drawOneLine( x_ini + 100, tmp, x_ini + 110, tmp);
-
-
-       /* Draw elevator trim diagram */
-       textString( x_ini + 121, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
-       textString( x_ini + 121, y_end-22, "m", GLUT_BITMAP_8_BY_13 );
-       drawOneLine( x_ini + 135, y_ini + 5, x_ini + 135, y_ini + 55 );
-       drawOneLine( x_ini + 134, y_ini + 30, x_ini + 136, y_ini + 30 );
+  if( !width_units ) {
+    width_units = 45;
+    }
+  factor = (double)get_span() / (double) width_units;
+}
 
-       tmp = y_ini + 5 + (int)(((pCtls->elevator_trim + 1)/2)*50.0);
-       if( pCtls->elevator_trim <= -0.01 || pCtls->elevator_trim >= 0.01 )
-       {
-               drawOneLine( x_ini + 130, tmp, x_ini + 140, tmp);
-       }
-       else
-       {
-               drawOneLine( x_ini + 127, tmp, x_ini + 143, tmp);
-       }
+HudLadder ::
+  ~HudLadder()
+{
+}
 
+HudLadder ::
+  HudLadder( const HudLadder & image ) :
+        dual_instr_item( (dual_instr_item &) image),
+        width_units    ( image.width_units   ),
+        div_units      ( image.div_units     ),
+        label_pos      ( image.label_pos     ),
+        scr_hole       ( image.scr_hole      ),
+        vmax           ( image.vmax ),
+        vmin           ( image.vmin ),
+        factor         ( image.factor        )
+{
+}
+HudLadder & HudLadder ::
+  operator = ( const HudLadder & rhs )
+{
+  if( !(this == &rhs)) {
+    (dual_instr_item &)(*this) = (dual_instr_item &)rhs;
+    width_units  = rhs.width_units;
+    div_units    = rhs.div_units;
+    label_pos    = rhs.label_pos;
+    scr_hole     = rhs.scr_hole;
+    vmax         = rhs.vmax;
+    vmin         = rhs.vmin;
+    factor       = rhs.factor;
+    }
+  return *this;
 }
 
 //
-// Draws a label anywhere in the HUD
-//
+//     Draws a climb ladder in the center of the HUD
 //
 
-static void drawlabel( HUD_label *label )
+void HudLadder :: draw( void )
 {
-  char buffer[80];
-  char string[80];
-  int posincr;
-  int lenstr;
+  double roll_value, pitch_value;
+//  int marker_x;
+  int marker_y;
+  int scr_min;
+//  int scr_max;
+  int x_ini, x_end;
+  int y_ini, y_end;
+  int new_x_ini, new_x_end;
+  int new_y_ini, new_y_end;
+  register i;
+  POINT centroid = get_centroid();
+  RECT  box      = get_location();
+  int half_span  = (box.right - box.left) >> 1;
+  char TextLadder[80];
+  int condition;
 
-  if( !label ) { // Eliminate the possible, but absurd case.
-    return;
-    }
+  roll_value  = current_ch2();
+  pitch_value = current_ch1() * RAD_TO_DEG;
 
-  if( label->pre_str != NULL) {
-    if( label->post_str != NULL ) {
-      sprintf( buffer, "%s%s%s", label->pre_str,  \
-                                 label->format,   \
-                                 label->post_str );
-      }
-    else {
-      sprintf( buffer, "%s%s",   label->pre_str, \
-                                 label->format );
-      }
-    }
-  else {
-    if( label->post_str != NULL ) {
-      sprintf( buffer, "%s%s",   label->format,  \
-                                 label->post_str );
-      }
-    } // else do nothing if both pre and post strings are nulls. Interesting.
+  vmin        = (int)pitch_value - (double)width_units/2.0;
+  vmax        = (int)pitch_value + (double)width_units/2.0;
 
+  scr_min     = box.bottom; // centroid.y - ((box.top - box.bottom) >> 1);
+//  scr_max     = box.top;    // scr_min    + (box.top - box.bottom);
+//  marker_x    = centroid.x - half_span;
 
-  sprintf( string, buffer, (*label->load_value)() );
-#ifdef DEBUGHUD
-       fgPrintf( FG_COCKPIT, FG_DEBUG,  buffer );
-       fgPrintf( FG_COCKPIT, FG_DEBUG,  "\n" );
-       fgPrintf( FG_COCKPIT, FG_DEBUG, string );
-       fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
-#endif
-  lenstr = strlen( string );
-  if( label->justify == LEFT_JUST ) {
-   posincr = -lenstr*8;
-   }
-  else {
-    if( label->justify == CENTER_JUST ) {
-      posincr = -lenstr*4;
-      }
-    else {
-      if( label->justify == RIGHT_JUST ) {
-        posincr = 0;
+// Box the target.
+  drawOneLine( centroid.x - 5, centroid.y,     centroid.x,     centroid.y + 5);
+  drawOneLine( centroid.x,     centroid.y + 5, centroid.x + 5, centroid.y);
+  drawOneLine( centroid.x + 5, centroid.y,     centroid.x,     centroid.y - 5);
+  drawOneLine( centroid.x,     centroid.y - 5, centroid.x - 5, centroid.y);
+
+  for( i=(int)vmin; i<=(int)vmax; i+=1 )
+    {
+    condition = 1;
+    if( condition )
+      {
+      marker_y = scr_min + (int)((i-vmin)*factor);
+      if( div_units ) {
+        if( i%div_units==0 )
+          {
+          sprintf( TextLadder, "%d", i );
+          if( scr_hole == 0 )
+            {
+            if( i ) {
+              x_ini = centroid.x - half_span;
+              }
+            else {
+              x_ini = centroid.x - half_span - 10;
+              }
+            y_ini = marker_y;
+            x_end = centroid.x + half_span;
+            y_end = marker_y;
+            new_x_ini = centroid.x + (int)(                     \
+                       (x_ini - centroid.x) * cos(roll_value) - \
+                       (y_ini - centroid.y) * sin(roll_value));
+            new_y_ini = centroid.y + (int)(                     \
+                       (x_ini - centroid.x) * sin(roll_value) + \
+                       (y_ini - centroid.y) * cos(roll_value));
+            new_x_end = centroid.x + (int)(                       \
+                       (x_end - centroid.x) * cos(roll_value) - \
+                       (y_end - centroid.y) * sin(roll_value));
+            new_y_end = centroid.y + (int)(                            \
+                       (x_end - centroid.x) * sin(roll_value) + \
+                       (y_end - centroid.y) * cos(roll_value));
+
+            if( i >= 0 )
+              {
+              drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
+              }
+            else
+              {
+              glEnable(GL_LINE_STIPPLE);
+              glLineStipple( 1, 0x00FF );
+              drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
+              glDisable(GL_LINE_STIPPLE);
+              }
+            textString( new_x_ini -  8 * strlen(TextLadder) - 8,
+                        new_y_ini -  4,
+                        TextLadder, GLUT_BITMAP_8_BY_13 );
+            textString( new_x_end + 10,
+                        new_y_end -  4,
+                        TextLadder, GLUT_BITMAP_8_BY_13 );
+            }
+          else
+            {
+            if( i != 0 )  {
+              x_ini = centroid.x - half_span;
+              }
+            else          {
+              x_ini = centroid.x - half_span - 10;
+              }
+            y_ini = marker_y;
+            x_end = centroid.x - half_span + scr_hole/2;
+            y_end = marker_y;
+            new_x_ini = centroid.x+ (int)(                      \
+                        (x_ini - centroid.x) * cos(roll_value) -\
+                        (y_ini - centroid.y) * sin(roll_value));
+            new_y_ini = centroid.y+  (int)(                     \
+                        (x_ini - centroid.x) * sin(roll_value) +\
+                        (y_ini - centroid.y) * cos(roll_value));
+            new_x_end = centroid.x+  (int)(                     \
+                        (x_end - centroid.x) * cos(roll_value) -\
+                        (y_end - centroid.y) * sin(roll_value));
+            new_y_end = centroid.y+ (int)(                      \
+                        (x_end - centroid.x) * sin(roll_value) +\
+                        (y_end - centroid.y) * cos(roll_value));
+
+            if( i >= 0 )
+              {
+              drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
+              }
+            else
+              {
+              glEnable(GL_LINE_STIPPLE);
+              glLineStipple( 1, 0x00FF );
+              drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
+              glDisable(GL_LINE_STIPPLE);
+              }
+            textString( new_x_ini - 8 * strlen(TextLadder) - 8,
+                        new_y_ini - 4,
+                        TextLadder, GLUT_BITMAP_8_BY_13 );
+
+            x_ini = centroid.x + half_span - scr_hole/2;
+            y_ini = marker_y;
+            if( i != 0 )  {
+              x_end = centroid.x + half_span;
+              }
+            else          {
+              x_end = centroid.x + half_span + 10;
+              }
+            y_end = marker_y;
+            new_x_ini = centroid.x + (int)(                 \
+                        (x_ini-centroid.x)*cos(roll_value) -\
+                        (y_ini-centroid.y)*sin(roll_value));
+            new_y_ini = centroid.y + (int)(                 \
+                        (x_ini-centroid.x)*sin(roll_value) +\
+                        (y_ini-centroid.y)*cos(roll_value));
+            new_x_end = centroid.x + (int)(                 \
+                        (x_end-centroid.x)*cos(roll_value) -\
+                        (y_end-centroid.y)*sin(roll_value));
+            new_y_end = centroid.y +  (int)(                  \
+                        (x_end-centroid.x)*sin(roll_value) +\
+                        (y_end-centroid.y)*cos(roll_value));
+
+            if( i >= 0 )
+              {
+              drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
+              }
+            else
+              {
+              glEnable(GL_LINE_STIPPLE);
+              glLineStipple( 1, 0x00FF );
+              drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
+              glDisable(GL_LINE_STIPPLE);
+              }
+            textString( new_x_end+10, new_y_end-4,
+                        TextLadder, GLUT_BITMAP_8_BY_13 );
+            }
+          }
+         }
+            /* if( i%div_max()==0 )
+            {
+               drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
+                sprintf( TextScale, "%d", i );
+                if( orientation == LEFT )
+                {
+                       textString( marker_x-8*strlen(TextScale)-2, marker_y-4,
+                              TextScale, GLUT_BITMAP_8_BY_13 );
+                }
+                else if( orientation == RIGHT )
+                {
+                       textString( marker_x+10, marker_y-4,
+                              TextScale, GLUT_BITMAP_8_BY_13 );
+                }
+            } */
         }
-      }
     }
 
-  if( label->size == SMALL ) {
-    textString( label->scrn_pos.x + posincr, label->scrn_pos.y,
-                string, GLUT_BITMAP_8_BY_13);
-    }
-  else  {
-    if( label->size == LARGE ) {
-      textString( label->scrn_pos.x + posincr, label->scrn_pos.y,
-                  string, GLUT_BITMAP_9_BY_15);
-      }
-    }
 }
-// The following routines concern HUD object/component object construction
-//
 
+//========================= End of Class Implementations===================
 // fgHUDInit
 //
 // Constructs a HUD object and then adds in instruments. At the present
@@ -1043,460 +1472,317 @@ static void drawlabel( HUD_label *label )
 // display for a Piper Cub doesn't show the speed range of a North American
 // mustange and the engine readouts of a B36!
 //
-Hptr fgHUDInit( fgAIRCRAFT *current_aircraft )
+
+#define INSTRDEFS 15
+
+int fgHUDInit( fgAIRCRAFT * /* current_aircraft */ )
 {
-  Hptr hud;
+  instr_item *HIptr;
+  int index;
+  RECT loc;
 
-  fgPrintf( FG_COCKPIT, FG_INFO, "Initializing HUD\n" );
+  fgPrintf( FG_COCKPIT, FG_INFO, "Initializing current aircraft HUD\n" );
 
-  hud = (Hptr)calloc(sizeof( HUD),1);
-  if( hud == NULL )
-    return( NULL );
+  HUD_deque.erase( HUD_deque.begin(), HUD_deque.end());  // empty the HUD deque
 
-  hud->code = 1;
-  hud->status = 0;
+//  hud->code = 1;
+//  hud->status = 0;
 
   // For now lets just hardcode the hud here.
   // In the future, hud information has to come from the same place
   // aircraft information came from.
 
-  fgHUDSetTimeMode( hud, NIGHT );
-  fgHUDSetBrightness( hud, BRT_LIGHT );
-
-     // TBI
-  fgHUDAddHorizon( hud, 330, 100, 40, 5, 10, get_roll, get_sideslip );
-
-  fgHUDAddLadder ( hud, 330, 285, 120, 180, 70, 10,
-                   NONE, 45, get_roll, get_pitch );
-     // KIAS
-  fgHUDAddScale  ( hud, VERTICAL,     LIMIT, 200, 180, 380,  5,  10,
-                      LEFT,     0,  100,   50,   0, get_speed );
-     // Angle of Attack
-  fgHUDAddScale  ( hud, HORIZONTAL, NOLIMIT, 180, 250, 410,  1,   5,
-                      BOTTOM, -40,   50,   21,   0, get_aoa );
-     // GYRO COMPASS
-  fgHUDAddScale  ( hud, HORIZONTAL, NOLIMIT, 380, 200, 460,  5,  10,
-                      TOP,      0,   50,   50, 360, get_heading );
-     // AMSL
-  fgHUDAddScale  ( hud, VERTICAL,     LIMIT, 460, 180, 380, 25, 100,
-                      RIGHT,    0, 15000, 250,   0, get_altitude);
-
-  fgHUDAddLabel  ( hud, 160, 150, SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " Kts",      "%5.0f", get_speed );
-  fgHUDAddLabel  ( hud, 160, 135, SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " m",        "%5.0f", get_altitude );
-  fgHUDAddLabel  ( hud, 160, 120, SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " Roll",     "%5.2f", get_roll );
-  fgHUDAddLabel  ( hud, 160, 105, SMALL, NOBLINK,
-                      RIGHT_JUST, "Lat  ", "d",     "%03.0f", get_latitude );
-  fgHUDAddLabel  ( hud, 160, 90,  SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " m",        "%05.2f", get_lat_min );
-  
-  fgHUDAddLabel  ( hud, 440, 150, SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " AOA",      "%5.2f", get_aoa );
-  fgHUDAddLabel  ( hud, 440, 135, SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " Heading",  "%5.0f", get_heading );
-  fgHUDAddLabel  ( hud, 440, 120, SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " Sideslip", "%5.2f", get_sideslip );
-  fgHUDAddLabel  ( hud, 440, 105, SMALL, NOBLINK,
-                      RIGHT_JUST, "Lon  ", "d",     "%04.0f", get_longitude );
-  fgHUDAddLabel  ( hud, 440, 90,  SMALL, NOBLINK,
-                      RIGHT_JUST, NULL, " m",        "%05.2f", get_long_min );
-  fgHUDAddLabel  ( hud, 10,470, SMALL, NOBLINK,
-                     RIGHT_JUST, "Frame rate = ", NULL,  "%.1f ", get_frame_rate);
-
-  fgHUDAddControlSurfaces( hud, 10, 10, NULL );
-
-//  fgHUDAddControl( hud, HORIZONTAL, 50,  25, get_aileronval  ); // was 10, 10
-//  fgHUDAddControl( hud, VERTICAL,   150, 25, get_elevatorval ); // was 10, 10
-//  fgHUDAddControl( hud, HORIZONTAL, 250, 25, get_rudderval   ); // was 10, 10
-
-  return( hud );
-}
-
-
-// add_instrument
-//
-// This is a stand in for linked list code that will get replaced later
-// by some more elegant list handling code.
-
-void add_instrument( Hptr hud, HIptr pinstrument )
-{
-    if( !hud || !pinstrument ) {
-       return;
-    }
-
-    pinstrument->next = hud->instruments;
-    hud->instruments = pinstrument;
-}
-
-
-// fgHUDAddHorizon
-//
-// Constructs a HUD_horizon "object" and installs it into the hud instrument
-// list.
-
-Hptr fgHUDAddHorizon( Hptr hud,     \
-                      int x_pos,    \
-                      int y_pos,    \
-                      int length,   \
-                      int hole_len, \
-                      int tee_height,\
-                      double (*load_roll)(),
-                      double (*load_sideslip)() )
-{
-    HUD_horizon *phorizon;
-    HUD_instr   *pinstrument;
-
-    if( !hud ) {
-       return NULL;
-    }
-                                       // construct the parent object
-    pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
-    if( pinstrument == NULL ) {
-       return( NULL );
-    }
-    pinstrument->type    = HUDhorizon;  //  ARTIFICIAL_HORIZON;
-
-                                      // Construct the horizon
-    phorizon = (HUD_horizon *) calloc( sizeof(HUD_horizon),1);
-    if( phorizon == NULL )   {
-       return( NULL );
-    }
-
-    phorizon->scrn_pos.x    = x_pos;
-    phorizon->scrn_pos.y    = y_pos;
-    phorizon->scr_width     = length | 1;
-    phorizon->scr_hole      = hole_len;
-    phorizon->tee_height    = tee_height;
-    phorizon->load_roll     = load_roll;
-    phorizon->load_sideslip = load_sideslip;
-    //  Install the horizon in the parent.
-    pinstrument->instr   = phorizon;
-    //  Install the instrument into hud.
-    add_instrument( hud, pinstrument);
-
-    return( hud );
-}
-
-// fgHUDAddScale
-//
-// Constructs a HUD_scale "object" and installs it into the hud instrument
-// list.
-
-Hptr fgHUDAddScale( Hptr hud,        \
-                    int type,        \
-                    int sub_type,    \
-                    int scr_pos,     \
-                    int scr_min,     \
-                    int scr_max,     \
-                    int div_min,     \
-                    int div_max,     \
-                    int orientation, \
-                    int min_value,   \
-                    int max_value,   \
-                    int width_units, \
-                    int modulus,     \
-                    double (*load_value)() )
-{
-  HUD_scale *pscale;
-  HUD_instr *pinstrument;
-
-  if( !hud ) {
-    return NULL;
-    }
-
-       pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
-       if( pinstrument == NULL ) {
-     return( NULL );
-     }
-
-  pinstrument->type = HUDscale;
-
-  pscale = ( HUD_scale *)calloc(sizeof(HUD_scale),1);
-  if( pscale == NULL )   {
-     return( NULL );
-    }
-
-  pscale->type             = type;
-  pscale->sub_type         = sub_type;
-  pscale->div_min          = div_min;
-  pscale->div_max          = div_max;
-  pscale->orientation      = orientation;
-  pscale->minimum_value    = min_value;
-  pscale->maximum_value    = max_value;
-  pscale->modulo           = modulus;
-  pscale->load_value       = load_value;
-
-  pscale->half_width_units = width_units / 2.0;
-  pscale->scr_span = scr_max - scr_min; // Run of scan in pix coord
-  pscale->scr_span |= 1;                // Force odd span of units.
-             // If span is odd number of units, mid will be correct.
-             // If not it will be high by one coordinate unit. This is
-             // an artifact of integer division needed for screen loc's.
-
-  pscale->mid_scr  = (pscale->scr_span >> 1) + scr_min;
-
-             // Calculate the number of screen units per indicator unit
-             // We must force floating point calculation or the factor
-             // will be low and miss locate tics by several units.
-
-  pscale->factor   = (double)pscale->scr_span / (double)width_units;
-
-  switch( type ) {
-    case HORIZONTAL:
-      pscale->scrn_pos.left    = scr_min;
-      pscale->scrn_pos.top     = scr_pos;
-      pscale->scrn_pos.right   = scr_max;
-      pscale->scrn_pos.bottom  = scr_pos;
-      break;
-
-    case VERTICAL:
-    default:
-      pscale->scrn_pos.left    = scr_pos;
-      pscale->scrn_pos.top     = scr_max;
-      pscale->scrn_pos.right   = scr_pos;
-      pscale->scrn_pos.bottom  = scr_min;
-    }
-
-                                     // Install the scale
-  pinstrument->instr = pscale;
-                                      //  Install the instrument into hud.
-  add_instrument( hud, pinstrument);
-
-  return( hud );
-}
-
-// fgHUDAddLabel
-//
-// Constructs a HUD_Label object and installs it into the hud instrument
-// list.
-Hptr fgHUDAddLabel( Hptr hud,       \
-                    int x_pos,      \
-                    int y_pos,      \
-                    int size,       \
-                    int blink,      \
-                    int justify,    \
-                                                 char *pre_str,  \
-                    char *post_str, \
-                    char *format,   \
-                    double (*load_value)() )
-{
-       HUD_label *plabel;
-       HUD_instr *pinstrument;
-
-  if( !hud ) {
-    return NULL;
-    }
-
-       pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
-       if( pinstrument == NULL ) {
-    return NULL;
-    }
-       pinstrument->type = HUDlabel;
-
-       plabel = (HUD_label *)calloc(sizeof(HUD_label),1);
-       if( plabel == NULL ){
-    return NULL;
-    }
-
-  plabel->scrn_pos.x      = x_pos;
-  plabel->scrn_pos.y      = y_pos;
-  plabel->size       = size;
-  plabel->blink      = blink;
-  plabel->justify    = justify;
-  plabel->pre_str    = pre_str;
-  plabel->post_str   = post_str;
-  plabel->format     = format;
-  plabel->load_value = load_value;
-                                      // Install the label
-       pinstrument->instr = plabel;
-                                      //  Install the instrument into hud.
-  add_instrument( hud, pinstrument);
-
-       return( hud );
-}
-
-// fgHUDAddLadder
-//
-// Contains code that constructs a ladder "object" and installs it as
-// a hud instrument in the hud instrument list.
-//
-Hptr fgHUDAddLadder( Hptr hud,        \
-                     int x_pos,       \
-                     int y_pos,       \
-                     int scr_width,   \
-                     int scr_height,  \
-                                                  int hole_len,    \
-                     int div_units,   \
-                     int label_pos,   \
-                     int width_units, \
-                                                  double (*load_roll)(),
-                     double (*load_pitch)() )
-{
-       HUD_ladder *pladder;
-       HUD_instr  *pinstrument;
-
-  if( !hud ) {
-    return NULL;
-    }
-
-       pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
-       if( pinstrument == NULL )
-               return( NULL );
-
-       pinstrument->type = HUDladder;
-
-       pladder = (HUD_ladder *)calloc(sizeof(HUD_ladder),1);
-       if( pladder == NULL )
-               return( NULL );
-
-  pladder->type           = 0; // Not used.
-  pladder->scrn_pos.x          = x_pos;
-  pladder->scrn_pos.y          = y_pos;
-  pladder->scr_width      = scr_width;
-  pladder->scr_height     = scr_height;
-  pladder->scr_hole       = hole_len;
-  pladder->div_units      = div_units;
-  pladder->label_position = label_pos;
-  pladder->width_units    = width_units;
-  pladder->load_roll      = load_roll;
-  pladder->load_pitch     = load_pitch;
-
-  pinstrument->instr      = pladder;
-                                      //  Install the instrument into hud.
-  add_instrument( hud, pinstrument);
-       return hud;
-}
-
-//   fgHUDAddControlSurfaces()
-//
-//   Adds the control surface indicators which make up for the lack of seat
-//   of the pants feel. Should be unnecessary with joystick and pedals
-//   enabled. But that is another improvement. Also, what of flaps? Spoilers?
-//   This may need to be expanded or flattened into multiple indicators,
-//   vertical and horizontal.
-
-Hptr fgHUDAddControlSurfaces( Hptr hud,
-                              int x_pos,
-                              int y_pos,
-                              double (*load_value)() )
-{
-       HUD_control_surfaces *pcontrol_surfaces;
-       HUD_instr *pinstrument;
-
-    if( !hud ) {
-      return NULL;
-    }
-
-    // Construct shell
-    pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
-    if( !pinstrument ) {
-      return NULL;
+//  fgHUDSetTimeMode( hud, NIGHT );
+//  fgHUDSetBrightness( hud, BRT_LIGHT );
+
+  for( index = 0; index <= INSTRDEFS; index++) {
+    switch ( index ) {
+      case 0:     // TBI
+      //  fgHUDAddHorizon( hud, 330, 100, 40, 5, 10, get_roll, get_sideslip );
+        loc.left   =  330 - 40;
+        loc.top    =  110;
+        loc.right  =  330 + 40;
+        loc.bottom =  100;
+        HIptr = (instr_item *) new fgTBI_instr( loc );
+        break;
+
+      case 1:     // Artificial Horizon
+      //  fgHUDAddLadder ( hud, 330, 285, 120, 180, 70, 10,
+      //                   NONE, 45, get_roll, get_pitch );
+        loc.left   =  270; // 330 -  60
+        loc.top    =  375; // 285 +  90
+        loc.right  =  390; // 330 +  60
+        loc.bottom =  195; // 285 -  90
+        HIptr = (instr_item *) new HudLadder( loc );
+        break;
+
+      case 2:    // KIAS
+      //  fgHUDAddScale  ( hud, VERTICAL,     LIMIT, 200, 180, 380,  5,  10,
+      //                      LEFT,     0,  100,   50,   0, get_speed );
+        loc.left   =  160;
+        loc.top    =  380;
+        loc.right  =  200;
+        loc.bottom =  180;
+        HIptr = (instr_item *) new moving_scale( loc,
+                                                 get_speed,
+                                                 ReadLEFT,
+                                                 200, 0,
+                                                 10,  5,
+                                                 0,
+                                                 50.0,
+                                                 TRUE);
+        break;
+
+      case 3:    // Angle of Attack
+      //  fgHUDAddScale  ( hud, HORIZONTAL, NOLIMIT, 180, 250, 410,  1,   5,
+      //                      BOTTOM, -40,   50,   21,   0, get_aoa );
+        loc.left   =  250;
+        loc.top    =  190;
+        loc.right  =  410;
+        loc.bottom =  160;
+        HIptr = (instr_item *) new moving_scale( loc,
+                                                 get_aoa,
+                                                 ReadBOTTOM,
+                                                 50, -40,
+                                                 5,    1,
+                                                 0,
+                                                 21.0,
+                                                 TRUE);
+        break;
+
+      case 4:    // GYRO COMPASS
+      // fgHUDAddScale  ( hud, HORIZONTAL, NOLIMIT, 380, 200, 460,  5,  10,
+      //                      TOP,      0,   50,   50, 360, get_heading );
+        loc.left   =  200;
+        loc.top    =  410;
+        loc.right  =  460;
+        loc.bottom =  380;
+        HIptr = (instr_item *) new moving_scale( loc,
+                                                 get_heading,
+                                                 ReadTOP,
+                                                 360, 0,
+                                                 10,   5,
+                                                 360,
+                                                 50,
+                                                 TRUE);
+        break;
+
+      case 5:    // AMSL
+      //  fgHUDAddScale  ( hud, VERTICAL,     LIMIT, 460, 180, 380, 25, 100,
+      //                      RIGHT,    0, 15000, 250,   0, get_altitude);
+        loc.left   =  460;
+        loc.top    =  380;
+        loc.right  =  490;
+        loc.bottom =  180;
+        HIptr = (instr_item *) new moving_scale( loc,
+                                                 get_altitude,
+                                                 ReadRIGHT,
+                                                 15000, 0,
+                                                 100,  25,
+                                                 0,
+                                                 250,
+                                                 TRUE);
+        break;
+
+      case 6:    // Digital KIAS
+      //  fgHUDAddLabel  ( hud, 160, 150, SMALL, NOBLINK,
+      //                 RIGHT_JUST, NULL, " Kts",      "%5.0f", get_speed );
+        loc.left   =  160;
+        loc.top    =  180; // Ignore
+        loc.right  =  200; // Ignore
+        loc.bottom =  150;
+        HIptr = (instr_item *) new instr_label ( loc,
+                                                 get_speed,
+                                                 "%5.0f",
+                                                 NULL,
+                                                 " Kts",
+                                                 ReadTOP,
+                                                 RIGHT_JUST,
+                                                 SMALL,
+                                                 0,
+                                                 TRUE );
+        break;
+
+      case 7:    // Digital Altimeter
+      //  fgHUDAddLabel  ( hud, 160, 135, SMALL, NOBLINK,
+      //              RIGHT_JUST, NULL, " m",        "%5.0f", get_altitude );
+        loc.left   =  160;
+        loc.top    =  145; // Ignore
+        loc.right  =  200; // Ignore
+        loc.bottom =  135;
+        HIptr = (instr_item *) new instr_label ( loc,
+                                                 get_altitude,
+                                                 "MSL  %5.0f",
+                                                 NULL,
+                                                 " m",
+                                                 ReadTOP,
+                                                 LEFT_JUST,
+                                                 SMALL,
+                                                 0,
+                                                 TRUE );
+        break;
+
+      case 8:    // Roll indication diagnostic
+      // fgHUDAddLabel  ( hud, 160, 120, SMALL, NOBLINK,
+      //                  RIGHT_JUST, NULL, " Roll",     "%5.2f", get_roll );
+        loc.left   =  160;
+        loc.top    =  130; // Ignore
+        loc.right  =  200; // Ignore
+        loc.bottom =  120;
+        HIptr = (instr_item *) new instr_label ( loc,
+                                                 get_roll,
+                                                 "%5.2f",
+                                                 " Roll",
+                                                 " Deg",
+                                                 ReadTOP,
+                                                 RIGHT_JUST,
+                                                 SMALL,
+                                                 0,
+                                                 TRUE );
+        break;
+
+      case 9:    // Angle of attack diagnostic
+      //  fgHUDAddLabel  ( hud, 440, 150, SMALL, NOBLINK,
+      //                   RIGHT_JUST, NULL, " AOA",      "%5.2f", get_aoa );
+        loc.left   =  440;
+        loc.top    =  160; // Ignore
+        loc.right  =  500; // Ignore
+        loc.bottom =  150;
+        HIptr = (instr_item *) new instr_label ( loc,
+                                                 get_aoa,
+                                                 "    %5.2f",
+                                                 " AOA",
+                                                 " Deg",
+                                                 ReadTOP,
+                                                 RIGHT_JUST,
+                                                 SMALL,
+                                                 0,
+                                                 TRUE );
+        break;
+
+      case 10:
+      //  fgHUDAddLabel  ( hud, 440, 135, SMALL, NOBLINK,
+      //               RIGHT_JUST, NULL, " Heading",  "%5.0f", get_heading );
+        loc.left   =  440;
+        loc.top    =  145; // Ignore
+        loc.right  =  500; // Ignore
+        loc.bottom =  135;
+        HIptr = (instr_item *) new instr_label ( loc,
+                                                 get_heading,
+                                                 "%5.0f",
+                                                 "Heading",
+                                                 " Deg",
+                                                 ReadTOP,
+                                                 RIGHT_JUST,
+                                                 SMALL,
+                                                 0,
+                                                 TRUE );
+        break;
+
+      case 11:
+      //  fgHUDAddLabel  ( hud, 440, 120, SMALL, NOBLINK,
+      //              RIGHT_JUST, NULL, " Sideslip", "%5.2f", get_sideslip );
+        loc.left   =  440;
+        loc.top    =  130; // Ignore
+        loc.right  =  500; // Ignore
+        loc.bottom =  120;
+        HIptr = (instr_item *) new instr_label ( loc,
+                                                 get_sideslip,
+                                                 "%5.2f",
+                                                 "Sideslip",
+                                                 NULL,
+                                                 ReadTOP,
+                                                 RIGHT_JUST,
+                                                 SMALL,
+                                                 0,
+                                                 TRUE );
+        break;
+
+      case 12:
+        loc.left   = 440;
+        loc.top    =  90; // Ignore
+        loc.right  = 440; // Ignore
+        loc.bottom = 100;
+        HIptr = (instr_item *) new instr_label( loc, get_throttleval,
+                                                "%5.2f",
+                                                "Throttle",
+                                                NULL,
+                                                ReadTOP,
+                                                RIGHT_JUST,
+                                                SMALL,
+                                                0,
+                                                TRUE );
+        break;
+
+      case 13:
+        loc.left   = 440;
+        loc.top    =  70; // Ignore
+        loc.right  = 500; // Ignore
+        loc.bottom =  85;
+        HIptr = (instr_item *) new instr_label( loc, get_elevatorval,
+                                                "%5.2f",
+                                                "Elevator",
+                                                NULL,
+                                                ReadTOP,
+                                                RIGHT_JUST,
+                                                SMALL,
+                                                0,
+                                                TRUE );
+        break;
+
+      case 14:
+        loc.left   = 440;
+        loc.top    = 100; // Ignore
+        loc.right  = 500; // Ignore
+        loc.bottom =  60;
+        HIptr = (instr_item *) new instr_label( loc, get_aileronval,
+                                                "%5.2f",
+                                                "Aileron",
+                                                NULL,
+                                                ReadTOP,
+                                                RIGHT_JUST,
+                                                SMALL,
+                                                0,
+                                                TRUE );
+        break;
+
+      case 15:
+        loc.left   = 10;
+        loc.top    = 100; // Ignore
+        loc.right  = 500; // Ignore
+        loc.bottom =  10;
+        HIptr = (instr_item *) new instr_label( loc, get_frame_rate,
+                                                "%.1f",
+                                                "Frame rate = ",
+                                                NULL,
+                                                ReadTOP,
+                                                RIGHT_JUST,
+                                                SMALL,
+                                                0,
+                                                TRUE );
+        break;
+
+      //  fgHUDAddControlSurfaces( hud, 10, 10, NULL );
+//        loc.left   =  250;
+//        loc.top    =  190;
+//        loc.right  =  410;
+//        loc.bottom =  180;
+//        HIptr = (instr_item *) new
+//        break;
+
+      default:;
       }
-    pinstrument->type = HUDcontrol_surfaces;
-
-    // Construct core
-    pcontrol_surfaces = (HUD_control_surfaces *)calloc(sizeof(HUD_control),1);
-    if( !pcontrol_surfaces ) {
-      return( NULL );
+    if( HIptr ) {                   // Anything to install?
+      HUD_deque.insert( HUD_deque.begin(), HIptr);
       }
-
-    pcontrol_surfaces->scrn_pos.x = x_pos;
-    pcontrol_surfaces->scrn_pos.y = y_pos;
-    pcontrol_surfaces->load_value = load_value;
-
-    pinstrument->instr     = pcontrol_surfaces;
-                                                   // Install
-    add_instrument( hud, pinstrument);
-
-    return hud;
-}
-
-// fgHUDAddControl
-//
-//
-
-Hptr fgHUDAddControl( Hptr hud,        \
-                      int ctrl_x,      \
-                      int ctrl_y,      \
-                      int ctrl_length, \
-                      int orientation, \
-                      int alignment,   \
-                      int min_value,   \
-                      int max_value,   \
-                      int width_units, \
-                      double (*load_value)() )
-{
-    HUD_control *pcontrol;
-    HUD_instr *pinstrument;
-
-    if( !hud ) {
-      return NULL;
     }
 
-    // Construct shell
-    pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
-    if( !pinstrument ) {
-      return NULL;
-      }
-    pinstrument->type = HUDcontrol;
-
-    // Construct core
-    pcontrol = (HUD_control *)calloc(sizeof(HUD_control),1);
-    if( !(pcontrol == NULL) ) {
-      return( NULL );
-      }
-    pcontrol->scrn_pos.x    = ctrl_x;
-    pcontrol->scrn_pos.y    = ctrl_y;
-    pcontrol->ctrl_length   = ctrl_length;
-    pcontrol->orientation   = orientation;
-    pcontrol->alignment     = alignment;
-    pcontrol->min_value     = min_value;
-    pcontrol->max_value     = max_value;
-    pcontrol->width_units   = width_units;
-    pcontrol->load_value    = load_value;
-                                                   // Integrate
-    pinstrument->instr     = pcontrol;
-                                                   // Install
-    add_instrument( hud, pinstrument);
-
-    return hud;
-}
-
-/*
-Hptr fgHUDAddMovingHorizon(  Hptr hud,     \
-                             int x_pos,    \
-                             int y_pos,    \
-                             int length,   \
-                             int hole_len, \
-                             int color )
-{
-
-}
-
-Hptr fgHUDAddCircularLadder( Hptr hud,    \
-                             int scr_min, \
-                             int scr_max, \
-                             int div_min, \
-                             int div_max, \
-                             int max_value )
-{
-
+//  fgHUDAddControl( hud, HORIZONTAL, 50,  25, get_aileronval  ); // was 10, 10
+//  fgHUDAddControl( hud, VERTICAL,   150, 25, get_elevatorval ); // was 10, 10
+//  fgHUDAddControl( hud, HORIZONTAL, 250, 25, get_rudderval   ); // was 10, 10
+  return 0;  // For now. Later we may use this for an error code.
 }
 
-Hptr fgHUDAddNumDisp( Hptr hud,           \
-                      int x_pos,          \
-                      int y_pos,          \
-                      int size,           \
-                      int color,          \
-                      int blink,          \
-                                                         char *pre_str,      \
-                      char *post_str )
-{
-
-}
-*/
 
 // fgUpdateHUD
 //
@@ -1504,95 +1790,90 @@ Hptr fgHUDAddNumDisp( Hptr hud,           \
 // the HUD object with requests for redraw. Kinda. It will when this is
 // all C++.
 //
+int global_day_night_switch = DAY;
 
-void fgUpdateHUD( Hptr hud ) {
-    HIptr phud_instr;
-
-    glMatrixMode(GL_PROJECTION);
-    glPushMatrix();
-
-    glLoadIdentity();
-    gluOrtho2D(0, 640, 0, 480);
-    glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-    glLoadIdentity();
-
-    glColor3f(1.0, 1.0, 1.0);
-    glIndexi(7);
-
-    glDisable(GL_DEPTH_TEST);
-    glDisable(GL_LIGHTING);
-
-    glLineWidth(1);
-                                   // This is a good improvement, but needs
-                                   // to respond to a dial instead of time
-                                   // of day. Of course, we have no dial!
-    if( hud->time_of_day==DAY) {
-      switch (hud->brightness) {
-         case BRT_LIGHT:
-           glColor3f (0.1, 0.9, 0.1);
-           break;
-         case BRT_MEDIUM:
-           glColor3f (0.1, 0.7, 0.0);
-           break;
-         case BRT_DARK:
-           glColor3f (0.0, 0.5, 0.0);
-         }
-      }
-    else if( hud->time_of_day==NIGHT) {
-      switch (hud->brightness) {
-         case BRT_LIGHT:
-           glColor3f (0.9, 0.1, 0.1);
-           break;
-         case BRT_MEDIUM:
-           glColor3f (0.7, 0.0, 0.1);
-           break;
-         case BRT_DARK:
-           glColor3f (0.5, 0.0, 0.0);
-         }
-      }
-    else {
-      glColor3f (0.1, 0.9, 0.1);
-      }
-
-    fgPrintf( FG_COCKPIT, FG_DEBUG, "HUD Code %d  Status %d\n",
-              hud->code, hud->status );
-
-    phud_instr = hud->instruments;
-    while( phud_instr ) {
-       /* printf("Drawing Instrument %d\n", phud_instr->type); */
-
-       switch (phud_instr->type) {
-    case HUDhorizon:   // ARTIFICIAL HORIZON
-           drawhorizon( (pHUDhorizon)phud_instr->instr );
-           break;
+void fgUpdateHUD( void ) {
+  int i;
+  int brightness;
+//  int day_night_sw = current_aircraft.controls->day_night_switch;
+  int day_night_sw = global_day_night_switch;
+  int hud_displays = HUD_deque.size();
+  instr_item *pHUDInstr;
 
-    case HUDscale:     // Need to simplify this call.
-           drawscale (  (pHUDscale)  phud_instr->instr  );
-           break;
-
-    case HUDlabel:
-           drawlabel (  (pHUDlabel)  phud_instr->instr  );
-           break;
-
-    case HUDladder:
-           drawladder(  (pHUDladder) phud_instr->instr  );
-           break;
+  if( !hud_displays ) {  // Trust everyone, but ALWAYS cut the cards!
+    return;
+    }
 
-//    case HUDcontrol:
-//      drawControl( (pHUDcontrol) phud_instr->instr );
-//      break;
+  pHUDInstr = HUD_deque[0];
+  brightness = pHUDInstr->get_brightness();
+//  brightness = HUD_deque.at(0)->get_brightness();
 
-    case HUDcontrol_surfaces:
-           drawControlSurfaces( (pHUDControlSurfaces) phud_instr->instr );
-           break;
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
 
-    default:; // Ignore anything you don't know about.
+  glLoadIdentity();
+  gluOrtho2D(0, 640, 0, 480);
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+
+  glColor3f(1.0, 1.0, 1.0);
+  glIndexi(7);
+
+  glDisable(GL_DEPTH_TEST);
+  glDisable(GL_LIGHTING);
+
+  glLineWidth(1);
+
+  for( i = hud_displays; i; --i) { // Draw everything
+//    if( HUD_deque.at(i)->enabled()) {
+    pHUDInstr = HUD_deque[i - 1];
+    if( pHUDInstr->enabled()) {
+                                   // We should to respond to a dial instead
+                                   // or as well to the of time of day. Of
+                                   // course, we have no dial!
+      if( day_night_sw == DAY) {
+        switch (brightness) {
+          case BRT_LIGHT:
+            glColor3f (0.1, 0.9, 0.1);
+            break;
+
+          case BRT_MEDIUM:
+            glColor3f (0.1, 0.7, 0.0);
+            break;
+
+          case BRT_DARK:
+            glColor3f (0.0, 0.5, 0.0);
+            }
+          }
+        else {
+          if( day_night_sw == NIGHT) {
+            switch (brightness) {
+              case BRT_LIGHT:
+                glColor3f (0.9, 0.1, 0.1);
+                break;
+
+              case BRT_MEDIUM:
+                glColor3f (0.7, 0.0, 0.1);
+                break;
+
+              case BRT_DARK:
+              default:
+                glColor3f (0.5, 0.0, 0.0);
+              }
+            }
+          else {     // Just in case default
+            glColor3f (0.1, 0.9, 0.1);
+            }
+          }
+    //  fgPrintf( FG_COCKPIT, FG_DEBUG, "HUD Code %d  Status %d\n",
+    //            hud->code, hud->status );
+      pHUDInstr->draw();
+//      HUD_deque.at(i)->draw(); // Responsible for broken or fixed variants.
+                              // No broken displays honored just now.
+      }
     }
 
-  phud_instr = phud_instr->next;
-  }
-
   glEnable(GL_DEPTH_TEST);
   glEnable(GL_LIGHTING);
   glMatrixMode(GL_PROJECTION);
@@ -1601,40 +1882,10 @@ void fgUpdateHUD( Hptr hud ) {
   glPopMatrix();
 }
 
-void fgHUDSetTimeMode( Hptr hud, int time_of_day )
-{
-
-  hud->time_of_day = time_of_day;
-
-}
-
-void fgHUDSetBrightness( Hptr hud, int brightness )
-{
-
-  hud->brightness = brightness;
-
-}
-
 /* $Log$
-/* Revision 1.6  1998/05/07 23:12:31  curt
-/* Changed frame rate formatting a bit.
+/* Revision 1.7  1998/05/11 18:13:11  curt
+/* Complete C++ rewrite of all cockpit code by Charlie Hotchkiss.
 /*
- * Revision 1.5  1998/05/06 03:15:08  curt
- * Durk Talsma contributed a graphical frame rate counter which is displayed
- * as part of the HUD.
- *
- * Revision 1.4  1998/05/03 00:46:46  curt
- * polar.h -> polar3d.h
- *
- * Revision 1.3  1998/04/30 12:36:02  curt
- * C++-ifying a couple source files.
- *
- * Revision 1.2  1998/04/25 22:06:27  curt
- * Edited cvs log messages in source files ... bad bad bad!
- *
- * Revision 1.1  1998/04/24 00:45:57  curt
- * C++-ifing the code a bit.
- *
  * Revision 1.22  1998/04/18 04:14:02  curt
  * Moved fg_debug.c to it's own library.
  *
@@ -1683,7 +1934,7 @@ void fgHUDSetBrightness( Hptr hud, int brightness )
  * Added MetroWorks patches from Carmen Volpe.
  *
  * Revision 1.8  1998/01/27 00:47:51  curt
- * Incorporated Paul Bleisch's <pbleisch@acm.org> new debug message
+ * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
  * system and commandline/config file processing code.
  *
  * Revision 1.7  1998/01/19 18:40:20  curt
index dd1e31501cc872f9b3237e4a5797f6ced9fcf8fa..2ccec4fd53cafc87b4008edec96f41acd543a926 100644 (file)
 #define _HUD_HXX
 
 
-#ifndef __cplusplus                                                          
+#ifndef __cplusplus
 # error This library requires C++
-#endif                                   
+#endif
 
 
+#include <config.h>
+
+
+#include <fg_typedefs.h>
+#include <fg_constants.h>
 #include <Aircraft/aircraft.h>
 #include <Flight/flight.h>
 #include <Controls/controls.h>
 
+//using namespace std;
+
+#include <deque.h>       // STL
+
+
+#ifndef WIN32
+
+  typedef struct {
+      int x, y;
+  } POINT;
+
+  typedef struct {
+      int top, bottom, left, right;
+  } RECT;
+
+#endif
+
+
 // View mode definitions
 
-enum VIEW_MODES { HUD_VIEW, PANEL_VIEW, CHASE_VIEW, TOWER_VIEW };
+enum VIEW_MODES{ HUD_VIEW, PANEL_VIEW, CHASE_VIEW, TOWER_VIEW };
 
+// DAY, NIGHT and brightness levels need to be visible where dialogs and
+// controls can be used to set intensity and appropriate color. This will
+// be moved.
 // Hud general constants
 #define DAY                1
 #define NIGHT              2
@@ -50,31 +76,14 @@ enum VIEW_MODES { HUD_VIEW, PANEL_VIEW, CHASE_VIEW, TOWER_VIEW };
 #define SIZE_SMALL         6
 #define SIZE_LARGE         7
 
-// Instrument types
-#define ARTIFICIAL_HORIZON     1
-#define SCALE              2
-#define LADDER             3
-#define LABEL              4
-
-// Scale constants
-#define HORIZONTAL         1
-#define TOP                2
-#define BOTTOM             3
-#define VERTICAL           4
-#define LEFT               5
-#define RIGHT              6
-#define LIMIT              7
-#define NOLIMIT            8
-#define ROUNDROB           9
-
 // Label constants
 #define SMALL              1
 #define LARGE              2
+
 #define BLINK              3
 #define NOBLINK            4
-#define LEFT_JUST          5
-#define CENTER_JUST        6
-#define RIGHT_JUST         7
+
+enum fgLabelJust{ LEFT_JUST, CENTER_JUST, RIGHT_JUST } ;
 
 // Ladder constants
 #define NONE               1
@@ -90,6 +99,12 @@ enum VIEW_MODES { HUD_VIEW, PANEL_VIEW, CHASE_VIEW, TOWER_VIEW };
 #define DASHED_LINES      11
 #define DASHED_NEG_LINES  12
 
+
+#define HORIZON_FIXED  1
+#define HORIZON_MOVING 2
+#define LABEL_COUNTER  1
+#define LABEL_WARNING  2
+
 // Ladder orientaion
 // #define HUD_VERTICAL        1
 // #define HUD_HORIZONTAL              2
@@ -116,275 +131,316 @@ enum VIEW_MODES { HUD_VIEW, PANEL_VIEW, CHASE_VIEW, TOWER_VIEW };
 // #define HUD_INSTR_HORIZON   3
 // #define HUD_INSTR_LABEL             4
 
-// The following structs will become classes with a derivation from
-// an ABC instrument_pack. Eventually the instruments may well become
-// dll's. This would open the instrumentation issue to all commers.
-//
-// Methods Needed:
-//    Constructor()
-//    Initialization();  // For dynamic scenario settups?
-//    Update();          // Follow the data changes.
-//    Repaint();         // Respond to uncover/panel repaints.
-//    Break();           // Show a frown.
-//    Fix();             // Return to normal appearance and function.
-//    Night_Day();       // Illumination changes appearance/bitmaps.
-//
-
-// CLO 2/21/98 - added to fix compile error
-typedef struct  {
-  int x;
-  int y;
-} FG_POINT;
-
-// CLO 2/21/98 - added to fix compile error
-typedef struct  {
-  int left;
-  int right;
-  int top;
-  int bottom;
-} FG_RECT;
-
-typedef struct  {
-       // Parametric defined members
-  int  type;
-  int  sub_type;
-  int  div_min;
-  int  div_max;
-  int  orientation;
-  int  minimum_value;
-  int  maximum_value;
-  int  width_units;
-  int  modulo;    // for compass, etc. Set to 0 for non_modulo scales.
-
-  double (*load_value)( void );
-
-  // Pre-calculated members.
-  int scr_span;
-  int mid_scr;
-  FG_RECT scrn_pos; // Screen rectangle for inicator
-                 //  Replaces previous parameters as:
-                 //  scr_pos -> left,bottom
-                 //  scr_max -> top, right
-                 //  scr_min -> left,bottom
-  double factor;
-  double half_width_units;
-}HUD_scale,  *pHUDscale;
-
-typedef struct  {
-       int type;
-  FG_RECT  position;
-       int div_min;
-       int div_max;
-       int orientation;
-       int label_position;
-       int width_units;
-  int  modulo;  // for compass, etc. Set to 0 for non_modulo scales.
-       double (*load_value)( void );
-}HUD_circular_scale, *pHUD_circscale;
-
-typedef struct  {
-       int type;
-  FG_POINT scrn_pos;
-       int scr_width;
-       int scr_height;
-       int scr_hole;
-       int div_units;
-       int label_position;
-       int width_units;
-       double (*load_roll)( void );
-       double (*load_pitch)( void );
-}HUD_ladder, *pHUDladder;
-
-typedef struct {
-       int scr_min;
-       int scr_max;
-       int div_min;
-       int div_max;
-       int orientation;
-       int label_position;
-       int width_units;
-       double (*load_value)( void );
-} HUD_circular_ladder, *pHUDcircladder;
-
-#define HORIZON_FIXED  1
-#define HORIZON_MOVING 2
-
-typedef struct{
-       int type;
-  FG_POINT scrn_pos;
-       int scr_width;
-       int scr_hole;
-       int tee_height;
-       double (*load_roll)( void );
-       double (*load_sideslip)( void );
-} HUD_horizon, *pHUDhorizon;
-
-typedef struct {
-  FG_POINT scrn_pos;
-  double(*load_value)(void);
-} HUD_control_surfaces, *pHUDControlSurfaces;
-
-typedef struct {
-  FG_POINT scrn_pos;    // ctrl_x, ctrl_y
-  int ctrl_length;
-  int orientation;
-  int alignment;
-  int min_value;
-  int max_value;
-  int width_units;
-  double (*load_value)(void);
-} HUD_control, *pHUDControl;
-#define LABEL_COUNTER  1
-#define LABEL_WARNING  2
-
-typedef struct {
-       int type;
-  FG_POINT scrn_pos;
-       int size;
-       int blink;
-       int justify;
-       char *pre_str;
-       char *post_str;
-       char *format;
-       double (*load_value)( void ); // pointer to routine to get the data
-} HUD_label, *pHUDlabel;
-
-// Removed union HUD_instr_data to evolve this to oop code.
-
-typedef enum{ HUDno_instr,
+extern double get_throttleval ( void );
+extern double get_aileronval  ( void );
+extern double get_elevatorval ( void );
+extern double get_elev_trimval( void );
+extern double get_rudderval   ( void );
+extern double get_speed       ( void );
+extern double get_aoa         ( void );
+extern double get_roll        ( void );
+extern double get_pitch       ( void );
+extern double get_heading     ( void );
+extern double get_altitude    ( void );
+extern double get_sideslip    ( void );
+extern double get_frame_rate  ( void );
+
+enum  hudinstype{ HUDno_instr,
               HUDscale,
-              HUDcirc_scale,
+              HUDlabel,
               HUDladder,
               HUDcirc_ladder,
               HUDhorizon,
-              HUDlabel,
-              HUDcontrol_surfaces,
-              HUDcontrol
-              } hudinstype;
-
-typedef struct HUD_INSTR_STRUCT{
-  hudinstype  type;
-  int sub_type;
-  int orientation;
-  void *instr;   // For now we will cast this pointer accoring to the value
-                 // of the type member.
-  struct HUD_INSTR_STRUCT *next;
-} HUD_instr, *HIptr;
-
-typedef struct  {
-       int code;
-       HIptr instruments;
-       int status;
-       int time_of_day;
-       int brightness;
-       int size; // possibly another name for this ? (michele)
-}HUD, *Hptr;
-
-Hptr fgHUDInit      ( fgAIRCRAFT *cur_aircraft );
+              HUDguage,
+              HUDdual_inst,
+              HUDmoving_scale,
+              HUDtbi
+              };
+
+enum ReadOriented{ ReadRIGHT, ReadLEFT, ReadTOP, ReadBOTTOM };
+
+class instr_item {  // An Abstract Base Class (ABC)
+  private:
+    static UINT      instances;     // More than 64K instruments? Nah!
+    UINT             handle;
+    RECT             scrn_pos;      // Framing - affects scale dimensions
+                                    // and orientation. Vert vs Horz, etc.
+    DBLFNPTR         load_value_fn;
+    ReadOriented     oriented;
+    bool             is_enabled;
+    bool             broken;
+    int              brightness;
+    UINT             scr_span;      // Working values for draw;
+    POINT            mid_span;      //
+
+  public:
+    instr_item( RECT           scrn_pos,
+                DBLFNPTR       data_source,
+                ReadOriented   orient,
+                bool           working      = true);
+
+    instr_item( const instr_item & image );
+
+    instr_item & operator = ( const instr_item & rhs );
+    virtual ~instr_item ();
+
+    int          get_brightness  ( void ) { return brightness;}
+    RECT         get_location    ( void ) { return scrn_pos;  }
+    bool         is_broken       ( void ) { return broken;    }
+    bool         enabled         ( void ) { return is_enabled;}
+    double       get_value       ( void ) { return load_value_fn();}
+    UINT         get_span        ( void ) { return scr_span;  }
+    POINT        get_centroid    ( void ) { return mid_span;  }
+    ReadOriented get_orientation ( void ) { return oriented;  }
+
+    virtual void display_enable( bool working ) { is_enabled = !! working;}
+
+
+    virtual void update( void );
+    virtual void break_display ( bool bad );
+    virtual void SetBrightness( int illumination_level ); // fgHUDSetBright...
+    UINT    get_Handle( void );
+    virtual void draw( void ) = 0;   // Required method in derived classes
+};
+
+typedef instr_item *HIptr;
+extern deque< instr_item *> HUD_deque;
+
+// instr_item           This class has no other purpose than to maintain
+//                      a linked list of instrument and derived class
+// object pointers.
+
+
+class instr_label : public instr_item {
+  private:
+    const char *pformat;
+    const char *pre_str;
+    const char *post_str;
+    fgLabelJust justify;
+    int         fontSize;
+    int         blink;
+
+  public:
+    instr_label( RECT         the_box,
+                 DBLFNPTR     data_source,
+                 const char  *label_format,
+                 const char  *pre_label_string    = 0,
+                 const char  *post_label_string   = 0,
+                 ReadOriented orientation         = ReadTOP,
+                 fgLabelJust  justification       = CENTER_JUST,
+                 int          font_size           = SMALL,
+                 int          blinking            = NOBLINK,
+                 bool         working             = true);
+
+    ~instr_label();
+
+    instr_label( const instr_label & image);
+    instr_label & operator = (const instr_label & rhs );
+
+    virtual void draw( void );       // Required method in base class
+};
+
+typedef instr_label * pInstlabel;
 
-void fgHUDSetTimeMode( Hptr hud, int time_of_day );
-void fgHUDSetBrightness( Hptr hud, int brightness );
-
-Hptr fgHUDAddHorizon( Hptr hud,
-                      int x_pos,
-                      int y_pos,
-                      int length,
-                      int hole_len,
-                      int tee_height,
-                      double (*load_roll)( void ),
-                      double (*load_sideslip)( void ) );
-
-Hptr fgHUDAddScale  ( Hptr hud,                    \
-                      int type,                    \
-                      int subtype,                 \
-                      int scr_pos,                 \
-                      int scr_min,                 \
-                      int scr_max,                 \
-                      int div_min,                 \
-                      int div_max,                 \
-                      int orientation,             \
-                      int min_value,               \
-                      int max_value,               \
-                      int width_units,             \
-                      int modulus,                 \
-                      double (*load_value)( void ) );
-
-Hptr fgHUDAddLabel  ( Hptr hud,                    \
-                      int x_pos,                   \
-                      int y_pos,                   \
-                      int size,                    \
-                      int blink,                   \
-                      int justify,                 \
-                      char *pre_str,               \
-                      char *post_str,              \
-                      char *format,                \
-                      double (*load_value)( void ) );
-
-Hptr fgHUDAddLadder ( Hptr hud,                    \
-                      int x_pos,                   \
-                      int y_pos,                   \
-                      int scr_width,               \
-                      int scr_height,              \
-                      int hole_len,                \
-                      int div_units,               \
-                      int label_pos,               \
-                      int max_value,               \
-                      double (*load_roll)( void ), \
-                      double (*load_pitch)( void ) );
-
-Hptr fgHUDAddControlSurfaces( Hptr hud,                    \
-                              int x_pos,                   \
-                              int y_pos,                   \
-                              double (*load_value)( void) );
-
-Hptr fgHUDAddControl( Hptr hud,                    \
-                      int ctrl_x,                  \
-                      int ctrl_y,                  \
-                      int ctrl_length,             \
-                      int orientation,             \
-                      int alignment,               \
-                      int min_value,               \
-                      int max_value,               \
-                      int width_units,             \
-                      double (*load_value)( void) );
+//
+// instr_scale           This class is an abstract base class for both moving
+//                       scale and moving needle (fixed scale) indicators. It
+// does not draw itself, but is not instanciable.
+//
+
+class instr_scale : public instr_item {
+  private:
+    int    range_shown;   // Width Units.
+    int    Maximum_value; //                ceiling.
+    int    Minimum_value; // Representation floor.
+    UINT   Maj_div;       // major division marker units
+    UINT   Min_div;       // minor division marker units
+    UINT   Modulo;        // Roll over point
+    double scale_factor;  // factor => screen units/range values.
+
+  public:
+    instr_scale( RECT         the_box,
+                 DBLFNPTR     load_fn,
+                 ReadOriented orient,
+                 int          show_range,
+                 int          max_value,
+                 int          min_value    =   0,
+                 UINT         major_divs   =  10,
+                 UINT         minor_divs   =   5,
+                 UINT         rollover     =   0,
+                 bool         working      = true);
+
+    virtual ~instr_scale();
+    instr_scale( const instr_scale & image);
+    instr_scale & operator = (const instr_scale & rhs);
+
+    virtual void draw   ( void ) {}; // No-op here. Defined in derived classes.
+    UINT   div_min      ( void ) { return Min_div;}
+    UINT   div_max      ( void ) { return Maj_div;}
+    int    min_val      ( void ) { return Minimum_value;}
+    int    max_val      ( void ) { return Maximum_value;}
+    UINT   modulo       ( void ) { return Modulo; }
+    double factor       ( void ) { return scale_factor;}
+    double range_to_show( void ) { return range_shown;}
+};
+
+// moving_scale_instr      This class displays the indicated quantity on
+//                         a scale that moves past the pointer. It may be
+// horizontal or vertical, read above(left) or below(right) of the base
+// line.
+
+class moving_scale : public instr_scale {
+  private:
+    double val_span;
+    double half_width_units;
+
+  public:
+    moving_scale( RECT         box,
+                  DBLFNPTR     load_fn,
+                  ReadOriented readway,
+                  int          maxValue,
+                  int          minValue,
+                  UINT         major_divs,
+                  UINT         minor_divs,
+                  UINT         modulator,
+                  double       value_span,
+                  bool         working = true);
+
+    ~moving_scale();
+    moving_scale( const moving_scale & image);
+    moving_scale & operator = (const moving_scale & rhs );
+//    virtual void display_enable( bool setting );
+    virtual void draw( void );       // Required method in base class
+};
+
+typedef moving_scale * pMoveScale;
+
+class guage_instr : public instr_scale {
+  private:
+
+  public:
+    guage_instr( RECT         box,
+                 DBLFNPTR     load_fn,
+                 ReadOriented readway,
+                 int          maxValue,
+                 int          minValue,
+                 UINT         major_divs,
+                 UINT         minor_divs,
+                 UINT         modulus,
+                 bool         working = true);
+
+    ~guage_instr();
+    guage_instr( const guage_instr & image);
+    guage_instr & operator = (const guage_instr & rhs );
+    virtual void draw( void );       // Required method in base class
+};
+
+typedef guage_instr * pGuageInst;
+//
+// dual_instr_item         This class was created to form the base class
+//                         for both panel and HUD Turn Bank Indicators.
+
+class dual_instr_item : public instr_item {
+  private:
+    DBLFNPTR alt_data_source;
+
+  public:
+    dual_instr_item ( RECT         the_box,
+                      DBLFNPTR     chn1_source,
+                      DBLFNPTR     chn2_source,
+                      bool         working     = true,
+                      ReadOriented readway  = ReadTOP);
+
+    virtual ~dual_instr_item() {};
+    dual_instr_item( const dual_instr_item & image);
+    dual_instr_item & operator = (const dual_instr_item & rhs );
+
+    double current_ch1( void ) { return alt_data_source();}
+    double current_ch2( void ) { return get_value();}
+    virtual void draw ( void ) { }
+};
+
+class fgTBI_instr : public dual_instr_item {
+  private:
+    UINT BankLimit;
+    UINT SlewLimit;
+    UINT scr_hole;
+
+  public:
+    fgTBI_instr( RECT      the_box,
+                 DBLFNPTR  chn1_source  = get_roll,
+                 DBLFNPTR  chn2_source  = get_sideslip,
+                 UINT      maxBankAngle = 45,
+                 UINT      maxSlipAngle =  5,
+                 UINT      gap_width    =  5,
+                 bool      working      =  true);
+
+    fgTBI_instr( const fgTBI_instr & image);
+    fgTBI_instr & operator = (const fgTBI_instr & rhs );
+
+    ~fgTBI_instr();
+
+    UINT bank_limit( void ) { return BankLimit;}
+    UINT slew_limit( void ) { return SlewLimit;}
+
+    virtual void draw( void );       // Required method in base class
+};
+
+typedef fgTBI_instr * pTBI;
+
+class HudLadder : public dual_instr_item {
+  private:
+    UINT   width_units;
+    int    div_units;
+    UINT   minor_div;
+    UINT   label_pos;
+    UINT   scr_hole;
+    int    vmax;
+    int    vmin;
+    double factor;
+
+  public:
+    HudLadder( RECT      the_box,
+               DBLFNPTR  ptch_source    = get_roll,
+               DBLFNPTR  roll_source    = get_pitch,
+               UINT      span_units     = 45,
+               int       division_units = 10,
+               UINT      minor_division = 0,
+               UINT      screen_hole    = 70,
+               UINT      lbl_pos        = 0,
+               bool      working        = true );
+
+    ~HudLadder();
+
+    HudLadder( const HudLadder & image );
+    HudLadder & operator = ( const HudLadder & rhs );
+    virtual void draw( void );
+};
+
+
+//using namespace std;
+//deque <instr_item>  * Hdeque_ptr;
+
+extern int  fgHUDInit( fgAIRCRAFT * /* current_aircraft */ );
+extern void fgUpdateHUD( void );
 
 /*
-Hptr fgHUDAddLadder ( Hptr hud,
-                      int scr_min,
-                      int scr_max,
-                      int div_min,
-                      int div_max, \
-                                                   int orientation,
-                      int max_value,
-                      double *(load_value);
-
-Hptr fgHUDAddCircularLadder( Hptr hud,
-                             int scr_min,
-                             int scr_max,
-                             int div_min,
-                             int div_max, \
-                                                          int max_value,
-                             double *(load_value) );
-
-Hptr fgHUDAddNumDisp( Hptr hud,
-                      int x_pos,
-                      int y_pos,
-                      int size,
-                      int blink, \
-                                                   char *pre_str,
-                      char *post_str,
-                      double *(load_value) );
-*/
+bool AddHUDInstrument( instr_item *pBlackBox );
+void DrawHUD ( void );
+bool DamageInstrument( INSTR_HANDLE unit );
+bool RepairInstrument( INSTR_HANDLE unit );
+
 
 void fgUpdateHUD ( Hptr hud );
 void fgUpdateHUD2( Hptr hud ); // Future use?
+void fgHUDSetTimeMode( Hptr hud, int time_of_day );
+*/
 
-
-#endif // _HUD_HXX
+#endif // _HUD_H
 
 /* $Log$
-/* Revision 1.1  1998/04/24 00:45:58  curt
-/* C++-ifing the code a bit.
+/* Revision 1.2  1998/05/11 18:13:12  curt
+/* Complete C++ rewrite of all cockpit code by Charlie Hotchkiss.
 /*
  * Revision 1.15  1998/02/23 19:07:57  curt
  * Incorporated Durk's Astro/ tweaks.  Includes unifying the sun position
@@ -405,6 +461,9 @@ void fgUpdateHUD2( Hptr hud ); // Future use?
  * Revision 1.11  1998/02/16 13:38:42  curt
  * Integrated changes from Charlie Hotchkiss.
  *
+ * Revision 1.11  1998/02/16 13:38:42  curt
+ * Integrated changes from Charlie Hotchkiss.
+ *
  * Revision 1.10  1998/02/12 21:59:42  curt
  * Incorporated code changes contributed by Charlie Hotchkiss
  * <chotchkiss@namg.us.anritsu.com>