/********************************************************************
** @source JEEPS input functions
**
** @author Copyright (C) 1999 Alan Bleasby
** @version 1.0
** @modified Dec 28 1999 Alan Bleasby. First version
** @@
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
********************************************************************/
#include "gps.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>


static int32 GPS_Input_Load_String(char* t, int32 n, char* s);
static int32 GPS_Input_Load_Strnull(char* t, char* s);
static int32 GPS_Input_Read_Line(char* s, FILE* inf);

static int32 GPS_Input_Get_D100(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D101(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D102(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D103(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D104(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D105(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D106(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D107(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D108(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D109(GPS_PWay* way, FILE* inf, int protonum);
static int32 GPS_Input_Get_D150(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D151(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D152(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D154(GPS_PWay* way, FILE* inf);
static int32 GPS_Input_Get_D155(GPS_PWay* way, FILE* inf);

static int32 GPS_Input_Get_Track301(GPS_PTrack** trk, FILE* inf, int32 type,
                                    int32 n);
static int32 GPS_Input_Get_D300(GPS_PTrack* trk, FILE* inf, char* s);
static int32 GPS_Input_Get_D301(GPS_PTrack* trk, FILE* inf, char* s);

static int32 GPS_Input_Get_Route201(GPS_PWay** way, FILE* inf);


/* @funcstatic GPS_Input_Load_String ***********************************
**
** Load a GPS char type from an input line
** Remove trailing newline
**
** @param [w] t [char *] string to load
** @param [r] n [int32] maximum type length
** @param [r] s [char *] source line
**
** @return [int32] success
************************************************************************/
static int32 GPS_Input_Load_String(char* t, int32 n, char* s)
{
  char* p;
  char* q;

  int32 len;
  int32 i;

  gps_errno = INPUT_ERROR;

  p=s;
  if (!(p=strchr(p,':'))) {
    return gps_errno;
  }
  ++p;
  while (*p && (*p==' ' || *p=='\t')) {
    ++p;
  }
  if (!*p) {
    return 0;
  }

  len = strlen(p);
  q = p+len-1;
  while (*q==' ' || *q=='\t') {
    --q;
  }
  len = q-p+1;

  if (q-p+1 > n) {
    len = n;
    p[n]='\0';
  }
  for (i=0; i<len; ++i) {
    t[i]=*p++;
  }

  return 1;
}



/* @funcstatic GPS_Input_Load_Strnull **********************************
**
** Load a GPS variable length string type from an input line
** Remove trailing newline
**
** @param [w] t [char *] string to load
** @param [r] s [char *] source line
**
** @return [int32] success
************************************************************************/
static int32 GPS_Input_Load_Strnull(char* t, char* s)
{
  char* p;
  char* q;

  gps_errno = INPUT_ERROR;

  p=s;
  if (!(p=strchr(p,':'))) {
    return gps_errno;
  }
  ++p;
  while (*p && (*p==' ' || *p=='\t')) {
    ++p;
  }

  q = t;
  while ((*q++ = *p++));

  return 1;
}



/* @funcstatic GPS_Input_Read_Line   ************************************
**
** Read line from a file ignoring comments and newlines
** Remove trailing newline
**
** @param [w] s [char *] string
** @param [r] inf [FILE *] stream
**
** @return [int32] success
************************************************************************/

static int32 GPS_Input_Read_Line(char* s, FILE* inf)
{
  int32 len;

  while (fgets(s,GPS_ARB_LEN,inf)) {
    if (*s=='#' || *s=='\n') {
      continue;
    }
    len = strlen(s);
    if (s[len-1]=='\n') {
      s[len-1]='\0';
      return len-1;
    }
    return len;
  }

  return 0;
}



/* @func GPS_Input_Get_Almanac   ****************************************
**
** Construct an almanac array from a file
**
** @param [w] alm [GPS_PAlmanac **] pointer to almanac array
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/

int32 GPS_Input_Get_Almanac(GPS_PAlmanac** alm, FILE* inf)
{
  char s[GPS_ARB_LEN];
  int32 n;
  int32 type;
  int32 i;
  int32   d;
  float f;
  char* p;

  gps_errno = INPUT_ERROR;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }

  if (sscanf(s,"Almanac %d%d",(int*)&n,(int*)&type)!=2) {
    return gps_errno;
  }

  if (!type) {
    if (!(*alm = (GPS_PAlmanac*) malloc(32*sizeof(GPS_PAlmanac*)))) {
      return MEMORY_ERROR;
    }
    for (i=0; i<32; ++i) {
      if (!((*alm)[i] = GPS_Almanac_New())) {
        return MEMORY_ERROR;
      }

      (*alm)[i]->svid = i;
      (*alm)[i]->wn = -1;
    }
  } else {
    if (!(*alm = (GPS_PAlmanac*) malloc(n*sizeof(GPS_PAlmanac*)))) {
      return MEMORY_ERROR;
    }
    for (i=0; i<32; ++i)
      if (!((*alm)[i] = GPS_Almanac_New())) {
        return MEMORY_ERROR;
      }
  }

  for (i=0; i<n; ++i) {
    if (!GPS_Input_Read_Line(s,inf)) {
      if (!type) {
        break;
      } else {
        return gps_error;
      }
    }

    p=strchr(s,':');
    if (sscanf(p+1,"%d",(int*)&d)!=1) {
      return gps_errno;
    }
    --d;

    if (!type)
      while ((*alm)[i]->svid!=d) {
        ++i;
      }
    (*alm)[i]->svid=d;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%d",(int*)&d)!=1) {
      return gps_errno;
    }
    (*alm)[i]->wn = d;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->toa = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->af0 = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->af1 = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->e = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->sqrta = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->m0 = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->w = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->omg0 = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->odot = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%f",&f)!=1) {
      return gps_errno;
    }
    (*alm)[i]->i = f;

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%d",(int*)&d)!=1) {
      return gps_errno;
    }
    (*alm)[i]->hlth=d;
  }

  if (!type) {
    n = 32;
  }

  return n;
}



/* @func GPS_Input_Get_Waypoint *****************************************
**
** Construct a waypoint array from a file
**
** @param [w] way [GPS_PWay **] pointer to waypoint array
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/

int32 GPS_Input_Get_Waypoint(GPS_PWay** way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  int32 n;
  int32 type;
  int32 i;
  long pos;
  int32 ret;

  gps_errno = INPUT_ERROR;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (sscanf(s,"Waypoints Type: %d",(int*)&type)!=1) {
    return gps_errno;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (strncmp(s,"Start",5)) {
    return gps_errno;
  }

  pos = ftell(inf);
  n = 0;
  while (strncmp(s,"End",3)) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    if (strstr(s,"Latitude")) {
      ++n;
    }
  }
  fseek(inf,pos,0);

  if (!(*way=(GPS_PWay*)malloc(n*sizeof(GPS_PWay*)))) {
    return MEMORY_ERROR;
  }
  for (i=0; i<n; ++i) {
    if (!((*way)[i]=GPS_Way_New())) {
      return MEMORY_ERROR;
    }
    (*way)[i]->prot = type;
  }


  for (i=0; i<n; ++i) {
    switch (type) {
    case 100:
      ret = GPS_Input_Get_D100(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 101:
      ret = GPS_Input_Get_D101(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 102:
      ret = GPS_Input_Get_D102(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 103:
      ret = GPS_Input_Get_D103(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 104:
      ret = GPS_Input_Get_D104(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 105:
      ret = GPS_Input_Get_D105(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 106:
      ret = GPS_Input_Get_D106(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 107:
      ret = GPS_Input_Get_D107(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 108:
      ret = GPS_Input_Get_D108(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 109:
      ret = GPS_Input_Get_D109(&((*way)[i]),inf, 109);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 110:
      ret = GPS_Input_Get_D109(&((*way)[i]),inf, 110);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 150:
      ret = GPS_Input_Get_D150(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 151:
      ret = GPS_Input_Get_D151(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 152:
      ret = GPS_Input_Get_D152(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 154:
      ret = GPS_Input_Get_D154(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 155:
      ret = GPS_Input_Get_D155(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    default:
      GPS_Error("Input_Get_Waypoints: Unknown protocol");
      return PROTOCOL_ERROR;
    }
  }

  return n;
}



/* @func GPS_Input_Get_Proximity   *************************************
**
** Construct a proximity waypoint array from a file
**
** @param [w] way [GPS_PWay **] pointer to proximity waypoint array
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/

int32 GPS_Input_Get_Proximity(GPS_PWay** way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  int32 n;
  int32 type;
  int32 i;
  long pos;
  int32 ret;
  double f;
  char* p;

  gps_errno = INPUT_ERROR;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (sscanf(s,"Waypoints Type: %d",(int*)&type)!=1) {
    return gps_errno;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (strncmp(s,"Start",5)) {
    return gps_errno;
  }

  pos = ftell(inf);
  n = 0;
  while (strncmp(s,"End",3)) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    if (strstr(s,"Latitude")) {
      ++n;
    }
  }
  fseek(inf,pos,0);

  if (!(*way=(GPS_PWay*)malloc(n*sizeof(GPS_PWay*)))) {
    return MEMORY_ERROR;
  }
  for (i=0; i<n; ++i) {
    if (!((*way)[i]=GPS_Way_New())) {
      return MEMORY_ERROR;
    }
    (*way)[i]->prot = type;
  }

  for (i=0; i<n; ++i) {
    switch (type) {
    case 400:
      ret = GPS_Input_Get_D100(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 101:
      ret = GPS_Input_Get_D101(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 102:
      ret = GPS_Input_Get_D102(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 403:
      ret = GPS_Input_Get_D103(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 104:
      ret = GPS_Input_Get_D104(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 105:
      ret = GPS_Input_Get_D105(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 106:
      ret = GPS_Input_Get_D106(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 107:
      ret = GPS_Input_Get_D107(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 108:
      ret = GPS_Input_Get_D108(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 109:
      ret = GPS_Input_Get_D109(&((*way)[i]),inf, 109);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 110:
      ret = GPS_Input_Get_D109(&((*way)[i]),inf, 110);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 450:
      ret = GPS_Input_Get_D150(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 151:
      ret = GPS_Input_Get_D151(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 152:
      ret = GPS_Input_Get_D152(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 154:
      ret = GPS_Input_Get_D154(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 155:
      ret = GPS_Input_Get_D155(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    default:
      GPS_Error("Input_Get_Waypoints: Unknown protocol");
      return PROTOCOL_ERROR;
    }

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%lf",&f)!=1) {
      return gps_errno;
    }
    (*way)[i]->dst = f;
  }

  return n;
}



/* @funcstatic GPS_Input_Get_D100   ************************************
**
** Get a D100 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D100(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cmnt,40,s);

  return 1;
}



/* @funcstatic GPS_Input_Get_D101   ************************************
**
** Get a D101 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D101(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cmnt,40,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  return 1;
}



/* @funcstatic GPS_Input_Get_D102   ************************************
**
** Get a D102 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D102(GPS_PWay* way, FILE* inf)
{
  return GPS_Input_Get_D101(way,inf);
}



/* @funcstatic GPS_Input_Get_D103   ************************************
**
** Get a D103 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D103(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cmnt,40,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->dspl = d;

  return 1;
}



/* @funcstatic GPS_Input_Get_D104   ************************************
**
** Get a D104 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D104(GPS_PWay* way, FILE* inf)
{
  return GPS_Input_Get_D103(way,inf);
}



/* @funcstatic GPS_Input_Get_D105   ************************************
**
** Get a D105 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D105(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_Strnull((*way)->wpt_ident,s);

  return 1;
}



/* @funcstatic GPS_Input_Get_D106   ************************************
**
** Get a D106 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D106(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->wpt_class = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((char*)(*way)->subclass,13,s);


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_Strnull((*way)->wpt_ident,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_Strnull((*way)->lnk_ident,s);

  return 1;
}



/* @funcstatic GPS_Input_Get_D107   ************************************
**
** Get a D107 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D107(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  int32 d;
  int32 ret;

  if ((ret=GPS_Input_Get_D103(way,inf))<0) {
    return ret;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->colour = d;

  return 1;
}



/* @funcstatic GPS_Input_Get_D108   ************************************
**
** Get a D108 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D108(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;
  double f;
  int32 d;
  int32 xc;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_Strnull((*way)->ident,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->colour = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->dspl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->alt = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->dpth = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->state,2,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cc,2,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->wpt_class = d;
  xc = d;

  if (xc>=0x80 && xc<=0x85) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((char*)(*way)->subclass,18,s);
  } else {
    GPS_Util_Put_Short((*way)->subclass,0);
    GPS_Util_Put_Int((*way)->subclass+2,0);
    GPS_Util_Put_Uint((*way)->subclass+6,0xffffffff);
    GPS_Util_Put_Uint((*way)->subclass+10,0xffffffff);
    GPS_Util_Put_Uint((*way)->subclass+14,0xffffffff);
  }

  if (!xc) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->cmnt,s);
  }

  if (xc>=0x40 && xc<=0x46) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->facility,s);
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->city,s);
  }

  if (xc==0x83) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->addr,s);
  }

  if (xc==0x82) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->cross_road,s);
  }

  return 1;
}



/* @funcstatic GPS_Input_Get_D109   ************************************
**
** Get a D109 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
** D109's and D110's are so similar, we handle both with the same function.
************************************************************************/
static int32 GPS_Input_Get_D109(GPS_PWay* way, FILE* inf, int protonum)
{
  char s[GPS_ARB_LEN];
  char* p;
  double f;
  int32 d;
  int32 xc;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_Strnull((*way)->ident,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->colour = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->dspl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->alt = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->dpth = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->state,2,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cc,2,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->wpt_class = d;
  xc = d;

  if (xc>=0x80 && xc<=0x85) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((char*)(*way)->subclass,18,s);
  } else {
    GPS_Util_Put_Short((*way)->subclass,0);
    GPS_Util_Put_Int((*way)->subclass+2,0);
    GPS_Util_Put_Uint((*way)->subclass+6,0xffffffff);
    GPS_Util_Put_Uint((*way)->subclass+10,0xffffffff);
    GPS_Util_Put_Uint((*way)->subclass+14,0xffffffff);
  }

  if (!xc) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->cmnt,s);
  }

  if (xc>=0x40 && xc<=0x46) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->facility,s);
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->city,s);
  }

  if (xc==0x83) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->addr,s);
  }

  if (xc==0x82) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_Strnull((*way)->cross_road,s);
  }

  return 1;
}


/* @funcstatic GPS_Input_Get_D150   ************************************
**
** Get a D150 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D150(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;
  int32 cl=0;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cmnt,40,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->wpt_class = cl = d;

  if (cl != 4) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->cc,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->city,24,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->state,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->name,30,s);
  }

  if (!cl) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%d",(int*)&d)!=1) {
      return gps_errno;
    }
    (*way)->alt = d;
  }

  return 1;
}



/* @funcstatic GPS_Input_Get_D151   ************************************
**
** Get a D151 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D151(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;
  int32 cl=0;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cmnt,40,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->wpt_class = cl = d;

  if (cl != 2) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->cc,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->city,24,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->state,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->name,30,s);
  }

  if (!cl) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%d",(int*)&d)!=1) {
      return gps_errno;
    }
    (*way)->alt = d;
  }

  return 1;
}


/* @funcstatic GPS_Input_Get_D152   ************************************
**
** Get a D152 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D152(GPS_PWay* way, FILE* inf)
{
  return GPS_Input_Get_D150(way,inf);
}



/* @funcstatic GPS_Input_Get_D154   ************************************
**
** Get a D154 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D154(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;
  int32 cl=0;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cmnt,40,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->wpt_class = cl = d;

  if (cl != 4 && cl != 8) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->cc,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->city,24,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->state,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->name,30,s);
  }

  if (!cl) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%d",(int*)&d)!=1) {
      return gps_errno;
    }
    (*way)->alt = d;
  }

  return 1;
}



/* @funcstatic GPS_Input_Get_D155   ************************************
**
** Get a D155 Entry
**
** @param [w] way [GPS_PWay *] pointer to waypoint entry
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/
static int32 GPS_Input_Get_D155(GPS_PWay* way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  char* p;

  double f;
  int32 d;
  int32 cl=0;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->ident,6,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*way)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  GPS_Input_Load_String((*way)->cmnt,40,s);

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->smbl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->dspl = d;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%d",(int*)&d)!=1) {
    return gps_errno;
  }
  (*way)->wpt_class = cl = d;

  if (cl != 4 && cl != 8) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->cc,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->city,24,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->state,2,s);

    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    GPS_Input_Load_String((*way)->name,30,s);
  }

  if (!cl) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    p=strchr(s,':');
    if (sscanf(p+1,"%d",(int*)&d)!=1) {
      return gps_errno;
    }
    (*way)->alt = d;
  }

  return 1;
}



/* @func GPS_Input_Get_Track *******************************************
**
** Construct a travk array from a file
**
** @param [w] trk [GPS_PTrack **] pointer to track array
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/

int32 GPS_Input_Get_Track(GPS_PTrack** trk, FILE* inf)
{
  char s[GPS_ARB_LEN];
  int32 n;
  int32 i;
  long pos;
  int32 a;
  int32 d;

  gps_errno = INPUT_ERROR;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (strncmp(s,"Track log",9)) {
    return gps_errno;
  }

  if (sscanf(s,"Track log %d%d",(int*)&a,(int*)&d)!=2) {
    return INPUT_ERROR;
  }


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (strncmp(s,"Start",5)) {
    return gps_errno;
  }

  pos = ftell(inf);
  n = 0;
  while (strncmp(s,"End",3)) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    if (strstr(s,"Latitude")) {
      ++n;
    }
    if (strstr(s,"Header")) {
      ++n;
    }
  }
  fseek(inf,pos,0);


  if (!(*trk=(GPS_PTrack*)malloc(n*sizeof(GPS_PTrack*)))) {
    return MEMORY_ERROR;
  }
  for (i=0; i<n; ++i)
    if (!((*trk)[i]=GPS_Track_New())) {
      return MEMORY_ERROR;
    }


  switch (a) {
  case pA300:
    break;
  case pA301:
    return GPS_Input_Get_Track301(trk, inf, d, n);
  default:
    return INPUT_ERROR;
  }



  for (i=0; i<n; ++i) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }

    if (!strcmp(s,"New track")) {
      (*trk)[i]->tnew=1;
      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
    } else {
      (*trk)[i]->tnew=0;
    }

    switch (d) {
    case pD300:
      GPS_Input_Get_D300(&((*trk)[i]),inf,s);
      break;
    case pD301:
      GPS_Input_Get_D301(&((*trk)[i]),inf,s);
      break;
    default:
      return PROTOCOL_ERROR;
    }
  }

  return n;
}



/* @funcstatic GPS_Input_Get_Track301 **********************************
**
** Construct a travk array from a file
**
** @param [w] trk [GPS_PTrack **] pointer to track array
** @param [r] inf [FILE *] stream
** @param [r] type [int32] data type
** @param [r] n [int32] number of tracks
**
** @return [int32] number of entries
************************************************************************/

static int32 GPS_Input_Get_Track301(GPS_PTrack** trk, FILE* inf, int32 type,
                                    int32 n)
{
  char s[GPS_ARB_LEN];
  int32 i;
  char* p;
  int32 x;

  for (i=0; i<n; ++i) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    if (!strcmp(s,"Header")) {
      (*trk)[i]->ishdr = 1;

      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
      GPS_Input_Load_Strnull((*trk)[i]->trk_ident,s);

      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
      p=strchr(s,':');
      if (sscanf(p+1,"%d",(int*)&x)!=1) {
        return INPUT_ERROR;
      }
      (*trk)[i]->dspl = x;

      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
      p=strchr(s,':');
      if (sscanf(p+1,"%d",(int*)&x)!=1) {
        return INPUT_ERROR;
      }
      (*trk)[i]->colour = x;

      continue;
    }

    (*trk)[i]->ishdr = 0;

    if (!strcmp(s,"New track")) {
      (*trk)[i]->tnew=1;
      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
    } else {
      (*trk)[i]->tnew=0;
    }

    switch (type) {
    case pD300:
      GPS_Input_Get_D300(&((*trk)[i]),inf,s);
      break;
    case pD301:
      GPS_Input_Get_D301(&((*trk)[i]),inf,s);
      break;
    default:
      return PROTOCOL_ERROR;
    }
  }

  return n;
}



/* @funcstatic GPS_Input_Get_D300 **********************************
**
** Construct a track from a file
**
** @param [w] trk [GPS_PTrack *] pointer to track
** @param [r] inf [FILE *] stream
** @param [w] s [char *] input line
**
** @return [int32] number of entries
************************************************************************/

static int32 GPS_Input_Get_D300(GPS_PTrack* trk, FILE* inf, char* s)
{
  char* p;
  double f;

  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*trk)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*trk)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  (*trk)->Time = 0;

  return 1;
}



/* @funcstatic GPS_Input_Get_D301 **********************************
**
** Construct a track from a file
**
** @param [w] trk [GPS_PTrack *] pointer to track
** @param [r] inf [FILE *] stream
** @param [w] s [char *] input line
**
** @return [int32] number of entries
************************************************************************/

static int32 GPS_Input_Get_D301(GPS_PTrack* trk, FILE* inf, char* s)
{
  char* p;
  double f;

  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*trk)->lat = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*trk)->lon = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  (*trk)->Time = 0;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*trk)->alt = f;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  p=strchr(s,':');
  if (sscanf(p+1,"%lf",&f)!=1) {
    return gps_errno;
  }
  (*trk)->dpth = f;

  return 1;
}



