Index: /trunk/BNC/src/RTCM3/RTCM3Decoder.cpp
===================================================================
--- /trunk/BNC/src/RTCM3/RTCM3Decoder.cpp	(revision 9764)
+++ /trunk/BNC/src/RTCM3/RTCM3Decoder.cpp	(revision 9765)
@@ -1091,4 +1091,5 @@
     eph._fitInterval = fitIntervalFromFlag(fitIntervalFalg, eph._IODC, eph.type());
     eph._TOT = 0.9999e9;
+    eph._navType = t_eph::LNAV;
 
     emit newGPSEph(eph);
@@ -1216,4 +1217,6 @@
     _gloFrq = QString("%1 %2").arg(eph._prn.toString().c_str()).arg(eph._frequency_number, 2, 'f', 0);
 
+    eph._navType = t_eph::FDMA;
+
     emit newGlonassEph(eph);
     decoded = true;
@@ -1299,4 +1302,5 @@
     eph._fitInterval = fitIntervalFromFlag(fitIntervalFalg, eph._IODC, eph.type());
     eph._TOT = 0.9999e9;
+    eph._navType = t_eph::LNAV;
 
     emit newGPSEph(eph);
@@ -1390,4 +1394,5 @@
     SKIPBITS(2)
     eph._TOT = 0.9999e9;
+    eph._navType = t_eph::LNAV;
 
     emit newGPSEph(eph);
@@ -1445,4 +1450,5 @@
     eph._TOT = 0.9999E9;
     eph._health = 0;
+    eph._navType = t_eph::SBASL1;
 
     emit newSBASEph(eph);
@@ -1529,4 +1535,5 @@
         return false;
       }
+      eph._navType = t_eph::INAF;
     }
     else {
@@ -1540,4 +1547,5 @@
       GETBITS(eph._E5aHS, 2)
       GETBITS(eph._e5aDataInValid, 1)
+      eph._navType = t_eph::FNAV;
     }
     eph._TOT = 0.9999e9;
