[comp.sources.misc] v09i014: FPLAN 4/6

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (11/27/89)

Posting-number: Volume 9, Issue 14
Submitted-by: tynor@prism.gatech.edu (Steve Tynor)
Archive-name: fplan/part04

#This is part 4/6 of FPLAN
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#	Packed Mon Nov 20 19:28:39 EST 1989 by gaffa!tynor
#	from directory /files/home/users/tynor/src/fplan
#
#	Run the following text with /bin/sh to create:
#	  output.c
#
echo "x - extracting output.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > output.c &&
X/*
X * $Id: output.c,v 2.10 89/11/11 19:09:29 tynor Exp $
X *----------------------------------------------------------------------------
X *	FPLAN - Flight Planner
X *	Steve Tynor
X *	tynor@prism.gatech.edu
X *
X *	This program is in the public domain. Permission to copy,
X * distribute, modify this program is hearby given as long as this header
X * remains. If you redistribute this program after modifying it, please
X * document your changes so that I do not take the blame (or credit) for
X * those changes.  If you fix bugs or add features, please send me a
X * patch so that I can keep the 'official' version up-to-date.
X *
X *	Bug reports are welcome and I'll make an attempt to fix those
X * that are reported.
X *
X *	USE AT YOUR OWN RISK! I assume no responsibility for any
X * errors in this program, its database or documentation. I will make an
X * effort to fix bugs, but if you crash and burn because, for example,
X * fuel estimates in this program were inaccurate, it's your own fault
X * for trusting somebody else's code! Remember, as PIC, it's _your_
X * responsibility to do complete preflight planning. Use this program as
X * a flight planning aid, but verify its results before using them.
X *----------------------------------------------------------------------------
X */
X
Xstatic char rcsid[] = "$Id: output.c,v 2.10 89/11/11 19:09:29 tynor Exp $";
X
X#include <math.h>
X#include <stdio.h>
X#include "mystring.h"
X#include "wp_info.h"
X
Xextern double decimal_2_degrees_mins();
X
Xtypedef enum {
X   END_OF_FORMAT,	/* we count on ((int)END_OF_FORMAT == 0) */
X   CITY, NAME, COMMENT, ELEV, FREQ, TYPE, DESIG, 
X   TC, MC, MH, WIND, DIST_LEG, DIST, DIST_REMAIN,
X   ETA_LEG, ETA, ATA, FUEL_AMT, FUEL_RATE, FUEL_LEG, ALT,
X   TAS, EGS, AGS, VOR_DESIG, VOR_FREQ, VOR_RADIAL, LAT_LONG, VOR_DME,
X   IGNORE, EMPTY, FORWARD_ARROW, BACKWARD_ARROW, 
X   SEPARATOR, BAR, CROSS, EOL, END_OF_VOR,
X   } FORMAT_KIND;
X
Xchar *headers[] = 
X{
X   "", "CITY", "CHECKPOINT", "COMMENT", "ELEV", "FREQ", "TYPE", "DESIG", 
X   "TC", "MC", "MH", "WIND", "DIST", "DIS", "REM",
X   "ETE", "ETE", "ATE", "FUEL", "RATE", "FUEL", "ALT",
X   "TAS", "EGS", "AGS", "VOR", "FREQ", "RAD", "LAT/LONG", "DME", "", "",
X};
X
Xtypedef enum {R, L} JUSTIFICATION;
X
Xtypedef enum {U,S} UNSHIFTED_OR_SHIFTED;
X
Xtypedef struct {
X   FORMAT_KIND	 	kind;
X   int		 	field_width;
X   JUSTIFICATION 	justification;
X   int		 	arg;	/* which_vor or num_decimal_points */
X   UNSHIFTED_OR_SHIFTED	shifted;
X} FORMAT_SPEC_CELL;
X
X/*
X * default format (for narrow output (e.g. to terminals) the VORs are not 
X * output)
X *
X *                                                            VOR1    VOR2
X *+=========//==============+===+=====+                            +=======+
X *|NAME     //    TYPE DESIG|   | FUEL|                            |    VOR|
X *|CITY     //      ALT FREQ|DIS|  ETE|======+===+====+====+=======|   FREQ|
X *|COMMENT  //      LAT/LONG|REM|  ATE|    MC|TAS|DIST| ALT|    VOR|RAD DME|
X *+=========//==============+===+=====>  WIND|EGS| ETE|RATE|   FREQ<-------+
X *|         //              |   |     |    MH|AGS| ATE|FUEL|RAD DME|       |
X *|         //              |   |     |======+===+====+====+=======|       |
X *|         //              |   |     |      |   |    |    |       |       |
X *+---------//--------------+---+----->      |   |    |    |       <-------+
X *|         //              |   |     |      |   |    |    |       |       |
X *|         //              |   |     |------+---+----+----+-------|       |
X */
X
X#define MAX_NUM_FIELDS 170
X
XFORMAT_SPEC_CELL default_format_wide [] = 
X{
X   /* line 0 */
X   /* WAYPOINT INFO */
X   {CROSS},{SEPARATOR,44,L},{CROSS},
X   {SEPARATOR,3}, {CROSS}, {SEPARATOR,5},{FORWARD_ARROW},
X
X   /* LEG INFO */
X   {WIND,6,R,0,S},{BAR,1,R,0,S},{EGS,3,R,0,S},{BAR,1,R,0,S},
X   {ETA_LEG,4,R,0,S},{BAR,1,R,0,S},{FUEL_RATE,5,R,1,S},{BAR,1,R,0,S},
X   {END_OF_VOR,1,R,0,U},{VOR_FREQ,8,R,0,S},{BACKWARD_ARROW,1,R,0,U},
X   /* WAYPOINT INFO */
X   {END_OF_VOR,1,R,1,U},{SEPARATOR,8,R,1,U},{CROSS},
X   {END_OF_VOR,1,R,2,U},{SEPARATOR,8,R,2,U},{CROSS},
X   {END_OF_VOR,1,R,3,U},{SEPARATOR,8,R,3,U},{CROSS},
X   {END_OF_VOR,1,R,4,U},{SEPARATOR,8,R,4,U},{CROSS},
X   {END_OF_VOR,1,R,5,U},{SEPARATOR,8,R,5,U},{CROSS},
X   {END_OF_VOR,1,R,6,U},{SEPARATOR,8,R,6,U},{CROSS},
X   {END_OF_VOR,1,R,7,U},{SEPARATOR,8,R,7,U},{CROSS},
X   {EOL}, 
X
X   /* line 1 */
X   /* WAYPOINT INFO */
X   {BAR},{NAME,32,L},{ELEV,5},{EMPTY,1},{DESIG,6},{BAR},
X   {EMPTY,3}, {BAR}, {FUEL_AMT,5,R,1},{BAR},
X   /* LEG INFO */
X   {MH,6,R,0,S},{BAR,1,R,0,S},{AGS,3,R,0,S},{BAR,1,R,0,S},
X   {ATA,4,R,0,S},{BAR,1,R,0,S},{FUEL_LEG,5,R,1,S},{BAR,1,R,0,S},
X   {VOR_RADIAL,4,L,0,S},
X   {VOR_DME,4,R,0,S},{BAR,1,R,0,U},
X   /* WAYPOINT INFO */
X   {VOR_DESIG,8,R,1,U},{BAR},
X   {VOR_DESIG,8,R,2,U},{BAR},
X   {VOR_DESIG,8,R,3,U},{BAR},
X   {VOR_DESIG,8,R,4,U},{BAR},
X   {VOR_DESIG,8,R,5,U},{BAR},
X   {VOR_DESIG,8,R,6,U},{BAR},
X   {VOR_DESIG,8,R,7,U},{BAR},
X   {EOL}, 
X
X   /* line 2 */
X   /* WAYPOINT INFO */
X   {BAR},{CITY,29,L},{TYPE,8},{EMPTY,1},{FREQ,6},{BAR},
X   {DIST,3}, {BAR},{ETA,5},{BAR},
X   /* LEG INFO */
X   {SEPARATOR,6,R,0,U},{CROSS,1,R,0,U},{SEPARATOR,3,R,0,U},{CROSS,1,R,0,U},
X   {SEPARATOR,4,R,0,U},{CROSS,1,R,0,U},{SEPARATOR,5,R,0,U},{CROSS,1,R,0,U},
X   {END_OF_VOR,1,R,0,U},{SEPARATOR,8,R,0,U},{BAR,1,R,0,U},
X   /* WAYPOINT INFO */
X   {VOR_FREQ,8,R,1,U},{BAR},
X   {VOR_FREQ,8,R,2,U},{BAR},
X   {VOR_FREQ,8,R,3,U},{BAR},
X   {VOR_FREQ,8,R,4,U},{BAR},
X   {VOR_FREQ,8,R,5,U},{BAR},
X   {VOR_FREQ,8,R,6,U},{BAR},
X   {VOR_FREQ,8,R,7,U},{BAR},
X   {EOL}, 
X
X   /* line 3 */
X   /* WAYPOINT INFO */
X   {BAR},{COMMENT,26,L},{LAT_LONG,18},{BAR},
X   {DIST_REMAIN,3}, {BAR},{ATA,5},{BAR},
X   /* LEG INFO */
X   {MC,6,R,0,S},{BAR,1,R,0,S},{TAS,3,R,0,S},{BAR,1,R,0,S},
X   {DIST_LEG,4,R,0,S},{BAR,1,R,0,S},{ALT,5,R,0,S},{BAR,1,R,0,S},
X   {VOR_DESIG,8,R,0,S},{BAR,1,R,0,U},
X   /* WAYPOINT INFO */
X   {VOR_RADIAL,4,L,1,U}, {VOR_DME,4,R,1,U},{BAR},
X   {VOR_RADIAL,4,L,2,U}, {VOR_DME,4,R,2,U},{BAR},
X   {VOR_RADIAL,4,L,3,U}, {VOR_DME,4,R,3,U},{BAR},
X   {VOR_RADIAL,4,L,4,U}, {VOR_DME,4,R,4,U},{BAR},
X   {VOR_RADIAL,4,L,5,U}, {VOR_DME,4,R,5,U},{BAR},
X   {VOR_RADIAL,4,L,6,U}, {VOR_DME,4,R,6,U},{BAR},
X   {VOR_RADIAL,4,L,7,U}, {VOR_DME,4,R,7,U},{BAR},
X   {EOL}, 
X   {END_OF_FORMAT}
X};
X
X#ifdef OLD_FORMAT
X/*
X * Default wide column format:
X *
X+-------------//--------------+------+---+----+-----+-----+-----+-----+
X|NAME         //    TYPE DESIG|    MC|TAS| LEG|  LEG|  ALT|  VOR|  VOR|
X|CITY         //      ALT FREQ|  WIND|EGS|DIST|  ETA| RATE| FREQ| FREQ|
X|COMMENT      //      LAT/LONG|    MH|AGS| REM|  ATA| FUEL|  RAD|  RAD|
X+-------------//--------------+------+---+----+-----+-----+-----+-----+
X *
X * narrow column format is the same - without the last 2 fields
X */
X
XFORMAT_SPEC_CELL default_format_wide [MAX_NUM_FIELDS] = 
X{
X   {BAR},{NAME,33,L},{TYPE,11},{EMPTY,1},{DESIG,6},{BAR},
X   {MC,6},{BAR},{TAS,3},{BAR},
X   {DIST_LEG,4},{BAR},{ETA_LEG,5},{BAR},{ALT,5},{BAR},
X   {VOR_DESIG,6,R,0},{BAR},{VOR_DESIG,6,R,1},{BAR},
X   {EOL}, 
X
X   {BAR},{CITY,33,L},{ELEV,11},{EMPTY,1},{FREQ,6,R,1},{BAR},
X   {WIND,6},{BAR},{EGS,3},{BAR},
X   {DIST,4},{BAR},{ETA,5},{BAR},{FUEL_RATE,5,R,1},{BAR},
X   {VOR_FREQ,6,R,0},{BAR},{VOR_FREQ,6,R,1},{BAR},
X   {EOL},
X
X   {BAR},{COMMENT,33,L},{LAT_LONG,18},
X   {BAR},{MH,6},{BAR},{AGS,3},{BAR},
X   {DIST_REMAIN,4},{BAR},{ATA,5},{BAR},{FUEL_AMT,5,R,1},{BAR},
X   {VOR_RADIAL,6,R,0},{BAR},{VOR_RADIAL,6,R,1},{BAR},
X   {EOL},
X
X   {END_OF_FORMAT}
X};
X#endif
X
XFORMAT_SPEC_CELL output_format [MAX_NUM_FIELDS];
X
Xint line_num;
X
Xenum {NAUTICAL, STATUTE} output_units = NAUTICAL;
X/*
X * the only things affected by the output_format are:
X * speeds (TAS, GS) and distance (DIST, DIST_LEG, DIST_REMAIN)
X * All are internally stored as knots and km.
X */
X#define NM_OR_MI(a) ((output_units == NAUTICAL) ? (a) : (a) * MI_PER_NM)
X
X#define EPSON_CROSS		197
X#define EPSON_VERTICAL_BAR	179
X#define EPSON_HORIZONTAL_BAR	196
X#define EPSON_FORWARD_ARROW	180
X#define EPSON_BACKWARD_ARROW	195
Xstatic BOOLEAN use_epson_box_chars = FALSE;
X
X/*----------------------------------------------------------------------------*/
Xvoid set_output_units (nautical)
X     int nautical;
X{
X   if (nautical)
X      output_units = NAUTICAL;
X   else
X      output_units = STATUTE;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_format (max_nav, epson)
X     int max_nav;
X     BOOLEAN epson;
X{
X   int i;
X   FORMAT_SPEC_CELL *spec = default_format_wide;
X
X   use_epson_box_chars = epson;
X   for (i = 0; i < MAX_NUM_FIELDS; i++) {
X      if (((spec[i].kind == END_OF_VOR) ||
X	   (spec[i].kind == VOR_DESIG) ||
X	   (spec[i].kind == VOR_FREQ) ||
X	   (spec[i].kind == VOR_DME) ||
X	   (spec[i].kind == VOR_RADIAL))
X	  && 
X	  (max_nav < spec[i].arg)) {
X	 for (; (spec[i].kind != EOL) && (i < MAX_NUM_FIELDS); i++) {
X	    output_format[i].kind = IGNORE;
X	 }
X	 i--;
X      } else {
X	 output_format[i] = spec[i];
X      }
X   }
X#if 0
X   output_format[i] = spec[i];
X#endif
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic void put_time (out_fp, field_width, hours)
X     FILE   *out_fp;
X     int    field_width;
X     double hours;
X{
X   char   buffer[30];
X   int    h       = (int) hours;
X   double minutes = hours * 60.0;
X
X   if (h > 0) {
X      sprintf (buffer, "%d:%02.0f", h, minutes - h * 60.0);
X      fprintf (out_fp, "%*s", field_width, buffer);
X   } else {
X      fprintf (out_fp, "%*.0f", field_width, minutes);
X   }
X}
X/*----------------------------------------------------------------------------*/
Xstatic void put_string (out_fp, fw, str)
XFILE *out_fp;
Xint fw;
Xchar *str;
X{
X   /*
X    * force a string to fit in the specified field width. if we have to 
X    * truncate, then indicate the truncation with a '>' in the last position
X    */
X
X   char buffer[100];
X
X   strncpy (buffer, str, ABS (fw));
X   if (strlen (str) > ABS(fw))
X      buffer[ABS (fw)-1] = '>';
X   buffer[ABS (fw)] = '\0';
X#ifdef MSDOS
X   /* 
X    * both the Microsoft and Zortech compilers generate incorrect output for
X    * negative field widths.
X    */
X   {
X      int i;
X      int xtra = ABS(fw) - strlen (buffer);
X      
X      if (fw > 0)
X	 for (i = 0; i < xtra; i++)
X	    fprintf (out_fp, " ");
X      fprintf (out_fp, "%s", buffer);
X      if (fw < 0)
X	 for (i = 0; i < xtra; i++)
X	    fprintf (out_fp, " ");
X   }
X#else
X   fprintf (out_fp, "%*s", fw, buffer);
X#endif
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic void put_lat_long (out_fp, fw, latitude, longitude)
X     FILE   *out_fp;
X     int    fw;
X     double latitude, longitude;
X{
X   char buffer [100];
X   sprintf (buffer, "[%c%3.3lf,%c%3.3lf]", 
X	    (latitude > 0.0) ? 'N' : 'S',
X	    fabs ((double) decimal_2_degrees_mins (latitude)),
X	    (longitude > 0.0) ? 'W' : 'E',
X	    fabs ((double) decimal_2_degrees_mins (longitude)));
X   fprintf (out_fp, "%*s", fw, buffer);
X}
X/*----------------------------------------------------------------------------*/
Xstatic void put_db_mode (out_fp, fw, mode)
X     FILE 	   *out_fp;
X     int           fw;
X     WAYPOINT_MODE mode;
X{
X   char *str_val;
X
X   switch (mode) {
X   case WP_AIRPORT:
X      str_val = "Airport";
X      break;
X   case WP_VOR:
X      str_val = "VOR";
X      break;
X   case WP_NAMED_INTERSECTION:
X   case WP_INTERSECTION:
X      str_val = "Intersection";
X      break;
X   case WP_INCREMENTAL:
X      str_val = "Incremental";
X      break;
X   case WP_LAT_LONG:
X      str_val = "Lat/Long";
X      break;
X   case WP_NDB:
X      str_val = "NDB";
X      break;
X   case WP_DME:
X      str_val = "VOR/DME";
X      break;
X   case WP_TAC:
X      str_val = "TACAN";
X      break;
X   case WP_ILS:
X      str_val = "ILS";
X      break;
X   case WP_WPT:
X      str_val = "Waypoint";
X      break;
X   case WP_LOM:
X      str_val = "Outer Mkr";
X      break;
X   case WP_LMM:
X      str_val = "Middle Mkr";
X      break;
X   default:
X      break;
X   }
X   put_string (out_fp, fw, str_val);
X}
X/*----------------------------------------------------------------------------*/
Xstatic void put_header_cell (out_fp, cell, force)
X     FILE *out_fp;
X     FORMAT_SPEC_CELL cell;
X     BOOLEAN force;
X{
X   int fw = ((cell.justification == R) ? cell.field_width :
X	     -1 * cell.field_width);
X
X
X   if ((cell.kind == IGNORE) || (cell.kind == END_OF_VOR))
X      return;
X
X   if (cell.kind == EOL) {
X      line_num++;
X      fprintf (out_fp, "\n");
X      return;
X   }
X
X   if ((!force) &&(cell.shifted == S) && ((line_num == 0) || (line_num == 1))) {
X      put_string (out_fp, cell.field_width, "");
X      return;
X   }
X
X   switch (cell.kind) {
X   case BAR:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_VERTICAL_BAR : '|');
X      break;
X   case FORWARD_ARROW:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_FORWARD_ARROW : '+');
X      break;
X   case BACKWARD_ARROW:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_BACKWARD_ARROW : '+');
X      break;
X   case CROSS:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_CROSS : '+');
X      break;
X   case SEPARATOR:
X      { 
X	 int i;
X	 for (i = 0; i < cell.field_width; i++)
X	    fprintf (out_fp, "%c", 
X		     use_epson_box_chars ? EPSON_HORIZONTAL_BAR : '-');
X      }
X      break;
X   default:
X      put_string (out_fp, fw, headers[(int) cell.kind]);
X   }
X}
X
X
X/*----------------------------------------------------------------------------*/
Xstatic void put_info_cell (out_fp, cell, prev_wp, curr_wp)
X     FILE             *out_fp;
X     FORMAT_SPEC_CELL cell;
X     WAYPOINT_INFO    *prev_wp, *curr_wp;
X{ 
X   WAYPOINT_INFO *wp;
X
X   int fw = ((cell.justification == R) ? cell.field_width :
X	     -1 * cell.field_width);
X   char   *str_val;
X   double d_val;
X   char buffer[80];
X   BOOLEAN valid;
X   
X   if ((cell.kind == IGNORE) || (cell.kind == END_OF_VOR))
X      return;
X   if ((cell.shifted == S) &&
X	((line_num == 0) || (line_num == 1))) {
X      if (! prev_wp) {
X	 put_header_cell (out_fp, cell, TRUE);
X	 return;
X      } else
X	 wp = prev_wp;
X   } else
X      wp = curr_wp;
X
X   if ((cell.shifted == S) && (wp->wp_kind == WP_TO)) {
X      put_string (out_fp, cell.field_width, "");
X      return;
X   }
X
X   switch (cell.kind) {
X   case EOL:
X      line_num++;
X      fprintf (out_fp, "\n");
X      break;
X   case BAR:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_VERTICAL_BAR : '|');
X      break;
X   case CROSS:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_CROSS : '+');
X      break;
X   case FORWARD_ARROW:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_FORWARD_ARROW : '>');
X      break;
X   case BACKWARD_ARROW:
X      fprintf (out_fp, "%c", use_epson_box_chars ? EPSON_BACKWARD_ARROW : '<');
X      break;
X   case SEPARATOR:
X      { 
X	 int i;
X	 for (i = 0; i < cell.field_width; i++)
X	    fprintf (out_fp, "%c", 
X		     use_epson_box_chars ? EPSON_HORIZONTAL_BAR : '-');
X      }
X      break;
X      /*
X       * strings
X       */
X   case NAME:
X   case CITY:
X   case COMMENT:
X   case DESIG:
X   case VOR_DESIG:
X      switch (cell.kind) {
X      case CITY:
X	 valid = TRUE;
X	 str_val = wp->db->city;
X	 break;
X      case NAME:
X	 valid = TRUE;
X	 str_val = wp->db->name;
X	 break;
X      case COMMENT:
X	 valid = TRUE;
X	 str_val = wp->db->comment;
X	 break;
X      case DESIG:
X	 valid = TRUE;
X	 str_val = wp->db->desig;
X	 break;
X      case VOR_DESIG:
X	 valid   = wp->vor_fix [cell.arg].valid;
X	 if (valid)
X	    str_val = wp->vor_fix [cell.arg].db->desig;
X	 break;
X      default:
X	 valid   = FALSE;
X	 str_val = NULL;
X	 break;
X      }
X      if (! str_val)
X	 valid = FALSE;
X      if (valid) {
X	 put_string (out_fp, fw, str_val);
X      } else
X	 fprintf (out_fp, "%*s", fw, "");
X      break;
X      /*
X       * headings
X       */
X   case MH:
X   case MC:
X   case TC:
X      switch (cell.kind) {
X      case MH:
X	 valid = wp->mh.valid;
X	 d_val = wp->mh.value;
X	 break;
X      case MC:
X	 valid = wp->mc.valid;
X	 d_val = wp->mc.value;
X	 break;
X      case TC:
X	 valid = wp->tc.valid;
X	 d_val = wp->tc.value;
X	 break;
X      default:
X	 break;
X      }
X      if (valid) {
X	 sprintf (buffer, "%03.*f", cell.arg, d_val);
X	 fprintf (out_fp, "%*s", fw, buffer);
X      } else {
X	 fprintf (out_fp, "%*s", fw, "");
X      }
X      break;
X      /*
X       * numbers
X       */
X   case FREQ:
X   case VOR_FREQ:
X      switch (cell.kind) {
X      case VOR_FREQ:
X	 valid = wp->vor_fix [cell.arg].valid;
X	 if (valid) 
X	    d_val = wp->vor_fix [cell.arg].db->freq.value;
X	 break;
X      case FREQ:
X	 valid = wp->db->freq.valid;
X	 d_val = wp->db->freq.value;
X	 break;
X      default:
X	 valid = FALSE;
X	 break;
X      }
X      if (valid) {
X	 fprintf (out_fp, "%*.2f", fw, d_val);
X      } else
X	 fprintf (out_fp, "%*s", fw, "");
X      break;
X   case ELEV:
X   case TAS:
X   case EGS:
X   case FUEL_AMT:
X   case FUEL_LEG:
X   case FUEL_RATE:
X   case DIST_LEG:
X   case DIST:
X   case DIST_REMAIN:
X      switch (cell.kind) {
X      case ELEV:
X	 valid = wp->db->altitude.valid;
X	 d_val = wp->db->altitude.value;
X	 break;
X      case TAS:
X	 valid = wp->tas.valid;
X	 d_val = NM_OR_MI (wp->tas.value); 
X	 break;
X      case EGS:
X	 valid = wp->egs.valid;
X	 d_val = NM_OR_MI (wp->egs.value);
X	 break;
X      case FUEL_AMT:
X	 valid = wp->fuel_amt.valid;
X	 d_val = wp->fuel_amt.value;
X	 break;
X      case FUEL_LEG:
X	 valid = wp->fuel_leg.valid;
X	 d_val = wp->fuel_leg.value;
X	 break;
X      case FUEL_RATE:
X	 valid = wp->fuel_rate.valid;
X	 d_val = wp->fuel_rate.value;
X	 break;
X      case DIST_LEG:
X	 valid = wp->dist_leg.valid;
X	 d_val = NM_OR_MI (wp->dist_leg.value);
X	 break;
X      case DIST:
X	 valid = wp->dist.valid;
X	 d_val = NM_OR_MI (wp->dist.value);
X	 break;
X      case DIST_REMAIN:
X	 valid = wp->dist_remain.valid;
X	 d_val = NM_OR_MI (wp->dist_remain.value);
X	 break;
X      default:
X	 valid = FALSE;
X	 d_val = 0.0;
X	 break;
X      }
X      if (valid) {
X	 fprintf (out_fp, "%*.*f", fw, cell.arg, d_val);
X      } else
X	 fprintf (out_fp, "%*s", fw, "");
X      break;
X      /*
X       * times:
X       */
X   case ETA:
X   case ETA_LEG:
X      valid = (cell.kind == ETA) ? wp->eta.valid : wp->eta_leg.valid;
X      d_val = (cell.kind == ETA) ? wp->eta.value : wp->eta_leg.value;
X      if (valid)
X	 put_time (out_fp, fw, d_val);
X      else
X	 fprintf (out_fp, "%*s", fw, "");
X      break;
X   case VOR_DME:
X      if (wp->vor_fix[cell.arg].valid)
X	 fprintf (out_fp, "%*.0lf", fw, wp->vor_fix[cell.arg].distance);
X      else
X	 fprintf (out_fp, "%*s", fw, "");
X      break;
X   case VOR_RADIAL:
X      if (wp->vor_fix[cell.arg].valid) {
X	 sprintf (buffer, "%03.0f%c", wp->vor_fix[cell.arg].heading, 
X		  (wp->vor_fix[cell.arg].from_to == FROM ? 'F' : 'T') );
X	 fprintf (out_fp, "%*s", fw, buffer);
X      } else {
X	 fprintf (out_fp, "%*s", fw, "");
X      }
X      break;
X   case LAT_LONG:
X      put_lat_long (out_fp, fw, wp->db->latitude, wp->db->longitude);
X      break;
X   case ALT:
X      if (! wp->altitude.valid) {
X	 fprintf (out_fp, "%*s", fw, "");
X#if 0
X      } else if (wp->altitude.value < 1000.0) {
X	 sprintf (buffer, "FL%g", wp->altitude.value);
X	 fprintf (out_fp, "%*s", fw, buffer);
X#endif
X      } else {
X	 fprintf (out_fp, "%*.0f", fw, wp->altitude.value);
X      }
X      break;
X   case WIND:
X      if (wp->wind_direction.valid && wp->wind_speed.valid) {
X	 sprintf (buffer, "%03.0f@%02.0f", wp->wind_direction.value, 
X		  wp->wind_speed.value);
X	 fprintf (out_fp, "%*s", fw, buffer);
X      } else {
X	 fprintf (out_fp, "%*s", fw, "");
X      }
X      break;
X   case TYPE:
X      put_db_mode (out_fp, fw, wp->db->mode);
X      break;
X   case EMPTY:
X   case ATA:
X   case AGS:
X   default:
X      fprintf (out_fp, "%*s", fw, "");
X      break;
X   }    
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic void put_info_cells (out_fp, cells, prev_wp, wp)
X     FILE             *out_fp;
X     FORMAT_SPEC_CELL cells[];
X     WAYPOINT_INFO    *prev_wp, *wp;
X{
X   int i;
X
X   line_num = 0;
X   for (i = 0; (cells[i].kind != END_OF_FORMAT); i++) 
X      put_info_cell (out_fp, cells[i], prev_wp, wp);
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic void put_header_cells (out_fp, cells, first_line_only)
X     FILE             *out_fp;
X     FORMAT_SPEC_CELL cells[];
X     BOOLEAN first_line_only;
X{
X   int i;
X
X   line_num = 0;
X   for (i = 0; (cells[i].kind != END_OF_FORMAT); i++) {
X      if (first_line_only && line_num)
X	 return;
X      else
X	 put_header_cell (out_fp, cells[i], FALSE);
X   }
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid print_plan ()
X{
X   int i;
X
X   for (i = 0; i < num_waypoints; i++) {
X      if (waypoints[i].wp_kind == WP_FROM) {
X	 if (i)
X	    fprintf (stdout, "\f");
X	 printf ("\nSpeeds in %s; Distances in %s miles\n",
X		 (output_units == NAUTICAL) ? "knots" : "mph (wind in knots)",
X		 (output_units == NAUTICAL) ? "nautical" : "statute");
X	 put_header_cells (stdout, output_format, FALSE);
X      }
X      put_info_cells (stdout, output_format,
X		      (waypoints[i].wp_kind == WP_FROM) ? 0 : &waypoints[i-1],
X		      &waypoints[i]);
X      if (waypoints[i].wp_kind == WP_TO)
X	 put_header_cells (stdout, output_format, TRUE);
X   }
X}
X
X
X/*----------------------------------------------------------------------------*/
Xput_db (out_fp, db)
X     FILE          *out_fp;
X     DATABASE_INFO *db;
X{
X   fprintf (out_fp, "______________________________________________________________________________\n");
X   fprintf (out_fp, "%s\t", db->desig);
X   put_db_mode (out_fp, -12, db->mode);
X   if (db->name)
X      fprintf (out_fp, "\nNAME   : %s\n", db->name);
X   if (db->city)
X      fprintf (out_fp, "CITY   : %s\n", db->city);
X   if (db->comment)
X      fprintf (out_fp, "COMMENT: %s\n", db->comment);
X   fprintf (out_fp, "LAT/LONG: ");
X   put_lat_long (out_fp, 1, db->latitude, db->longitude);
X   fprintf (out_fp, " MAG VARIATION: %g ", db->mag_variation);
X   if (db->freq.valid)
X      fprintf (out_fp, "FREQ: %7.2f ", db->freq.value);
X   if (db->altitude.valid)
X      fprintf (out_fp, "ALTITUDE: %g", db->altitude.value);
X   fprintf (out_fp, "\n");
X}
SHAR_EOF
chmod 0444 output.c || echo "restore of output.c fails"
exit 0