/* @func GPS_Input_Get_Route *******************************************
**
** Construct a route array from a file
**
** @param [w] way [GPS_PWay **] pointer to waypoint array
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/

int32 GPS_Input_Get_Route(GPS_PWay** way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  int32 n;
  int32 type;
  int32 rtype=0;
  int32 atype=0;
  int32 i;
  long pos;
  int32 ret;
  char* p;
  int32 d;

  gps_errno = INPUT_ERROR;


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (sscanf(s,"Route log %d",(int*)&atype)!=1) {
    return gps_errno;
  }
  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }

  switch (atype) {
  case pA200:
    break;
  case pA201:
    return GPS_Input_Get_Route201(way,inf);
  default:
    GPS_Error("GPS_Input_Get_Route: Unknown protocol");
    return PROTOCOL_ERROR;
  }


  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (sscanf(s,"Route Type: %d",(int*)&rtype)!=1) {
    return gps_errno;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (sscanf(s,"Waypoints Type: %d",(int*)&type)!=1) {
    return gps_errno;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (strncmp(s,"Start",5)) {
    return gps_errno;
  }

  pos = ftell(inf);
  n = 1;
  while (strncmp(s,"End",3)) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    if (strstr(s,"Latitude") || strstr(s,"Route")) {
      ++n;
    }
  }
  fseek(inf,0L,0);


  if (!(*way=(GPS_PWay*)malloc(n*sizeof(GPS_PWay*)))) {
    return MEMORY_ERROR;
  }
  for (i=0; i<n; ++i) {
    if (!((*way)[i]=GPS_Way_New())) {
      return MEMORY_ERROR;
    }
    (*way)[i]->prot = type;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }

  for (i=0; i<n; ++i) {
    (*way)[i]->rte_prot = rtype;
    (*way)[i]->islink = 0;
    if (strstr(s,"Route")) {
      (*way)[i]->isrte = 1;
      switch (rtype) {
      case 200:
        p = strchr(s,':');
        p = strchr(p+1,':');
        if (sscanf(p+1,"%d",(int*)&d)!=1) {
          return gps_error;
        }
        (*way)[i]->rte_num=d;
        break;
      case 201:
        p = strchr(s,':');
        p = strchr(p+1,':');
        if (sscanf(p+1,"%d",(int*)&d)!=1) {
          return gps_error;
        }
        (*way)[i]->rte_num=d;
        ++p;
        GPS_Input_Load_String((*way)[i]->rte_cmnt,20,p+2);
        break;
      case 202:
        p = strchr(s,':');
        p = strchr(p+1,':');
        GPS_Input_Load_Strnull((*way)[i]->rte_ident,p+1);
        break;
      }
      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
      continue;
    } else {
      (*way)[i]->isrte=0;
    }

    if (strstr(s,"End")) {
      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }

      continue;
    }


    switch (type) {
    case 100:
      ret = GPS_Input_Get_D100(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 101:
      ret = GPS_Input_Get_D101(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 102:
      ret = GPS_Input_Get_D102(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 103:
      ret = GPS_Input_Get_D103(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 104:
      ret = GPS_Input_Get_D104(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 105:
      ret = GPS_Input_Get_D105(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 106:
      ret = GPS_Input_Get_D106(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 107:
      ret = GPS_Input_Get_D107(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 108:
      ret = GPS_Input_Get_D108(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 150:
      ret = GPS_Input_Get_D150(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 151:
      ret = GPS_Input_Get_D151(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 152:
      ret = GPS_Input_Get_D152(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 154:
      ret = GPS_Input_Get_D154(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 155:
      ret = GPS_Input_Get_D155(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    default:
      GPS_Error("Input_Get_Waypoints: Unknown protocol");
      return PROTOCOL_ERROR;
    }

  }

  return n;
}



/* @funcstatic GPS_Input_Get_Route201 ***********************************
**
** Construct a route array from a file
**
** @param [w] way [GPS_PWay **] pointer to waypoint array
** @param [r] inf [FILE *] stream
**
** @return [int32] number of entries
************************************************************************/