@@ -1562,4 +1570,5 @@
 bool RTCM3Decoder::DecodeBDSEphemeris(unsigned char* data, int size) {
   bool decoded = false;
+  const double iMaxGEO = 10.0 / 180.0 * M_PI;
 
   if (size == 70) {
@@ -1622,4 +1631,12 @@
 
     eph._TOT = 0.9999E9;
+    if (eph._i0 > iMaxGEO) {
+      eph._navType = t_eph::D1;
+    }
+    else {
+      eph._navType = t_eph::D2;
+    }
+
+
     emit newBDSEph(eph);
     decoded = true;
Index: /trunk/BNC/src/bncconst.h
===================================================================
--- /trunk/BNC/src/bncconst.h	(revision 9764)
+++ /trunk/BNC/src/bncconst.h	(revision 9765)
@@ -41,5 +41,5 @@
                         R4, // G1a / 1600.995
                         R2, // G2  / 1246 + k * 7/16 (k = -7 .. +12)
-                        R6, // G1b / 1248.06
+                        R6, // G2a / 1248.06
                         R3, // G3  / 1202.025
                         // Galileo
@@ -55,10 +55,10 @@
                         J6, // L6 / 1278.75
                         // BDS
-                        C2, // B1-2 / 1561.098
-                        C1, // B1   / 1575.42 (BDS-3 signals)
-                        C5, // B2a  / 1176.45 (BDS-3 signals)
-                        C7, // B2b  / 1207.14 (BDS-2 signals)
-                        C8, // B2 (B2a + B2b) / 1191.795 (BDS-3 signals)
-                        C6, // B3   / 1268.52
+                        C2, // B1 / 1561.098 (BDS 2/3 signals)
+                        C1, // B1C, B1A / 1575.42 (BDS-3 signals)
+                        C5, // B2a / 1176.45 (BDS-3 signals)
+                        C7, // B2, B2b / 1207.14 (BDS-2 signals)
+                        C8, // B2(B2a+B2b) / 1191.795 (BDS-3 signals)
+                        C6, // B3,B3A / 1268.52
                         // IRNSS
                         I5, // L5 / 1176.45
Index: /trunk/BNC/src/bnccore.cpp
===================================================================
--- /trunk/BNC/src/bnccore.cpp	(revision 9764)
+++ /trunk/BNC/src/bnccore.cpp	(revision 9765)
@@ -203,19 +203,22 @@
 #ifdef BNC_DEBUG_BCEP
   if      (eph->checkState() == t_eph::bad) {
-    messagePrivate(QString("%1: WRONG EPHEMERIS: %2")
+    messagePrivate(QString("%1: WRONG %2:%3")
                    .arg(eph->receptStaID())
-                   .arg(eph->rinexDateStr(eph->TOC(), eph->prn(), 3.0)).toLatin1());
+                   .arg(eph->navTypeString(eph->navType(), eph->prn(), 99.0))
+                   .arg(eph->rinexDateStr(eph->TOC(), eph->prn(), 99.0)).toLatin1());
     return failure;
   }
   else if (eph->checkState() == t_eph::outdated) {
-    messagePrivate(QString("%1: OUTDATED EPHEMERIS: %2")
+    messagePrivate(QString("%1: OUTDATED %2:%3")
                    .arg(eph->receptStaID())
-                   .arg(eph->rinexDateStr(eph->TOC(), eph->prn(), 3.0)).toLatin1());
+                   .arg(eph->navTypeString(eph->navType(), eph->prn(), 99.0))
+                   .arg(eph->rinexDateStr(eph->TOC(), eph->prn(), 99.0)).toLatin1());
     return failure;
   }
   else if (eph->checkState() == t_eph::unhealthy) {
-    messagePrivate(QString("%1: UNHEALTHY EPHEMERIS: %2")
+    messagePrivate(QString("%1: UNHEALTHY %2:%3")
                    .arg(eph->receptStaID())
-                   .arg(eph->rinexDateStr(eph->TOC(), eph->prn(), 3.0)).toLatin1());
+                   .arg(eph->navTypeString(eph->navType(), eph->prn(), 99.0))
+                   .arg(eph->rinexDateStr(eph->TOC(), eph->prn(), 99.0)).toLatin1());
   }
 #endif
@@ -383,6 +386,10 @@
     if (_rinexVers > 2) {
       if ( ! (appendFlagGPS & QIODevice::Append)) {
+        double rinexVersion = defaultRnxNavVersion4;
+        if (_rinexVers < 4.0) {
+          rinexVersion = defaultRnxNavVersion3;
+        }
         QString line = QString().asprintf("%9.2f%11sN: GNSS NAV DATA    M: Mixed%12sRINEX VERSION / TYPE\n",
-          defaultRnxNavVersion3, "", "");
+            rinexVersion, "", "");
         *_ephStreamGPS << line;
         line.clear();
@@ -397,4 +404,10 @@
         while (it.hasNext()) {
           *_ephStreamGPS << it.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
+        }
+
+        if (_rinexVers == 4) {
+          int leapSecs = gnumleap(datTim.date().year(), datTim.date().month(), datTim.date().day());
+          *_ephStreamGPS << QString("%1").arg(leapSecs, 6, 10, QLatin1Char(' ')).left(60).leftJustified(60)
+                  << "LEAP SECONDS\n";
         }
 
@@ -471,5 +484,5 @@
     printOutputEph(printFile, _ephStreamGPS, strV2, strV3, strV4);
   }
-  else if (_rinexVers == 3) {
+  else if (_rinexVers >= 3) {
     printOutputEph(printFile, _ephStreamGPS, strV2, strV3, strV4);
   }
Index: /trunk/BNC/src/ephemeris.cpp
===================================================================
--- /trunk/BNC/src/ephemeris.cpp	(revision 9764)
+++ /trunk/BNC/src/ephemeris.cpp	(revision 9765)
@@ -21,4 +21,5 @@
 t_eph::t_eph() {
   _checkState = unchecked;
+  _navType = undefined;
   _orbCorr    = 0;
   _clkCorr    = 0;
@@ -104,4 +105,86 @@
   return success;
 }
+
+
+//
+//////////////////////////////////////////////////////////////////////////////
+t_irc t_eph::setNavType(QString navTypeStr) {
+  if      (navTypeStr == "LNAV") {_navType =  t_eph::LNAV;}
+  else if (navTypeStr == "FDMA") {_navType =  t_eph::FDMA;}
+  else if (navTypeStr == "FNAV") {_navType =  t_eph::FNAV;}
+  else if (navTypeStr == "INAF") {_navType =  t_eph::INAF;}
+  else if (navTypeStr == "D1")   {_navType =  t_eph::D1;}
+  else if (navTypeStr == "D2")   {_navType =  t_eph::D2;}
+  else if (navTypeStr == "SBAS") {_navType =  t_eph::SBASL1;}
+  else if (navTypeStr == "CNAV") {_navType =  t_eph::CNAV;}
+  else if (navTypeStr == "CNV1") {_navType =  t_eph::CNV1;}
+  else if (navTypeStr == "CNV2") {_navType =  t_eph::CNV2;}
+  else if (navTypeStr == "CNV3") {_navType =  t_eph::CNV3;}
+  else {_navType = t_eph::undefined;  return failure;}
+
+  return success;
+}
+
+//
+//////////////////////////////////////////////////////////////////////////////
+QString t_eph::navTypeString(e_navType navType, const t_prn& prn, double version) {
+    QString navTypeString = "";
+    QString epochStart;
+    QString eolStr;
+
+    if (version < 4.0) {
+      return navTypeString;
+    }
+
+    if (version == 99.0) {
+      epochStart = "";
+      eolStr = "";
+    }
+    else {
+      epochStart = "> ";
+      eolStr = "\n";
+    }
+
+    QString ephStr = QString("EPH %1 ").arg(prn.toString().c_str());
+    switch (navType) {
+      case undefined:
+        navTypeString = epochStart + ephStr + "unknown" + eolStr;
+        break;
+      case LNAV:
+        navTypeString = epochStart + ephStr + "LNAV" + eolStr;
+        break;
+      case FDMA:
+        navTypeString = epochStart + ephStr + "FDMA" + eolStr;
+        break;
+      case FNAV:
+        navTypeString = epochStart + ephStr + "FNAV" + eolStr;
+        break;
+      case INAF:
+        navTypeString = epochStart + ephStr + "INAV" + eolStr;
+        break;
+      case D1:
+        navTypeString = epochStart + ephStr + "D1" + eolStr;
+        break;
+      case D2:
+        navTypeString = epochStart + ephStr + "D2" + eolStr;
+        break;
+      case SBASL1:
+        navTypeString = epochStart + ephStr + "SBAS" + eolStr;
+        break;
+      case CNAV:
+        navTypeString = epochStart + ephStr + "CNAV" + eolStr;
+        break;
+      case CNV1:
+        navTypeString = epochStart + ephStr + "CNV1" + eolStr;
+        break;
+      case CNV2:
+        navTypeString = epochStart + ephStr + "CNV2" + eolStr;
+        break;
+      case CNV3:
+        navTypeString = epochStart + ephStr + "CNV3" + eolStr;
+        break;
+    }
+    return navTypeString;
+  }
 
 //
@@ -134,4 +217,13 @@
       .arg(min,        2)
       .arg(sec, 5, 'f',1);
+  }
+  else if (version ==  99) {
+    out << QString(" %1 %2 %3 %4 %5 %6")
+      .arg(year,     4)
+      .arg(month,    2, 10, QChar('0'))
+      .arg(day,      2, 10, QChar('0'))
+      .arg(hour,     2, 10, QChar('0'))
+      .arg(min,      2, 10, QChar('0'))
+      .arg(int(sec), 2, 10, QChar('0'));
   }
   else {
@@ -413,5 +505,6 @@
 QString t_ephGPS::toString(double version) const {
 
-  QString rnxStr = rinexDateStr(_TOC, _prn, version);
+  QString navStr = navTypeString(_navType, _prn, version);
+  QString rnxStr = navStr + rinexDateStr(_TOC, _prn, version);
 
   QTextStream out(&rnxStr);
@@ -720,5 +813,6 @@
 QString t_ephGlo::toString(double version) const {
 
-  QString rnxStr = rinexDateStr(_TOC -_gps_utc, _prn, version);
+  QString navStr = navTypeString(_navType, _prn, version);
+  QString rnxStr = navStr + rinexDateStr(_TOC -_gps_utc, _prn, version);
   int nd = int((_TOC - _gps_utc).gpssec()) / (24.0*60.0*60.0);
   QTextStream out(&rnxStr);
@@ -1139,5 +1233,6 @@
 QString t_ephGal::toString(double version) const {
 
-  QString rnxStr = rinexDateStr(_TOC, _prn, version);
+  QString navStr = navTypeString(_navType, _prn, version);
+  QString rnxStr = navStr + rinexDateStr(_TOC, _prn, version);
 
   QTextStream out(&rnxStr);
@@ -1439,5 +1534,6 @@
 QString t_ephSBAS::toString(double version) const {
 
-  QString rnxStr = rinexDateStr(_TOC, _prn, version);
+  QString navStr = navTypeString(_navType, _prn, version);
+  QString rnxStr = navStr + rinexDateStr(_TOC, _prn, version);
 
   QTextStream out(&rnxStr);
@@ -1794,5 +1890,6 @@
 QString t_ephBDS::toString(double version) const {
 
-  QString rnxStr = rinexDateStr(_TOC-14.0, _prn, version);
+  QString navStr = navTypeString(_navType, _prn, version);
+  QString rnxStr = navStr + rinexDateStr(_TOC-14.0, _prn, version);
 
   QTextStream out(&rnxStr);
Index: /trunk/BNC/src/ephemeris.h
===================================================================
--- /trunk/BNC/src/ephemeris.h	(revision 9764)
+++ /trunk/BNC/src/ephemeris.h	(revision 9765)
@@ -19,4 +19,5 @@
   enum e_type {unknown, GPS, QZSS, GLONASS, Galileo, SBAS, BDS, IRNSS};
   enum e_checkState {unchecked, ok, bad, outdated, unhealthy};
+  enum e_navType {undefined, LNAV, FDMA, FNAV, INAF, D1, D2, SBASL1, CNAV, CNV1, CNV2, CNV3};
 
   t_eph();
@@ -30,22 +31,19 @@
   bncTime TOC() const {return _TOC;}
   bool    isNewerThan(const t_eph* eph) const {return earlierTime(eph, this);}
+  void setCheckState(e_checkState checkState) {_checkState = checkState;}
   e_checkState checkState() const {return _checkState;}
   QString checkStateToString() {
     switch (_checkState) {
-      case unchecked:
-        return "unchecked";
-      case ok:
-        return "ok";
-      case bad:
-        return "bad";
-      case outdated:
-        return "outdated";
-      case unhealthy:
-        return "unhealthy";
-      default:
-        return "unknown";
+      case unchecked:  return "unchecked";
+      case ok:         return "ok";
+      case bad:        return "bad";
+      case outdated:   return "outdated";
+      case unhealthy:  return "unhealthy";
+      default:         return "unknown";
     }
   }
-  void    setCheckState(e_checkState checkState) {_checkState = checkState;}
+  e_navType navType() const {return _navType;}
+  t_irc setNavType(QString navTypeStr);
+
   t_prn   prn() const {return _prn;}
   t_irc   getCrd(const bncTime& tt, ColumnVector& xc, ColumnVector& vv, bool useCorr) const;
@@ -56,4 +54,5 @@
   static QString rinexDateStr(const bncTime& tt, const t_prn& prn, double version);
   static QString rinexDateStr(const bncTime& tt, const QString& prnStr, double version);
+  static QString navTypeString(e_navType navType, const t_prn& prn, double version);
   static bool earlierTime(const t_eph* eph1, const t_eph* eph2) {return eph1->_TOC < eph2->_TOC;}
   static bool prnSort(const t_eph* eph1, const t_eph* eph2) {return eph1->prn() < eph2->prn();}
@@ -61,13 +60,13 @@
  protected:
   virtual t_irc position(int GPSweek, double GPSweeks, double* xc, double* vv) const = 0;
-  t_prn        _prn;
-  bncTime      _TOC;
-  QDateTime    _receptDateTime;
-  QString      _receptStaID;
-  e_checkState _checkState;
-  t_orbCorr*   _orbCorr;
-  t_clkCorr*   _clkCorr;
-};
-
+  t_prn            _prn;
+  bncTime          _TOC;
+  QDateTime        _receptDateTime;
+  QString          _receptStaID;
+  e_checkState     _checkState;
+  e_navType        _navType; // defined in RINEX 4
+  t_orbCorr*       _orbCorr;
+  t_clkCorr*       _clkCorr;
+};
 
 class t_ephGPS : public t_eph {
Index: /trunk/BNC/src/rinex/reqcedit.cpp
===================================================================
--- /trunk/BNC/src/rinex/reqcedit.cpp	(revision 9764)
+++ /trunk/BNC/src/rinex/reqcedit.cpp	(revision 9765)
@@ -63,9 +63,12 @@
   _outNavFileName = settings.value("reqcOutNavFile").toString();
   int version     = settings.value("reqcRnxVersion").toInt();
-  if (version < 3) {
+  if (version == 2) {
     _rnxVersion = defaultRnxObsVersion2;
   }
-  else {
+  if (version == 3) {
     _rnxVersion = defaultRnxObsVersion3;
+  }
+  if (version == 4) {
+    _rnxVersion = defaultRnxObsVersion4;
   }
   _samplingRate   = settings.value("reqcSampling").toString().split("sec").first().toDouble();
@@ -601,9 +604,19 @@
   outNavFile.setGlonass(haveGlonass);
 
-  if ( (haveGPS && haveGlonass) || _rnxVersion >= 3.0) {
+  if (_rnxVersion < 3.0) {
+    if (haveGPS && haveGlonass) {
+      outNavFile.setVersion(defaultRnxNavVersion3);
+    }
+    if (haveGPS && !haveGlonass) {
+      outNavFile.setVersion(defaultRnxNavVersion2);
+    }
+  }
+
+  if (_rnxVersion >= 3.0 &&  _rnxVersion < 4.0) {
     outNavFile.setVersion(defaultRnxNavVersion3);
   }
-  else {
-    outNavFile.setVersion(defaultRnxNavVersion2);
+
+  if (_rnxVersion >= 4.0) {
+    outNavFile.setVersion(defaultRnxNavVersion4);
   }
 
@@ -626,5 +639,12 @@
   }
 
-  outNavFile.writeHeader(&txtMap);
+  int mergedNavFiles = _navFileNames.size();
+  unsigned year, month, day;
+  int gps_utc = 0;
+  if (_ephs.size()) {
+    _ephs.at(0)->TOC().civil_date(year, month, day);
+    gps_utc = gnumleap(year, month, day);
+  }
+  outNavFile.writeHeader(&txtMap, mergedNavFiles, gps_utc);
 
   // Loop over all ephemerides
@@ -645,4 +665,8 @@
     }
     if (eph->checkState() == t_eph::bad) {
+      continue;
+    }
+    if (outNavFile.version() >= 4.0 &&
+        eph->navType() == t_eph::undefined) { // input files < version 4.0
       continue;
     }
Index: /trunk/BNC/src/rinex/rnxnavfile.cpp
===================================================================
--- /trunk/BNC/src/rinex/rnxnavfile.cpp	(revision 9764)
+++ /trunk/BNC/src/rinex/rnxnavfile.cpp	(revision 9765)
@@ -146,14 +146,40 @@
 ////////////////////////////////////////////////////////////////////////////
 void t_rnxNavFile::read(QTextStream* stream) {
+  QString navTypeStr;
 
   while (stream->status() == QTextStream::Ok && !stream->atEnd()) {
+
     QString line = stream->readLine();
     if (line.isEmpty()) {
       continue;
     }
+
     QStringList hlp = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+    QString firstStr = hlp.at(0);
     QString prn;
-    if (version() >= 3.0) {
-      prn = hlp.at(0);
+
+    if      (version() >= 3.0 &&  firstStr != ">") {
+      prn = firstStr;
+    }
+    else if (version() >= 4.0 && firstStr == ">") {
+      int lines2skip = 0;
+      QString key = hlp.at(1);
+      // EPH is used
+      if (key == "EPH") {
+          navTypeStr = hlp.at(3);
+      }
+      // all others are currently ignored
+      else if (key == "STO") {
+        lines2skip = 2;
+      }
+      else if (key == "EOP" || key == "ION") {
+        lines2skip = 3;
+      }
+      if (lines2skip) {
+        for (int ii = 1; ii < lines2skip; ii++) {
+          stream->readLine();
+        }
+      }
+      continue;
     }
     else {
@@ -213,4 +239,13 @@
       }
       eph = new t_ephGPS(version(), lines);
+    }
+    else {
+      continue;
+    }
+    if (version() >= 4.0) {
+      if (eph->setNavType(navTypeStr) != success) {
+        delete eph;
+        continue;
+      }
     }
     _ephs.push_back(eph);
@@ -264,5 +299,5 @@
 //
 ////////////////////////////////////////////////////////////////////////////
-void t_rnxNavFile::writeHeader(const QMap<QString, QString>* txtMap) {
+void t_rnxNavFile::writeHeader(const QMap<QString, QString>* txtMap, int numMergedFiles, int leapSecs) {
 
   QString     runBy = BNC_CORE->userName();
@@ -334,4 +369,12 @@
            << "PGM / RUN BY / DATE\n";
 
+  if (version() >= 4.0) {
+    *_stream << QString("%1").arg(leapSecs, 6, 10, QLatin1Char(' ')).left(60).leftJustified(60)
+        << "LEAP SECONDS\n";
+
+    *_stream << QString("%1").arg(numMergedFiles, 19, 10, QLatin1Char(' ')).leftJustified(60)
+        << "MERGED FILE\n";
+  }
+
   QStringListIterator itCmnt(comments);
   while (itCmnt.hasNext()) {
@@ -339,4 +382,5 @@
   }
 
+
   *_stream << QString()
     .leftJustified(60)
Index: /trunk/BNC/src/rinex/rnxnavfile.h
===================================================================
--- /trunk/BNC/src/rinex/rnxnavfile.h	(revision 9764)
+++ /trunk/BNC/src/rinex/rnxnavfile.h	(revision 9765)
@@ -25,5 +25,5 @@
 #ifndef RNXNAVFILE_H
 #define RNXNAVFILE_H
-
+#include <iostream>
 #include <queue>
 #include <QtCore>
@@ -35,5 +35,5 @@
 class bncPPPclient;
 class t_eph;
-
+using namespace std;
 #define defaultRnxNavVersion2 2.11
 #define defaultRnxNavVersion3 3.05
@@ -68,5 +68,5 @@
   void   setGlonass(bool glo) {_header._glonass = glo;}
   void   setGnssTypeV3(t_eph::e_type sys) {_header._satSys = sys;}
-  void   writeHeader(const QMap<QString, QString>* txtMap = 0);
+  void   writeHeader(const QMap<QString, QString>* txtMap = 0, int numMergedFiles = 0, int leapSecs = 0);
   void   writeEph(const t_eph* eph);
 