static int32 GPS_Input_Get_Route201(GPS_PWay** way, FILE* inf)
{
  char s[GPS_ARB_LEN];
  int32 n;
  int32 type;
  int32 rtype;
  int32 i;
  long pos;
  int32 ret;
  char* p;
  int32 d;

  gps_errno = INPUT_ERROR;

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (sscanf(s,"Route Type: %d",(int*)&rtype)!=1) {
    return gps_errno;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (sscanf(s,"Waypoints Type: %d",(int*)&type)!=1) {
    return gps_errno;
  }


  pos = ftell(inf);
  n = 1;
  while (strncmp(s,"End",3)) {
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
    if (strstr(s,"Latitude") || strstr(s,"Route") || strstr(s,"Link Class")) {
      ++n;
    }
  }
  fseek(inf,0L,0);

  if (!(*way=(GPS_PWay*)malloc(n*sizeof(GPS_PWay*)))) {
    return MEMORY_ERROR;
  }
  for (i=0; i<n; ++i) {
    if (!((*way)[i]=GPS_Way_New())) {
      return MEMORY_ERROR;
    }
    (*way)[i]->prot = type;
  }

  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }
  if (!GPS_Input_Read_Line(s,inf)) {
    return gps_errno;
  }

  for (i=0; i<n; ++i) {
    (*way)[i]->rte_prot = rtype;
    (*way)[i]->islink = 0;
    if (strstr(s,"Route")) {
      (*way)[i]->isrte = 1;
      switch (rtype) {
      case 200:
        p = strchr(s,':');
        p = strchr(p+1,':');
        if (sscanf(p+1,"%d",(int*)&d)!=1) {
          return gps_error;
        }
        (*way)[i]->rte_num=d;
        break;
      case 201:
        p = strchr(s,':');
        p = strchr(p+1,':');
        if (sscanf(p+1,"%d",(int*)&d)!=1) {
          return gps_error;
        }
        (*way)[i]->rte_num=d;
        p = strchr(p+1,':');
        GPS_Input_Load_String((*way)[i]->rte_cmnt,20,p+1);
        break;
      case 202:
        p = strchr(s,':');
        p = strchr(p+1,':');
        GPS_Input_Load_Strnull((*way)[i]->rte_ident,p+1);
        break;
      }
      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
      continue;
    } else {
      (*way)[i]->isrte=0;
    }



    if (strstr(s,"Link Class")) {
      (*way)[i]->islink = 1;

      p = strchr(s,':');
      if (sscanf(p+1,"%d",(int*)&d)!=1) {
        return gps_error;
      }
      (*way)[i]->rte_link_class=d;

      if (!((*way)[i]->rte_link_class==3 || (*way)[i]->rte_link_class
            ==0xff)) {
        if (!GPS_Input_Read_Line(s,inf)) {
          return gps_errno;
        }
        GPS_Input_Load_String((*way)[i]->rte_link_subclass,18,s);
      } else {
        GPS_Util_Put_Short((UC*)(*way)[i]->rte_link_subclass,0);
        GPS_Util_Put_Int((UC*)(*way)[i]->rte_link_subclass+2,0);
        GPS_Util_Put_Uint((UC*)(*way)[i]->rte_link_subclass+6,
                          0xffffffff);
        GPS_Util_Put_Uint((UC*)(*way)[i]->rte_link_subclass+10,
                          0xffffffff);
        GPS_Util_Put_Uint((UC*)(*way)[i]->rte_link_subclass+14,
                          0xffffffff);
      }

      if (!GPS_Input_Read_Line(s,inf)) {
        return gps_errno;
      }
      GPS_Input_Load_Strnull((*way)[i]->rte_link_ident,s);

      continue;
    } else {
      (*way)[i]->islink=0;
    }


    if (strstr(s,"End")) {
      GPS_Error("Get_Route201: Unexpected End");
      return INPUT_ERROR;
    }


    switch (type) {
    case 100:
      ret = GPS_Input_Get_D100(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 101:
      ret = GPS_Input_Get_D101(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 102:
      ret = GPS_Input_Get_D102(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 103:
      ret = GPS_Input_Get_D103(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 104:
      ret = GPS_Input_Get_D104(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 105:
      ret = GPS_Input_Get_D105(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 106:
      ret = GPS_Input_Get_D106(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 107:
      ret = GPS_Input_Get_D107(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 108:
      ret = GPS_Input_Get_D108(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 150:
      ret = GPS_Input_Get_D150(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 151:
      ret = GPS_Input_Get_D151(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 152:
      ret = GPS_Input_Get_D152(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 154:
      ret = GPS_Input_Get_D154(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    case 155:
      ret = GPS_Input_Get_D155(&((*way)[i]),inf);
      if (ret<0) {
        return gps_errno;
      }
      break;
    default:
      GPS_Error("Input_Get_Waypoints: Unknown protocol");
      return PROTOCOL_ERROR;
    }
    if (!GPS_Input_Read_Line(s,inf)) {
      return gps_errno;
    }
  }

  return n;
}
