<commit_before>/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 Module:       FGLocation.cpp
 Author:       Jon S. Berndt
 Date started: 04/04/2004
 Purpose:      Store an arbitrary location on the globe

 ------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) ------------------
 -------           (C) 2004  Mathias Froehlich (Mathias.Froehlich@web.de) ----

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU Lesser General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program 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 Lesser General Public License for more
 details.

 You should have received a copy of the GNU Lesser General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU Lesser General Public License can also be found on
 the world wide web at http://www.gnu.org.

FUNCTIONAL DESCRIPTION
------------------------------------------------------------------------------
This class encapsulates an arbitrary position in the globe with its accessors.
It has vector properties, so you can add multiply ....

HISTORY
------------------------------------------------------------------------------
04/04/2004   MF    Created

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

#include <cmath>

#include "FGLocation.h"
#include "input_output/FGPropertyManager.h"

namespace JSBSim {

static const char *IdSrc = "$Id: FGLocation.cpp,v 1.22 2010/09/18 22:47:17 jberndt Exp $";
static const char *IdHdr = ID_LOCATION;
using std::cerr;
using std::endl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

FGLocation::FGLocation(void)
{
  mCacheValid = false;
  initial_longitude = 0.0;
  a = 0.0;
  b = 0.0;
  a2 = 0.0;
  b2 = 0.0;
  e2 = 1.0;
  e = 1.0;
  eps2 = -1.0;
  f = 1.0;
  epa = 0.0;

  mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;

//  initial_longitude = 0.0;

  mTl2ec.InitMatrix();
  mTec2l.InitMatrix();
  mTi2ec.InitMatrix();
  mTec2i.InitMatrix();
  mTi2l.InitMatrix();
  mTl2i.InitMatrix();
  mECLoc.InitMatrix();
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

FGLocation::FGLocation(double lon, double lat, double radius)
{
  mCacheValid = false;

  double sinLat = sin(lat);
  double cosLat = cos(lat);
  double sinLon = sin(lon);
  double cosLon = cos(lon);

  a = 0.0;
  b = 0.0;
  a2 = 0.0;
  b2 = 0.0;
  e2 = 1.0;
  e = 1.0;
  eps2 = -1.0;
  f = 1.0;
  epa = 0.0;
  mECLoc = FGColumnVector3( radius*cosLat*cosLon,
                            radius*cosLat*sinLon,
                            radius*sinLat );
  mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetLongitude(double longitude)
{
  double rtmp = mECLoc.Magnitude(eX, eY);
  // Check if we have zero radius.
  // If so set it to 1, so that we can set a position
  if (0.0 == mECLoc.Magnitude())
    rtmp = 1.0;

  // Fast return if we are on the north or south pole ...
  if (rtmp == 0.0)
    return;

  mCacheValid = false;

  // Need to figure out how to set the initial_longitude here

  mECLoc(eX) = rtmp*cos(longitude);
  mECLoc(eY) = rtmp*sin(longitude);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetLatitude(double latitude)
{
  mCacheValid = false;

  double r = mECLoc.Magnitude();
  if (r == 0.0) {
    mECLoc(eX) = 1.0;
    r = 1.0;
  }

  double rtmp = mECLoc.Magnitude(eX, eY);
  if (rtmp != 0.0) {
    double fac = r/rtmp*cos(latitude);
    mECLoc(eX) *= fac;
    mECLoc(eY) *= fac;
  } else {
    mECLoc(eX) = r*cos(latitude);
    mECLoc(eY) = 0.0;
  }
  mECLoc(eZ) = r*sin(latitude);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetRadius(double radius)
{
  mCacheValid = false;

  double rold = mECLoc.Magnitude();
  if (rold == 0.0)
    mECLoc(eX) = radius;
  else
    mECLoc *= radius/rold;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetPosition(double lon, double lat, double radius)
{
  mCacheValid = false;

  double sinLat = sin(lat);
  double cosLat = cos(lat);
  double sinLon = sin(lon);
  double cosLon = cos(lon);
//  initial_longitude = lon;
  mECLoc = FGColumnVector3( radius*cosLat*cosLon,
                            radius*cosLat*sinLon,
                            radius*sinLat );
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetPositionGeodetic(double lon, double lat, double height)
{
  mCacheValid = false;

  mGeodLat = lat;
  mLon = lon;
  GeodeticAltitude = height;

//  initial_longitude = mLon;

  double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat));

  mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon);
  mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon);
  mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetEllipse(double semimajor, double semiminor)
{
  mCacheValid = false;

  a = semimajor;
  b = semiminor;
  a2 = a*a;
  b2 = b*b;
  e2 = 1.0 - b2/a2;
  e = sqrt(e2);
  eps2 = a2/b2 - 1.0;
  f = 1.0 - b/a;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Compute the ECEF to ECI transformation matrix using Stevens and Lewis "Aircraft
// Control and Simulation", second edition, eqn. 1.4-12, pg. 39. In Stevens and Lewis
// notation, this is C_i/e, a transformation from ECEF to ECI.

const FGMatrix33& FGLocation::GetTec2i(void)
{
  ComputeDerived();
  return mTec2i;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This is given in Stevens and Lewis "Aircraft
// Control and Simulation", second edition, eqn. 1.4-12, pg. 39
// The notation in Stevens and Lewis is: C_e/i. This represents a transformation
// from ECI to ECEF - and the orientation of the ECEF frame relative to the ECI
// frame.

const FGMatrix33& FGLocation::GetTi2ec(void)
{
  ComputeDerived();
  return mTi2ec;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::ComputeDerivedUnconditional(void) const
{
  // The radius is just the Euclidean norm of the vector.
  mRadius = mECLoc.Magnitude();

  // The distance of the location to the Z-axis, which is the axis
  // through the poles.
  double r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY);
  double rxy = sqrt(r02);

  // Compute the sin/cos values of the longitude
  double sinLon, cosLon;
  if (rxy == 0.0) {
    sinLon = 0.0;
    cosLon = 1.0;
  } else {
    sinLon = mECLoc(eY)/rxy;
    cosLon = mECLoc(eX)/rxy;
  }

  // Compute the sin/cos values of the latitude
  double sinLat, cosLat;
  if (mRadius == 0.0)  {
    sinLat = 0.0;
    cosLat = 1.0;
  } else {
    sinLat = mECLoc(eZ)/mRadius;
    cosLat = rxy/mRadius;
  }

  // Compute the longitude and latitude itself
  if ( mECLoc( eX ) == 0.0 && mECLoc( eY ) == 0.0 )
    mLon = 0.0;
  else
    mLon = atan2( mECLoc( eY ), mECLoc( eX ) );

  if ( rxy == 0.0 && mECLoc( eZ ) == 0.0 )
    mLat = 0.0;
  else
    mLat = atan2( mECLoc(eZ), rxy );

  // Compute the transform matrices from and to the earth centered frame.
  // See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
  // Eqn. 1.4-13, page 40. In Stevens and Lewis notation, this is C_n/e - the
  // orientation of the navigation (local) frame relative to the ECEF frame,
  // and a transformation from ECEF to nav (local) frame.

  mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat,  cosLat,
                           -sinLon   ,     cosLon    ,    0.0 ,
                       -cosLon*cosLat, -sinLon*cosLat, -sinLat  );

  // In Stevens and Lewis notation, this is C_e/n - the
  // orientation of the ECEF frame relative to the nav (local) frame,
  // and a transformation from nav (local) to ECEF frame.

  mTl2ec = mTec2l.Transposed();

  // Calculate the inertial to ECEF and transpose matrices
  double cos_epa = cos(epa);
  double sin_epa = sin(epa);
  mTi2ec = FGMatrix33( cos_epa, sin_epa, 0.0,
                      -sin_epa, cos_epa, 0.0,
                           0.0,      0.0, 1.0 );
  mTec2i = mTi2ec.Transposed();

  // Now calculate the local (or nav, or ned) frame to inertial transform matrix,
  // and the inverse.
  mTl2i = mTec2i * mTl2ec;
  mTi2l = mTl2i.Transposed();

  // Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper,
  // "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and
  // "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited",
  // author: I. Sofair

  if (a != 0.0 && b != 0.0) {
    double c, p, q, s, t, u, v, w, z, p2, u2, r0;
    double Ne, P, Q0, Q, signz0, sqrt_q;
    p  = fabs(mECLoc(eZ))/eps2;
    s  = r02/(e2*eps2);
    p2 = p*p;
    q  = p2 - b2 + s;
    sqrt_q = sqrt(q);
    if (q>0)
    {
      u  = p/sqrt_q;
//      u2 = p2/q;
      u2 = u*u;
      v  = b2*u2/q;
      P  = 27.0*v*s/q;
      Q0 = sqrt(P+1) + sqrt(P);
      Q  = pow(Q0, 0.66666666667);
      t  = (1.0 + Q + 1.0/Q)/6.0;
      c  = sqrt(u2 - 1 + 2.0*t);
      w  = (c - u)/2.0;
      signz0 = mECLoc(eZ)>=0?1.0:-1.0;
      if ((sqrt(t*t+v)-u*w-0.5*t-0.25) < 0.0) {
        z = 0.0;
      } else {
        z  = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
      }
      Ne = a*sqrt(1+eps2*z*z/b2);
      mGeodLat = asin((eps2+1.0)*(z/Ne));
      r0 = rxy;
      GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne;
    }
  }

  // Mark the cached values as valid
  mCacheValid = true;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

} // namespace JSBSim
<commit_msg>Fixed some code to prevent divide by zeroes<commit_after>/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 Module:       FGLocation.cpp
 Author:       Jon S. Berndt
 Date started: 04/04/2004
 Purpose:      Store an arbitrary location on the globe

 ------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) ------------------
 -------           (C) 2004  Mathias Froehlich (Mathias.Froehlich@web.de) ----

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU Lesser General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program 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 Lesser General Public License for more
 details.

 You should have received a copy of the GNU Lesser General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU Lesser General Public License can also be found on
 the world wide web at http://www.gnu.org.

FUNCTIONAL DESCRIPTION
------------------------------------------------------------------------------
This class encapsulates an arbitrary position in the globe with its accessors.
It has vector properties, so you can add multiply ....

HISTORY
------------------------------------------------------------------------------
04/04/2004   MF    Created

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

#include <cmath>

#include "FGLocation.h"
#include "input_output/FGPropertyManager.h"

namespace JSBSim {

static const char *IdSrc = "$Id: FGLocation.cpp,v 1.23 2010/09/22 11:34:09 jberndt Exp $";
static const char *IdHdr = ID_LOCATION;
using std::cerr;
using std::endl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

FGLocation::FGLocation(void)
{
  mCacheValid = false;
  initial_longitude = 0.0;
  a = 0.0;
  b = 0.0;
  a2 = 0.0;
  b2 = 0.0;
  e2 = 1.0;
  e = 1.0;
  eps2 = -1.0;
  f = 1.0;
  epa = 0.0;

  mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;

//  initial_longitude = 0.0;

  mTl2ec.InitMatrix();
  mTec2l.InitMatrix();
  mTi2ec.InitMatrix();
  mTec2i.InitMatrix();
  mTi2l.InitMatrix();
  mTl2i.InitMatrix();
  mECLoc.InitMatrix();
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

FGLocation::FGLocation(double lon, double lat, double radius)
{
  mCacheValid = false;

  double sinLat = sin(lat);
  double cosLat = cos(lat);
  double sinLon = sin(lon);
  double cosLon = cos(lon);

  a = 0.0;
  b = 0.0;
  a2 = 0.0;
  b2 = 0.0;
  e2 = 1.0;
  e = 1.0;
  eps2 = -1.0;
  f = 1.0;
  epa = 0.0;
  mECLoc = FGColumnVector3( radius*cosLat*cosLon,
                            radius*cosLat*sinLon,
                            radius*sinLat );
  mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetLongitude(double longitude)
{
  double rtmp = mECLoc.Magnitude(eX, eY);
  // Check if we have zero radius.
  // If so set it to 1, so that we can set a position
  if (0.0 == mECLoc.Magnitude())
    rtmp = 1.0;

  // Fast return if we are on the north or south pole ...
  if (rtmp == 0.0)
    return;

  mCacheValid = false;

  // Need to figure out how to set the initial_longitude here

  mECLoc(eX) = rtmp*cos(longitude);
  mECLoc(eY) = rtmp*sin(longitude);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetLatitude(double latitude)
{
  mCacheValid = false;

  double r = mECLoc.Magnitude();
  if (r == 0.0) {
    mECLoc(eX) = 1.0;
    r = 1.0;
  }

  double rtmp = mECLoc.Magnitude(eX, eY);
  if (rtmp != 0.0) {
    double fac = r/rtmp*cos(latitude);
    mECLoc(eX) *= fac;
    mECLoc(eY) *= fac;
  } else {
    mECLoc(eX) = r*cos(latitude);
    mECLoc(eY) = 0.0;
  }
  mECLoc(eZ) = r*sin(latitude);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetRadius(double radius)
{
  mCacheValid = false;

  double rold = mECLoc.Magnitude();
  if (rold == 0.0)
    mECLoc(eX) = radius;
  else
    mECLoc *= radius/rold;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetPosition(double lon, double lat, double radius)
{
  mCacheValid = false;

  double sinLat = sin(lat);
  double cosLat = cos(lat);
  double sinLon = sin(lon);
  double cosLon = cos(lon);
//  initial_longitude = lon;
  mECLoc = FGColumnVector3( radius*cosLat*cosLon,
                            radius*cosLat*sinLon,
                            radius*sinLat );
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetPositionGeodetic(double lon, double lat, double height)
{
  mCacheValid = false;

  mGeodLat = lat;
  mLon = lon;
  GeodeticAltitude = height;

//  initial_longitude = mLon;

  double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat));

  mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon);
  mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon);
  mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::SetEllipse(double semimajor, double semiminor)
{
  mCacheValid = false;

  a = semimajor;
  b = semiminor;
  a2 = a*a;
  b2 = b*b;
  e2 = 1.0 - b2/a2;
  e = sqrt(e2);
  eps2 = a2/b2 - 1.0;
  f = 1.0 - b/a;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Compute the ECEF to ECI transformation matrix using Stevens and Lewis "Aircraft
// Control and Simulation", second edition, eqn. 1.4-12, pg. 39. In Stevens and Lewis
// notation, this is C_i/e, a transformation from ECEF to ECI.

const FGMatrix33& FGLocation::GetTec2i(void)
{
  ComputeDerived();
  return mTec2i;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This is given in Stevens and Lewis "Aircraft
// Control and Simulation", second edition, eqn. 1.4-12, pg. 39
// The notation in Stevens and Lewis is: C_e/i. This represents a transformation
// from ECI to ECEF - and the orientation of the ECEF frame relative to the ECI
// frame.

const FGMatrix33& FGLocation::GetTi2ec(void)
{
  ComputeDerived();
  return mTi2ec;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void FGLocation::ComputeDerivedUnconditional(void) const
{
  // The radius is just the Euclidean norm of the vector.
  mRadius = mECLoc.Magnitude();

  // The distance of the location to the Z-axis, which is the axis
  // through the poles.
  double r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY);
  double rxy = sqrt(r02);

  // Compute the sin/cos values of the longitude
  double sinLon, cosLon;
  if (rxy == 0.0) {
    sinLon = 0.0;
    cosLon = 1.0;
  } else {
    sinLon = mECLoc(eY)/rxy;
    cosLon = mECLoc(eX)/rxy;
  }

  // Compute the sin/cos values of the latitude
  double sinLat, cosLat;
  if (mRadius == 0.0)  {
    sinLat = 0.0;
    cosLat = 1.0;
  } else {
    sinLat = mECLoc(eZ)/mRadius;
    cosLat = rxy/mRadius;
  }

  // Compute the longitude and latitude itself
  if ( mECLoc( eX ) == 0.0 && mECLoc( eY ) == 0.0 )
    mLon = 0.0;
  else
    mLon = atan2( mECLoc( eY ), mECLoc( eX ) );

  if ( rxy == 0.0 && mECLoc( eZ ) == 0.0 )
    mLat = 0.0;
  else
    mLat = atan2( mECLoc(eZ), rxy );

  // Compute the transform matrices from and to the earth centered frame.
  // See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
  // Eqn. 1.4-13, page 40. In Stevens and Lewis notation, this is C_n/e - the
  // orientation of the navigation (local) frame relative to the ECEF frame,
  // and a transformation from ECEF to nav (local) frame.

  mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat,  cosLat,
                           -sinLon   ,     cosLon    ,    0.0 ,
                       -cosLon*cosLat, -sinLon*cosLat, -sinLat  );

  // In Stevens and Lewis notation, this is C_e/n - the
  // orientation of the ECEF frame relative to the nav (local) frame,
  // and a transformation from nav (local) to ECEF frame.

  mTl2ec = mTec2l.Transposed();

  // Calculate the inertial to ECEF and transpose matrices
  double cos_epa = cos(epa);
  double sin_epa = sin(epa);
  mTi2ec = FGMatrix33( cos_epa, sin_epa, 0.0,
                      -sin_epa, cos_epa, 0.0,
                           0.0,      0.0, 1.0 );
  mTec2i = mTi2ec.Transposed();

  // Now calculate the local (or nav, or ned) frame to inertial transform matrix,
  // and the inverse.
  mTl2i = mTec2i * mTl2ec;
  mTi2l = mTl2i.Transposed();

  // Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper,
  // "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and
  // "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited",
  // author: I. Sofair

  if (a != 0.0 && b != 0.0) {
    double c, p, q, s, t, u, v, w, z, p2, u2, r0;
    double Ne, P, Q0, Q, signz0, sqrt_q, z_term;
    p  = fabs(mECLoc(eZ))/eps2;
    s  = r02/(e2*eps2);
    p2 = p*p;
    q  = p2 - b2 + s;
    sqrt_q = sqrt(q);
    if (q>0)
    {
      u  = p/sqrt_q;
      u2 = p2/q;
      v  = b2*u2/q;
      P  = 27.0*v*s/q;
      Q0 = sqrt(P+1) + sqrt(P);
      Q  = pow(Q0, 0.66666666667);
      t  = (1.0 + Q + 1.0/Q)/6.0;
      c  = sqrt(u2 - 1 + 2.0*t);
      w  = (c - u)/2.0;
      signz0 = mECLoc(eZ)>=0?1.0:-1.0;
      z_term = sqrt(t*t+v)-u*w-0.5*t-0.25;
      if (z_term < 0.0) {
        z = 0.0;
      } else {
        z  = signz0*sqrt_q*(w+sqrt(z_term));
      }
      Ne = a*sqrt(1+eps2*z*z/b2);
      mGeodLat = asin((eps2+1.0)*(z/Ne));
      r0 = rxy;
      GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne;
    }
  }

  // Mark the cached values as valid
  mCacheValid = true;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

} // namespace JSBSim
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 *          Andreas Hansson
 */

#include "debug/Drain.hh"
#include "debug/PacketQueue.hh"
#include "mem/packet_queue.hh"

using namespace std;

PacketQueue::PacketQueue(EventManager& _em, const std::string& _label)
    : em(_em), sendEvent(this), drainEvent(NULL), label(_label),
      waitingOnRetry(false)
{
    ID=0;
	//printf("SendEvent initialized %d\n", sendEvent.initialized());
	//cout<< _label << endl;
}

PacketQueue::~PacketQueue()
{
}

void
PacketQueue::retry()
{
    DPRINTF(PacketQueue, "Queue %s received retry\n", name());
    assert(waitingOnRetry);
    //printf("Queue %s received retry @ %llu\n", name().c_str(), curTick());
	sendDeferredPacket();
}

bool
PacketQueue::checkFunctional(PacketPtr pkt)
{
    pkt->pushLabel(label);

    DeferredPacketIterator i = transmitList.begin();
    DeferredPacketIterator end = transmitList.end();
    bool found = false;

    while (!found && i != end) {
        // If the buffered packet contains data, and it overlaps the
        // current packet, then update data
        found = pkt->checkFunctional(i->pkt);
        ++i;
    }

    pkt->popLabel();

    return found;
}

void
PacketQueue::schedSendEvent(Tick when, bool isInteresting)
{
    // if we are waiting on a retry, do not schedule a send event, and
    // instead rely on retry being called
    if (waitingOnRetry) {
        assert(!sendEvent.scheduled());
        return;
    }

    if( isInteresting ){
      printf( "interesting schedEvent when=%lu curTick=%lu\n",
           when, curTick() );
    }

    //printf("schedule send Event @ cycle %llu\n", when);
	  //if (sendEvent.scheduled()) printf("Event scheduled @ cycle %llu\n", when);
	  if (!sendEvent.scheduled()) {
        if( isEra() ) printf("schedSendEvent at %lu\n",when);
        em.schedule(&sendEvent, when);
    } else if (sendEvent.when() > when) {
        if( isEra() ){
           printf("scendEvent was scheduled at %lu, rescheduled at %lu\n",
                   sendEvent.when(), when);
        }
        //printf("Event rescheduled @ cycle %llu\n", when);
      em.reschedule(&sendEvent, when);
    }
}

void
PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop)
{
    //printf("schedu send Timing %llx @ cycle %llu\n", pkt->getAddr(), when);
	// we can still send a packet before the end of this tick
    assert(when >= curTick());

    // express snoops should never be queued
    assert(!pkt->isExpressSnoop());

    // nothing on the list, or earlier than current front element,
    // schedule an event
    if (transmitList.empty() || when < transmitList.front().tick) {
        // note that currently we ignore a potentially outstanding retry
        // and could in theory put a new packet at the head of the
        // transmit list before retrying the existing packet
        transmitList.push_front(DeferredPacket(when, pkt, send_as_snoop));
#ifdef DEBUG_TP
        if(pkt->getAddr()==interesting && pkt->threadID==0){
          printf("interesting schedSendTiming->schedSendEvent @ %lu\n",
              curTick());
        }
        schedSendEvent(when,(pkt->getAddr())==interesting);
#else
        schedSendEvent(when,false);
#endif
        return;
    }

    // list is non-empty and this belongs at the end
    if (when >= transmitList.back().tick) {
        transmitList.push_back(DeferredPacket(when, pkt, send_as_snoop));
        return;
    }

    // this belongs in the middle somewhere, insertion sort
    DeferredPacketIterator i = transmitList.begin();
    ++i; // already checked for insertion at front
    while (i != transmitList.end() && when >= i->tick)
        ++i;
    transmitList.insert(i, DeferredPacket(when, pkt, send_as_snoop));
}

void PacketQueue::trySendTiming()
{
    //printf("trySendTiming @ cycle %llu\n", curTick());
	assert(deferredPacketReady());

    // take the next packet off the list here, as we might return to
    // ourselves through the sendTiming call below
    DeferredPacket dp = transmitList.front();
    transmitList.pop_front();

#ifdef DEBUG_TP
    if( dp.pkt->getAddr() == interesting ){
      printf("interesting trySendTiming within PQ @%lu, dest %i\n",
          curTick(), dp.pkt->getDest());
    }
#endif

    // use the appropriate implementation of sendTiming based on the
    // type of port associated with the queue, and whether the packet
    // is to be sent as a snoop or not
    waitingOnRetry = !sendTiming(dp.pkt, dp.sendAsSnoop);

    if (waitingOnRetry) {
        // put the packet back at the front of the list (packet should
        // not have changed since it wasn't accepted)
        assert(!sendEvent.scheduled());
        transmitList.push_front(dp);
    }
}

void
PacketQueue::scheduleSend(Tick time)
{
    // the next ready time is either determined by the next deferred packet,
    // or in the cache through the MSHR ready time
    Tick nextReady = std::min(deferredPacketReadyTime(), time);

    if (nextReady != MaxTick) {
        // if the sendTiming caused someone else to call our
        // recvTiming we could already have an event scheduled, check
        if (!sendEvent.scheduled())
            em.schedule(&sendEvent, std::max(nextReady, curTick() + 1));
    } else {
        // no more to send, so if we're draining, we may be done
        if (drainEvent && transmitList.empty() && !sendEvent.scheduled()) {
            DPRINTF(Drain, "PacketQueue done draining,"
                    "processing drain event\n");
            drainEvent->process();
            drainEvent = NULL;
        }
    }
}

void
PacketQueue::sendDeferredPacket()
{
    // try to send what is on the list, this will set waitingOnRetry
    // accordingly
    trySendTiming();

    // if we succeeded and are not waiting for a retry, schedule the
    // next send
    if (!waitingOnRetry) {
        scheduleSend();
    }
}

void
PacketQueue::processSendEvent()
{
    assert(!waitingOnRetry);
	//printf("processSendEvent called @ %llu\n", curTick());
    sendDeferredPacket();
}

unsigned int
PacketQueue::drain(Event *de)
{
    if (transmitList.empty() && !sendEvent.scheduled())
        return 0;
    DPRINTF(Drain, "PacketQueue not drained\n");
    drainEvent = de;
    return 1;
}

MasterPacketQueue::MasterPacketQueue(EventManager& _em, MasterPort& _masterPort,
                                     const std::string _label)
    : PacketQueue(_em, _label), masterPort(_masterPort)
{
}

bool
MasterPacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // attempt to send the packet and return according to the outcome
    if (!send_as_snoop)
        return masterPort.sendTimingReq(pkt);
    else
        return masterPort.sendTimingSnoopResp(pkt);
}

SlavePacketQueue::SlavePacketQueue(EventManager& _em, SlavePort& _slavePort,
                                   const std::string _label)
    : PacketQueue(_em, _label), slavePort(_slavePort)
{
}

bool
SlavePacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // we should never have queued snoop requests
    assert(!send_as_snoop);
    return slavePort.sendTimingResp(pkt);
}
<commit_msg>Remove assertion to fix regression.<commit_after>/*
 * Copyright (c) 2012 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 *          Andreas Hansson
 */

#include "debug/Drain.hh"
#include "debug/PacketQueue.hh"
#include "mem/packet_queue.hh"

using namespace std;

PacketQueue::PacketQueue(EventManager& _em, const std::string& _label)
    : em(_em), sendEvent(this), drainEvent(NULL), label(_label),
      waitingOnRetry(false)
{
    ID=0;
	//printf("SendEvent initialized %d\n", sendEvent.initialized());
	//cout<< _label << endl;
}

PacketQueue::~PacketQueue()
{
}

void
PacketQueue::retry()
{
    DPRINTF(PacketQueue, "Queue %s received retry\n", name());
    //assert(waitingOnRetry);
    //printf("Queue %s received retry @ %llu\n", name().c_str(), curTick());
	sendDeferredPacket();
}

bool
PacketQueue::checkFunctional(PacketPtr pkt)
{
    pkt->pushLabel(label);

    DeferredPacketIterator i = transmitList.begin();
    DeferredPacketIterator end = transmitList.end();
    bool found = false;

    while (!found && i != end) {
        // If the buffered packet contains data, and it overlaps the
        // current packet, then update data
        found = pkt->checkFunctional(i->pkt);
        ++i;
    }

    pkt->popLabel();

    return found;
}

void
PacketQueue::schedSendEvent(Tick when, bool isInteresting)
{
    // if we are waiting on a retry, do not schedule a send event, and
    // instead rely on retry being called
    if (waitingOnRetry) {
        assert(!sendEvent.scheduled());
        return;
    }

    if( isInteresting ){
      printf( "interesting schedEvent when=%lu curTick=%lu\n",
           when, curTick() );
    }

    //printf("schedule send Event @ cycle %llu\n", when);
	  //if (sendEvent.scheduled()) printf("Event scheduled @ cycle %llu\n", when);
	  if (!sendEvent.scheduled()) {
        if( isEra() ) printf("schedSendEvent at %lu\n",when);
        em.schedule(&sendEvent, when);
    } else if (sendEvent.when() > when) {
        if( isEra() ){
           printf("scendEvent was scheduled at %lu, rescheduled at %lu\n",
                   sendEvent.when(), when);
        }
        //printf("Event rescheduled @ cycle %llu\n", when);
      em.reschedule(&sendEvent, when);
    }
}

void
PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop)
{
    //printf("schedu send Timing %llx @ cycle %llu\n", pkt->getAddr(), when);
	// we can still send a packet before the end of this tick
    assert(when >= curTick());

    // express snoops should never be queued
    assert(!pkt->isExpressSnoop());

    // nothing on the list, or earlier than current front element,
    // schedule an event
    if (transmitList.empty() || when < transmitList.front().tick) {
        // note that currently we ignore a potentially outstanding retry
        // and could in theory put a new packet at the head of the
        // transmit list before retrying the existing packet
        transmitList.push_front(DeferredPacket(when, pkt, send_as_snoop));
#ifdef DEBUG_TP
        if(pkt->getAddr()==interesting && pkt->threadID==0){
          printf("interesting schedSendTiming->schedSendEvent @ %lu\n",
              curTick());
        }
        schedSendEvent(when,(pkt->getAddr())==interesting);
#else
        schedSendEvent(when,false);
#endif
        return;
    }

    // list is non-empty and this belongs at the end
    if (when >= transmitList.back().tick) {
        transmitList.push_back(DeferredPacket(when, pkt, send_as_snoop));
        return;
    }

    // this belongs in the middle somewhere, insertion sort
    DeferredPacketIterator i = transmitList.begin();
    ++i; // already checked for insertion at front
    while (i != transmitList.end() && when >= i->tick)
        ++i;
    transmitList.insert(i, DeferredPacket(when, pkt, send_as_snoop));
}

void PacketQueue::trySendTiming()
{
    //printf("trySendTiming @ cycle %llu\n", curTick());
	assert(deferredPacketReady());

    // take the next packet off the list here, as we might return to
    // ourselves through the sendTiming call below
    DeferredPacket dp = transmitList.front();
    transmitList.pop_front();

#ifdef DEBUG_TP
    if( dp.pkt->getAddr() == interesting ){
      printf("interesting trySendTiming within PQ @%lu, dest %i\n",
          curTick(), dp.pkt->getDest());
    }
#endif

    // use the appropriate implementation of sendTiming based on the
    // type of port associated with the queue, and whether the packet
    // is to be sent as a snoop or not
    waitingOnRetry = !sendTiming(dp.pkt, dp.sendAsSnoop);

    if (waitingOnRetry) {
        // put the packet back at the front of the list (packet should
        // not have changed since it wasn't accepted)
        assert(!sendEvent.scheduled());
        transmitList.push_front(dp);
    }
}

void
PacketQueue::scheduleSend(Tick time)
{
    // the next ready time is either determined by the next deferred packet,
    // or in the cache through the MSHR ready time
    Tick nextReady = std::min(deferredPacketReadyTime(), time);

    if (nextReady != MaxTick) {
        // if the sendTiming caused someone else to call our
        // recvTiming we could already have an event scheduled, check
        if (!sendEvent.scheduled())
            em.schedule(&sendEvent, std::max(nextReady, curTick() + 1));
    } else {
        // no more to send, so if we're draining, we may be done
        if (drainEvent && transmitList.empty() && !sendEvent.scheduled()) {
            DPRINTF(Drain, "PacketQueue done draining,"
                    "processing drain event\n");
            drainEvent->process();
            drainEvent = NULL;
        }
    }
}

void
PacketQueue::sendDeferredPacket()
{
    // try to send what is on the list, this will set waitingOnRetry
    // accordingly
    trySendTiming();

    // if we succeeded and are not waiting for a retry, schedule the
    // next send
    if (!waitingOnRetry) {
        scheduleSend();
    }
}

void
PacketQueue::processSendEvent()
{
    assert(!waitingOnRetry);
	//printf("processSendEvent called @ %llu\n", curTick());
    sendDeferredPacket();
}

unsigned int
PacketQueue::drain(Event *de)
{
    if (transmitList.empty() && !sendEvent.scheduled())
        return 0;
    DPRINTF(Drain, "PacketQueue not drained\n");
    drainEvent = de;
    return 1;
}

MasterPacketQueue::MasterPacketQueue(EventManager& _em, MasterPort& _masterPort,
                                     const std::string _label)
    : PacketQueue(_em, _label), masterPort(_masterPort)
{
}

bool
MasterPacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // attempt to send the packet and return according to the outcome
    if (!send_as_snoop)
        return masterPort.sendTimingReq(pkt);
    else
        return masterPort.sendTimingSnoopResp(pkt);
}

SlavePacketQueue::SlavePacketQueue(EventManager& _em, SlavePort& _slavePort,
                                   const std::string _label)
    : PacketQueue(_em, _label), slavePort(_slavePort)
{
}

bool
SlavePacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop)
{
    // we should never have queued snoop requests
    assert(!send_as_snoop);
    return slavePort.sendTimingResp(pkt);
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2016 Louis McCarthy
  All rights reserved.

  Licensed under MIT License, see LICENSE for full license text

  parseRawImage.ccp - Loads the raw image binary file and spits out debug info
*/

#include <CCfits>
#include <cmath>
    // The library is enclosed in a namespace.

    using namespace CCfits;
    using std::valarray;

#include <stdio.h>
#include <stdlib.h>

#define MAX_TRANSFER_SIZE 12677612

int main()
{
    FILE* newFile = fopen("raw.image", "r");
    if (newFile == NULL)
    {
        printf("Failed to open file\n");
        return -1;
    }

    unsigned char* data = (unsigned char*)malloc(MAX_TRANSFER_SIZE);
    size_t result = fread(data, 1, MAX_TRANSFER_SIZE, newFile);
    fclose(newFile);

    printf("Read %lu bytes\n", result);

    int rowCount = 0;
    int byteCount = 0;
    unsigned char lastByte;

    // FITS Variables
    long naxis = 2;
    long naxes[naxis] = { 3110, 2034 };

    std::auto_ptr<FITS> pFits(0);

    try
    {
        const std::string fileName("!sspro.fit");
        pFits.reset( new FITS(fileName , USHORT_IMG , naxis , naxes ) );
    }
    catch (FITS::CantCreate)
    {
          return -1;
    }

    long& width = naxes[0];
    long nelements = std::accumulate(&naxes[0],&naxes[naxis],1,std::multiplies<long>());
    std::valarray<unsigned short> row(width);
    std::valarray<unsigned short> image(nelements);

    printf("Parsing rows...");
    for (unsigned long i=0; i<result; i++)
    {
        // create 16 bit values from 2 bytes
        if (byteCount % 2 != 0)
        {
            //printf("Adding bytes 0x%X and 0x%X to get short 0x%X for array index %d\n", data[i], lastByte, ((unsigned short)data[i] << 8) + lastByte, (byteCount-1)/2);
            row[(byteCount-1)/2] = ((unsigned short)data[i] << 8) + lastByte;
        }

        lastByte = data[i];

        if (++byteCount == 6220)
        {
            byteCount = 0;

            /* Add row to image (frames a+b, even's first)
            if (rowCount > 1016)
                image[std::slice(width*static_cast<unsigned short>((rowCount-1016)*2-1),width,1)] = row; // + (unsigned short)rowCount;
            else
                image[std::slice(width*static_cast<unsigned short>(rowCount*2),width,1)] = row;
            rowCount++;*/

            // Add row to image (swapped frames, b+a, odd's first)
            if (rowCount > 1016)
                image[std::slice(width*static_cast<unsigned short>((rowCount-1017)*2),width,1)] = row; // + (unsigned short)rowCount;
            else
                image[std::slice(width*static_cast<unsigned short>(rowCount*2+1),width,1)] = row;
            rowCount++;
        }
    }

    printf("Done\r\n");
    // Save image
    long firstPixel(1);
    long exposure(1500);
    pFits->pHDU().addKey("EXPOSURE", exposure,"Total Exposure Time");

    pFits->pHDU().write(firstPixel,nelements,image);
    std::cout << pFits->pHDU() << std::endl;

    free(data);
}
<commit_msg>Reduce image to crop out front/back porch<commit_after>/*
  Copyright (c) 2016 Louis McCarthy
  All rights reserved.

  Licensed under MIT License, see LICENSE for full license text

  parseRawImage.ccp - Loads the raw image binary file and spits out debug info
*/

#include <CCfits>
#include <cmath>

// The library is enclosed in a namespace.
using namespace CCfits;
using std::valarray;

#include <stdio.h>
#include <stdlib.h>

#define MAX_TRANSFER_SIZE 12677612
#define MAX_HEIGHT 2028
#define MAX_WIDTH  3040
#define ROW_LENGTH_BYTES 6220

int main()
{
    FILE* newFile = fopen("raw.image", "r");
    if (newFile == NULL)
    {
        printf("Failed to open file\n");
        return -1;
    }

    unsigned char* data = (unsigned char*)malloc(MAX_TRANSFER_SIZE);
    size_t result = fread(data, 1, MAX_TRANSFER_SIZE, newFile);
    fclose(newFile);

    printf("Read %lu bytes\n", result);

    int rowCount = 0;
    unsigned char lastByte;

    // FITS Variables
    long naxis = 2;
    long naxes[naxis] = { MAX_WIDTH, MAX_HEIGHT };

    std::auto_ptr<FITS> pFits(0);

    try
    {
        const std::string fileName("!sspro_mxdl.fit");
        pFits.reset( new FITS(fileName , USHORT_IMG , naxis , naxes ) );
    }
    catch (FITS::CantCreate)
    {
        return -1;
    }

    long& width = naxes[0];
    long nelements = std::accumulate(&naxes[0],&naxes[naxis],1,std::multiplies<long>());
    std::valarray<unsigned short> row(width);
    std::valarray<unsigned short> image(nelements);

    printf("Parsing rows...");
    int zeroCount = 0;
    unsigned int lastIndex = 0;
    unsigned int rowIndexes[MAX_HEIGHT];

    // Find and validate row starts
    for (unsigned int i=0; i<result; i++)
    {
        if (data[i] == 0x00)
        {
            if (++zeroCount==18)
            {
                int rowSize = i - lastIndex;

                // Is this a valid row?
                if (rowSize == ROW_LENGTH_BYTES || lastIndex == 0)
                {
                    rowIndexes[rowCount++] = i - 17; // Set start of row to beginning of zeros
                    printf("\r\nRow %d: starts at location 0x%x", rowCount, i - 17);
                }
                else
                {
                    printf("\r\nToo many bytes (%d) in row....", rowSize);
                    if (rowSize % ROW_LENGTH_BYTES == 0)
                    {
                        printf("good, byte count is a multiple of rows...parsing\r\n");
                        while (lastIndex < i)
                        {
                            rowIndexes[rowCount++] = lastIndex - 17 + ROW_LENGTH_BYTES;
                            printf("\r\nRow %d: starts at location 0x%x", rowCount, lastIndex - 17 + ROW_LENGTH_BYTES);
                            lastIndex += ROW_LENGTH_BYTES;
                        }
                    }
                    else
                    {
                        printf("\r\nInvalid byte count...giving up\r\n");
                    }
                }

                lastIndex = i;
                zeroCount = 0;
            }
        }
        else
        {
            //if (zeroCount > 4)
            //    printf("\r\nFound %d, zero's in a row....0x%x\r\n", zeroCount, i);
            zeroCount=0;
        }
    }

    for (int fitsRows=3;fitsRows<rowCount;fitsRows++)
    {
        int start = 0;

        // Add first rows (3-1010, raw frame is 0-1016)
        if (fitsRows <= 1010)
        {
            const short frontPorch = 60 * 2; // Pixels * Bytes per pixel
            const short backPorch = 10 * 2;  // Pixels * Bytes per pixel

            start = rowIndexes[fitsRows] + frontPorch;

            for (int pixelBytes=0;pixelBytes<(ROW_LENGTH_BYTES - (frontPorch + backPorch));pixelBytes++)
            {
                // create 16 bit values from 2 bytes
                if (pixelBytes % 2 != 0)
                    row[(pixelBytes-1)/2] = ((unsigned short)data[start + pixelBytes] << 8) + lastByte;

                lastByte = data[start + pixelBytes];
            }

            //image[std::slice(width*static_cast<unsigned short>(fitsRows*2+1),width,1)] = row; // Odds first
            image[std::slice(width*static_cast<unsigned short>(fitsRows*2),width,1)] = row; // Evens first
        }

        // Add last rows (1021-1010, raw frame is 1017-2032)
        if (fitsRows >= 1021 && fitsRows < 2032)
        {
            const short frontPorch = 70 * 2; // Pixels * Bytes per pixel
            const short backPorch = 0 * 2;   // Pixels * Bytes per pixel

            start = rowIndexes[fitsRows] + frontPorch;

            for (int pixelBytes=0;pixelBytes<(ROW_LENGTH_BYTES - (frontPorch + backPorch));pixelBytes++)
            {
                // create 16 bit values from 2 bytes
                if (pixelBytes % 2 != 0)
                    row[(pixelBytes-1)/2] = ((unsigned short)data[start + pixelBytes] << 8) + lastByte;

                lastByte = data[start + pixelBytes];
            }

            //image[std::slice(width*static_cast<unsigned short>((fitsRows-1017)*2),width,1)] = row; // Odds first
            image[std::slice(width*static_cast<unsigned short>((fitsRows-1016)*2-1),width,1)] = row; // Evens first
        }
    }

    printf("\r\nDone parsing\r\n\r\nGenerating FITS file:\r\n");

    // Save image
    long firstPixel(1);
    long exposure(1500);
    pFits->pHDU().addKey("EXPOSURE", exposure,"Total Exposure Time");

    pFits->pHDU().write(firstPixel,nelements,image);
    std::cout << pFits->pHDU() << std::endl;

    free(data);
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
#include "posixsocket.h"
#include <stdlib.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>

#include <iostream>
using namespace std;

shared_ptr<Socket> Socket::create() {
	return make_shared<PosixSocket>();
}

//-----------------------------------------------------------------------------
PosixSocket::PosixSocket() {

}

//-----------------------------------------------------------------------------
PosixSocket::~PosixSocket() {
	//if(close(sockfd) == -1)
	//		std::cerr << "ERROR: No se ha podido cerrar el socket." << std::endl
}
//-----------------------------------------------------------------------------
bool PosixSocket::Connect(std::string hostIp,int hostPort){
	cerr << "connect()" << endl;
	// Usamos connect cuando tenemos que conectarnos a un server

	// Obtenemos host
	struct hostent *he = gethostbyname(hostIp.c_str());

	// Cargamos datos de la conexión a realizar
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(hostPort);
	// destinoDir.sin_addr.s_addr = inet_addr(ipDestino.c_str());
	sockaddr.sin_addr = *((struct in_addr *)he->h_addr);

	//Ver si es necesario
	//memset(&(sockaddr.sin_zero), '\0', sizeof(sockaddr.sin_zero));

	// Conectamos
	if(connect(this->sockfd, (struct sockaddr *)&sockaddr,
		sizeof(struct sockaddr)) == -1)
		return false;

	return true;
}
//-----------------------------------------------------------------------------
bool PosixSocket::Listen(unsigned int port, int maxConnections)
{
	cerr << "listen()" << endl;
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		return false;

	status =  true;

	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(port);

	sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(	bind(sockfd,
			(struct sockaddr *)&sockaddr,
			sizeof(sockaddr)) < 0)
	{
		return false;
	}

	// Comenzamos la escucha
	if ( listen(sockfd, maxConnections) < 0)
	{
		return false;
	}

	return true;
}
//-----------------------------------------------------------------------------
shared_ptr<Socket> PosixSocket::Accept()
{
	cerr << "accept()" << endl;
	unsigned sin_size = sizeof(struct sockaddr_in);
	//Revisar
	auto socket_client = make_shared<PosixSocket>();

	int sockfd_client = accept(sockfd, (struct sockaddr *)&(socket_client->sockaddr), &sin_size);

	socket_client->sockfd = sockfd_client;
	// Corroboramos si no se cerró el socket
	if(status != 1) return nullptr;

	return socket_client;

}
//-----------------------------------------------------------------------------
int PosixSocket::Send(const void* data, int dataLenght)
{
	cerr << "send()" << endl;
	// Cantidad de bytes que han sido enviados
	int total_bytes = 0;
	// Cantidad de bytes que faltan enviar
	int residuary_bytes = dataLenght;
	// Variable auxiliar
	int n;

	while(residuary_bytes > 0)
	{
		// Realizamos envío de bytes
		n = send(sockfd, (char *) data + total_bytes, residuary_bytes, 0);

		if(n == -1)	return -1;

		total_bytes += n;
		residuary_bytes -= n;
	}

	return 0;

}
//-----------------------------------------------------------------------------
int PosixSocket::Recv(void* data, int dataLenght)
{
	cerr << "receive()" << endl;
	//REVISAR
	//memset(data, '\0', dataLenght);
	// Recibimos datos en buffer
	return recv(sockfd, data, dataLenght, 0);
}
//-----------------------------------------------------------------------------
bool PosixSocket::IsActive()
{
	return status;
}
//-----------------------------------------------------------------------------
void PosixSocket::deinit()
{
	this->status = false;
}
//-----------------------------------------------------------------------------
void PosixSocket::Activate()
{
	this->status = true;
}
//-----------------------------------------------------------------------------
<commit_msg>Arreglo PosixSocket.connect()<commit_after>//-----------------------------------------------------------------------------
#include "posixsocket.h"
#include <stdlib.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>

#include <cstring>

#include <iostream>
using namespace std;

shared_ptr<Socket> Socket::create() {
	return make_shared<PosixSocket>();
}

//-----------------------------------------------------------------------------
PosixSocket::PosixSocket() {

}

//-----------------------------------------------------------------------------
PosixSocket::~PosixSocket() {
	//if(close(sockfd) == -1)
	//		std::cerr << "ERROR: No se ha podido cerrar el socket." << std::endl
}
//-----------------------------------------------------------------------------
bool PosixSocket::Connect(std::string hostIp,int hostPort){
	cerr << "connect()" << endl;
	// Usamos connect cuando tenemos que conectarnos a un server

	// Obtenemos host
	struct hostent *he = gethostbyname(hostIp.c_str());
	if (!he) {
		return false;
	}

	// Obtenemos socket
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		return false;
	}

	// Cargamos datos de la conexión a realizar
	memset(&sockaddr, '\0', sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(hostPort);
	memcpy(&sockaddr.sin_addr, he->h_addr, he->h_length);

	// Conectamos
	if(connect(sockfd, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr)) == -1) {
		return false;
	}

	return true;
}
//-----------------------------------------------------------------------------
bool PosixSocket::Listen(unsigned int port, int maxConnections)
{
	cerr << "listen()" << endl;
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		return false;

	status =  true;

	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(port);

	sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(	bind(sockfd,
			(struct sockaddr *)&sockaddr,
			sizeof(sockaddr)) < 0)
	{
		return false;
	}

	// Comenzamos la escucha
	if ( listen(sockfd, maxConnections) < 0)
	{
		return false;
	}

	return true;
}
//-----------------------------------------------------------------------------
shared_ptr<Socket> PosixSocket::Accept()
{
	cerr << "accept()" << endl;
	unsigned sin_size = sizeof(struct sockaddr_in);
	//Revisar
	auto socket_client = make_shared<PosixSocket>();

	int sockfd_client = accept(sockfd, (struct sockaddr *)&(socket_client->sockaddr), &sin_size);

	socket_client->sockfd = sockfd_client;
	// Corroboramos si no se cerró el socket
	if(status != 1) return nullptr;

	return socket_client;

}
//-----------------------------------------------------------------------------
int PosixSocket::Send(const void* data, int dataLenght)
{
	cerr << "send()" << endl;
	// Cantidad de bytes que han sido enviados
	int total_bytes = 0;
	// Cantidad de bytes que faltan enviar
	int residuary_bytes = dataLenght;
	// Variable auxiliar
	int n;

	while(residuary_bytes > 0)
	{
		// Realizamos envío de bytes
		n = send(sockfd, (char *) data + total_bytes, residuary_bytes, 0);

		if(n == -1)	return -1;

		total_bytes += n;
		residuary_bytes -= n;
	}

	return 0;

}
//-----------------------------------------------------------------------------
int PosixSocket::Recv(void* data, int dataLenght)
{
	cerr << "receive()" << endl;
	//REVISAR
	//memset(data, '\0', dataLenght);
	// Recibimos datos en buffer
	return recv(sockfd, data, dataLenght, 0);
}
//-----------------------------------------------------------------------------
bool PosixSocket::IsActive()
{
	return status;
}
//-----------------------------------------------------------------------------
void PosixSocket::deinit()
{
	this->status = false;
}
//-----------------------------------------------------------------------------
void PosixSocket::Activate()
{
	this->status = true;
}
//-----------------------------------------------------------------------------
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: popupmenucontrollerfactory.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 00:49:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser 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
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIFACTORY_POPUPMENUCONTROLLERFACTORY_HXX_
#define __FRAMEWORK_UIFACTORY_POPUPMENUCONTROLLERFACTORY_HXX_

/** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble
               with solaris headers ...
*/
#include <vector>
#include <list>

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XSERVICEINFO_HXX_
#include <macros/xserviceinfo.hxx>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTICOMPONENTFACTORY_HPP_
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XUICONTROLLERREGISTRATION_HPP_
#include <com/sun/star/frame/XUIControllerRegistration.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

namespace framework
{

class ConfigurationAccess_PopupMenuControllerFactory;
class PopupMenuControllerFactory :  public com::sun::star::lang::XTypeProvider                          ,
                                    public com::sun::star::lang::XServiceInfo                           ,
                                    public com::sun::star::lang::XMultiComponentFactory                 ,
                                    public ::com::sun::star::frame::XUIControllerRegistration     ,
                                    private ThreadHelpBase                                              ,   // Struct for right initalization of mutex member! Must be first of baseclasses.
                                    public ::cppu::OWeakObject
{
    public:
        PopupMenuControllerFactory( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );
        virtual ~PopupMenuControllerFactory();

        //  XInterface, XTypeProvider, XServiceInfo
        DECLARE_XINTERFACE
        DECLARE_XTYPEPROVIDER
        DECLARE_XSERVICEINFO

        // XMultiComponentFactory
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithContext( const ::rtl::OUString& aServiceSpecifier, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& Context ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArgumentsAndContext( const ::rtl::OUString& ServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& Context ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames() throw (::com::sun::star::uno::RuntimeException);

        // XUIControllerRegistration
        virtual sal_Bool SAL_CALL hasController( const ::rtl::OUString& aCommandURL, const rtl::OUString& aModuleName ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL registerController( const ::rtl::OUString& aCommandURL, const rtl::OUString& aModuleName, const ::rtl::OUString& aControllerImplementationName ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL deregisterController( const ::rtl::OUString& aCommandURL, const rtl::OUString& aModuleName ) throw (::com::sun::star::uno::RuntimeException);

    private:
        sal_Bool                                                                         m_bConfigRead;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceManager;
        ConfigurationAccess_PopupMenuControllerFactory*                                  m_pConfigAccess;
};

} // namespace framework

#endif // __FRAMEWORK_SERVICES_POPUPMENUCONTROLLERFACTORY_HXX_
<commit_msg>INTEGRATION: CWS warnings01 (1.5.32); FILE MERGED 2005/10/28 14:48:23 cd 1.5.32.1: #i55991# Warning free code changes for gcc<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: popupmenucontrollerfactory.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 11:07:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser 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
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIFACTORY_POPUPMENUCONTROLLERFACTORY_HXX_
#define __FRAMEWORK_UIFACTORY_POPUPMENUCONTROLLERFACTORY_HXX_

/** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble
               with solaris headers ...
*/
#include <vector>
#include <list>

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XSERVICEINFO_HXX_
#include <macros/xserviceinfo.hxx>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTICOMPONENTFACTORY_HPP_
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XUICONTROLLERREGISTRATION_HPP_
#include <com/sun/star/frame/XUIControllerRegistration.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

namespace framework
{

class ConfigurationAccess_PopupMenuControllerFactory;
class PopupMenuControllerFactory :  public com::sun::star::lang::XTypeProvider                          ,
                                    public com::sun::star::lang::XServiceInfo                           ,
                                    public com::sun::star::lang::XMultiComponentFactory                 ,
                                    public ::com::sun::star::frame::XUIControllerRegistration     ,
                                    private ThreadHelpBase                                              ,   // Struct for right initalization of mutex member! Must be first of baseclasses.
                                    public ::cppu::OWeakObject
{
    public:
        PopupMenuControllerFactory( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );
        virtual ~PopupMenuControllerFactory();

        //  XInterface, XTypeProvider, XServiceInfo
        FWK_DECLARE_XINTERFACE
        FWK_DECLARE_XTYPEPROVIDER
        DECLARE_XSERVICEINFO

        // XMultiComponentFactory
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithContext( const ::rtl::OUString& aServiceSpecifier, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& Context ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArgumentsAndContext( const ::rtl::OUString& ServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& Context ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames() throw (::com::sun::star::uno::RuntimeException);

        // XUIControllerRegistration
        virtual sal_Bool SAL_CALL hasController( const ::rtl::OUString& aCommandURL, const rtl::OUString& aModuleName ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL registerController( const ::rtl::OUString& aCommandURL, const rtl::OUString& aModuleName, const ::rtl::OUString& aControllerImplementationName ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL deregisterController( const ::rtl::OUString& aCommandURL, const rtl::OUString& aModuleName ) throw (::com::sun::star::uno::RuntimeException);

    private:
        sal_Bool                                                                         m_bConfigRead;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceManager;
        ConfigurationAccess_PopupMenuControllerFactory*                                  m_pConfigAccess;
};

} // namespace framework

#endif // __FRAMEWORK_SERVICES_POPUPMENUCONTROLLERFACTORY_HXX_
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// Copyright (c) 2016 John D. Haughton
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//------------------------------------------------------------------------------

#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <stdlib.h>

#include "PLT/Frame.h"

namespace PLT {

class FrameImpl
{
private:
   unsigned  width;
   unsigned  height;
   uint8_t*  buffer;
   int       refresh_fd;

   size_t getSize() const { return width * height / 2; }

   static void error(const char* format, ...)
   {
      va_list ap;

      fprintf(stderr, "ERROR - ");

      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);

      fprintf(stderr, "\n");
      exit(1);
   }

   static int openDev(const char* filename)
   {
      int fd = open(filename, O_RDWR);
      if (-1 == fd)
      {
         error("Failed to open \"%s\"", filename);
      }
      return fd;
   }

public:
   FrameImpl(const char*  title_, unsigned width_, unsigned height_, uint32_t flags_)
   {
      int fd = openDev("/dev/fb0");

      struct fb_var_screeninfo screeninfo;
      int status = ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo);
      if (-1 == status)
      {
         error("ioctl(.. FBIOGET_VSCREENINFO) failed");
      }

      width  = screeninfo.xres;
      height = screeninfo.yres;

      buffer = (uint8_t*) mmap(0, getSize(),
                               PROT_READ | PROT_WRITE,
                               MAP_SHARED, fd, 0);
      if (0 == buffer)
      {
         error("mmap() failed");
      }

      close(fd);

      refresh_fd = openDev("/proc/eink_fb/update_display");
   }

   ~FrameImpl()
   {
      munmap(buffer, getSize());
      close(refresh_fd);
   }

   uint8_t* getPointer(unsigned& pitch)
   {
      pitch = width;
      return buffer;
   }

   void resize(unsigned width_, unsigned height_)
   {
   }

   void refresh()
   {
      write(refresh_fd, "2", 1);
   }
};

Frame::Frame(const char* title_,
             unsigned    width_,
             unsigned    height_,
             uint32_t    flags_)
   : FrameBase(width_, height_)
{
   pimpl  = new FrameImpl(title_, width, height, flags_);
   buffer = pimpl->getPointer(pitch);
}

Frame::~Frame()
{
   delete pimpl;
}

void Frame::blit(unsigned x,
                 unsigned y,
                 unsigned src_offset,
                 unsigned src_width,
                 const FrameBase& src)
{
}

void Frame::resize(unsigned width_, unsigned height_)
{
   if ((width == width_) && (height == height_)) return;

   width  = width_;
   height = height_;

   pimpl->resize(width_, height_);
   buffer = pimpl->getPointer(pitch);
}

void Frame::refresh()
{
   pimpl->refresh();
}

} // namespace PLT

<commit_msg>Kindle3 build - avoid a warning<commit_after>//------------------------------------------------------------------------------
// Copyright (c) 2016 John D. Haughton
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//------------------------------------------------------------------------------

#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <stdlib.h>

#include "PLT/Frame.h"

namespace PLT {

class FrameImpl
{
private:
   unsigned  width;
   unsigned  height;
   uint8_t*  buffer;
   int       refresh_fd;

   size_t getSize() const { return width * height / 2; }

   static void error(const char* format, ...)
   {
      va_list ap;

      fprintf(stderr, "ERROR - ");

      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);

      fprintf(stderr, "\n");
      exit(1);
   }

   static int openDev(const char* filename)
   {
      int fd = open(filename, O_RDWR);
      if (-1 == fd)
      {
         error("Failed to open \"%s\"", filename);
      }
      return fd;
   }

public:
   FrameImpl(const char*  title_, unsigned width_, unsigned height_, uint32_t flags_)
   {
      int fd = openDev("/dev/fb0");

      struct fb_var_screeninfo screeninfo;
      int status = ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo);
      if (-1 == status)
      {
         error("ioctl(.. FBIOGET_VSCREENINFO) failed");
      }

      width  = screeninfo.xres;
      height = screeninfo.yres;

      buffer = (uint8_t*) mmap(0, getSize(),
                               PROT_READ | PROT_WRITE,
                               MAP_SHARED, fd, 0);
      if (0 == buffer)
      {
         error("mmap() failed");
      }

      close(fd);

      refresh_fd = openDev("/proc/eink_fb/update_display");
   }

   ~FrameImpl()
   {
      munmap(buffer, getSize());
      close(refresh_fd);
   }

   uint8_t* getPointer(unsigned& pitch)
   {
      pitch = width;
      return buffer;
   }

   void resize(unsigned width_, unsigned height_)
   {
   }

   void refresh()
   {
      (void) write(refresh_fd, "2", 1);
   }
};

Frame::Frame(const char* title_,
             unsigned    width_,
             unsigned    height_,
             uint32_t    flags_)
   : FrameBase(width_, height_)
{
   pimpl  = new FrameImpl(title_, width, height, flags_);
   buffer = pimpl->getPointer(pitch);
}

Frame::~Frame()
{
   delete pimpl;
}

void Frame::blit(unsigned x,
                 unsigned y,
                 unsigned src_offset,
                 unsigned src_width,
                 const FrameBase& src)
{
}

void Frame::resize(unsigned width_, unsigned height_)
{
   if ((width == width_) && (height == height_)) return;

   width  = width_;
   height = height_;

   pimpl->resize(width_, height_);
   buffer = pimpl->getPointer(pitch);
}

void Frame::refresh()
{
   pimpl->refresh();
}

} // namespace PLT

<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2011 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*/

#include "messageview.h"
#include "session.h"
#include "settings.h"
#include "completer.h"
#include "application.h"
#include <QStringListModel>
#include <QShortcut>
#include <QKeyEvent>
#include <QDebug>
#include <irccommand.h>
#include <ircutil.h>
#include <irc.h>

QStringListModel* MessageView::MessageViewData::commandModel = 0;

MessageView::MessageView(IrcSession* session, QWidget* parent) :
    QWidget(parent)
{
    d.setupUi(this);

    setFocusProxy(d.editFrame->lineEdit());
    d.textBrowser->installEventFilter(this);
    d.textBrowser->viewport()->installEventFilter(this);

    d.session = session;
    d.formatter.setHightlights(QStringList(session->nickName()));
    connect(&d.parser, SIGNAL(customCommand(QString,QStringList)), this, SLOT(onCustomCommand(QString,QStringList)));

    d.userModel = new QStringListModel(this);

    if (!d.commandModel)
    {
        CommandParser::addCustomCommand("CONNECT", "(<host> <port>)");
        CommandParser::addCustomCommand("QUERY", "<user>");
        CommandParser::addCustomCommand("SETTINGS", "");

        QStringList prefixedCommands;
        foreach (const QString& command, CommandParser::availableCommands())
            prefixedCommands += "/" + command;

        d.commandModel = new QStringListModel(qApp);
        d.commandModel->setStringList(prefixedCommands);
    }

    d.editFrame->completer()->setDefaultModel(d.userModel);
    d.editFrame->completer()->setSlashModel(d.commandModel);

    connect(d.editFrame, SIGNAL(send(QString)), this, SLOT(onSend(QString)));
    connect(d.editFrame, SIGNAL(typed(QString)), this, SLOT(showHelp(QString)));

    d.helpLabel->hide();
    d.findFrame->setTextEdit(d.textBrowser);

    QShortcut* shortcut = new QShortcut(Qt::Key_Escape, this);
    connect(shortcut, SIGNAL(activated()), this, SLOT(onEscPressed()));

    connect(qApp, SIGNAL(settingsChanged(Settings)), this, SLOT(applySettings(Settings)));
    applySettings(Application::settings());
}

MessageView::~MessageView()
{
}

QString MessageView::receiver() const
{
    return d.receiver;
}

void MessageView::setReceiver(const QString& receiver)
{
    d.receiver = receiver;
}

bool MessageView::isChannelView() const
{
    if (d.receiver.isEmpty())
        return false;

    switch (d.receiver.at(0).unicode())
    {
        case '#':
        case '&':
        case '!':
        case '+':
            return true;
        default:
            return false;
    }
}

void MessageView::showHelp(const QString& text, bool error)
{
    QString syntax;
    if (text == "/")
    {
        QStringList commands = CommandParser::availableCommands();
        syntax = commands.join(" ");
    }
    else if (text.startsWith('/'))
    {
        QStringList words = text.mid(1).split(' ');
        QString command = words.value(0);
        QStringList suggestions = CommandParser::suggestedCommands(command, words.mid(1));
        if (suggestions.count() == 1)
            syntax = CommandParser::syntax(suggestions.first());
        else
            syntax = suggestions.join(" ");

        if (syntax.isEmpty() && error)
            syntax = tr("Unknown command '%1'").arg(command.toUpper());
    }

    d.helpLabel->setVisible(!syntax.isEmpty());
    QPalette pal;
    if (error)
        pal.setColor(QPalette::WindowText, Qt::red);
    d.helpLabel->setPalette(pal);
    d.helpLabel->setText(syntax);
}

void MessageView::appendMessage(const QString& message)
{
    // workaround the link activation merge char format bug
//    if (message.endsWith(""))
//        message += " ";

    if (!message.isEmpty())
        d.textBrowser->append(message);
}

bool MessageView::eventFilter(QObject* receiver, QEvent* event)
{
    Q_UNUSED(receiver);
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        // for example:
        // - Ctrl+C goes to the browser
        // - Ctrl+V goes to the line edit
        // - Shift+7 ("/") goes to the line edit
        switch (keyEvent->key())
        {
            case Qt::Key_Shift:
            case Qt::Key_Control:
            case Qt::Key_Meta:
            case Qt::Key_Alt:
            case Qt::Key_AltGr:
                break;
            default:
                if (!keyEvent->matches(QKeySequence::Copy))
                {
                    QApplication::sendEvent(d.editFrame->lineEdit(), keyEvent);
                    d.editFrame->lineEdit()->setFocus();
                    return true;
                }
                break;
        }
    }
    return false;
}

void MessageView::onEscPressed()
{
    d.helpLabel->hide();
    d.findFrame->hide();
    setFocus(Qt::OtherFocusReason);
}

void MessageView::onSend(const QString& text)
{
    IrcCommand* cmd = d.parser.parseCommand(d.receiver, text);
    if (cmd)
    {
        d.session->sendCommand(cmd);

        if (cmd->type() == IrcCommand::Message || cmd->type() == IrcCommand::CtcpAction)
        {
            IrcMessage* msg = IrcMessage::fromCommand(d.session->nickName(), cmd);
            receiveMessage(msg);
            delete msg;
        }
    }
    else if (d.parser.hasError())
    {
        showHelp(text, true);
    }
}

void MessageView::applySettings(const Settings& settings)
{
    d.formatter.setTimeStamp(settings.timeStamp);
    d.textBrowser->setFont(settings.font);
    d.textBrowser->document()->setMaximumBlockCount(settings.maxBlockCount);

    QString backgroundColor = settings.colors.value(Settings::Background);
    d.textBrowser->setStyleSheet(QString("QTextBrowser { background-color: %1 }").arg(backgroundColor));

    d.textBrowser->document()->setDefaultStyleSheet(
        QString(
            ".highlight { color: %1 }"
            ".message   { color: %2 }"
            ".notice    { color: %3 }"
            ".action    { color: %4 }"
            ".event     { color: %5 }"
        ).arg(settings.colors.value((Settings::Highlight)))
         .arg(settings.colors.value((Settings::Message)))
         .arg(settings.colors.value((Settings::Notice)))
         .arg(settings.colors.value((Settings::Action)))
         .arg(settings.colors.value((Settings::Event))));
}

void MessageView::receiveMessage(IrcMessage* message)
{
    bool append = true;
    bool hilite = false;
    bool matches = false;

    switch (message->type())
    {
    case IrcMessage::Join:
        append = Application::settings().messages.value(Settings::Joins);
        hilite = Application::settings().highlights.value(Settings::Joins);
        break;
    case IrcMessage::Kick:
        append = Application::settings().messages.value(Settings::Kicks);
        hilite = Application::settings().highlights.value(Settings::Kicks);
        break;
    case IrcMessage::Mode:
        append = Application::settings().messages.value(Settings::Modes);
        hilite = Application::settings().highlights.value(Settings::Modes);
        break;
    case IrcMessage::Nick:
        append = Application::settings().messages.value(Settings::Nicks);
        hilite = Application::settings().highlights.value(Settings::Nicks);
        break;
    case IrcMessage::Notice:
        matches = static_cast<IrcNoticeMessage*>(message)->message().contains(d.session->nickName());
        hilite = true;
        break;
    case IrcMessage::Part:
        append = Application::settings().messages.value(Settings::Parts);
        hilite = Application::settings().highlights.value(Settings::Parts);
        break;
    case IrcMessage::Private:
        matches = !isChannelView() || static_cast<IrcPrivateMessage*>(message)->message().contains(d.session->nickName());
        hilite = true;
        break;
    case IrcMessage::Quit:
        append = Application::settings().messages.value(Settings::Quits);
        hilite = Application::settings().highlights.value(Settings::Quits);
        break;
    case IrcMessage::Topic:
        append = Application::settings().messages.value(Settings::Topics);
        hilite = Application::settings().highlights.value(Settings::Topics);
        break;
    case IrcMessage::Unknown:
        qWarning() << "unknown:" << message;
        append = false;
        break;
    case IrcMessage::Invite:
    case IrcMessage::Numeric:
    case IrcMessage::Ping:
    case IrcMessage::Pong:
    case IrcMessage::Error:
        break;
    }

    if (matches)
        emit alert(this, true);
    else if (hilite)
        emit highlight(this, true);
    if (append)
        appendMessage(d.formatter.formatMessage(message));
}

void MessageView::addUser(const QString& user)
{
    // TODO: this is far from optimal
    QStringList users = d.userModel->stringList();
    users.append(user);
    d.userModel->setStringList(users);
}

void MessageView::removeUser(const QString& user)
{
    // TODO: this is far from optimal
    QStringList users = d.userModel->stringList();
    if (users.removeOne(user))
        d.userModel->setStringList(users);
}

void MessageView::onCustomCommand(const QString& command, const QStringList& params)
{
    if (command == "QUERY")
        emit query(params.value(0));
    else if (command == "SETTINGS")
        Application::showSettings();
    else if (command == "CONNECT")
        QMetaObject::invokeMethod(window(), "connectTo", Q_ARG(QString, params.value(0)), params.count() > 1 ? Q_ARG(quint16, params.value(1).toInt()) : QGenericArgument());
}
<commit_msg>MessageView: re-enabled the workaround for a link activation merge char format bug<commit_after>/*
* Copyright (C) 2008-2011 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*/

#include "messageview.h"
#include "session.h"
#include "settings.h"
#include "completer.h"
#include "application.h"
#include <QStringListModel>
#include <QShortcut>
#include <QKeyEvent>
#include <QDebug>
#include <irccommand.h>
#include <ircutil.h>
#include <irc.h>

QStringListModel* MessageView::MessageViewData::commandModel = 0;

MessageView::MessageView(IrcSession* session, QWidget* parent) :
    QWidget(parent)
{
    d.setupUi(this);

    setFocusProxy(d.editFrame->lineEdit());
    d.textBrowser->installEventFilter(this);
    d.textBrowser->viewport()->installEventFilter(this);

    d.session = session;
    d.formatter.setHightlights(QStringList(session->nickName()));
    connect(&d.parser, SIGNAL(customCommand(QString,QStringList)), this, SLOT(onCustomCommand(QString,QStringList)));

    d.userModel = new QStringListModel(this);

    if (!d.commandModel)
    {
        CommandParser::addCustomCommand("CONNECT", "(<host> <port>)");
        CommandParser::addCustomCommand("QUERY", "<user>");
        CommandParser::addCustomCommand("SETTINGS", "");

        QStringList prefixedCommands;
        foreach (const QString& command, CommandParser::availableCommands())
            prefixedCommands += "/" + command;

        d.commandModel = new QStringListModel(qApp);
        d.commandModel->setStringList(prefixedCommands);
    }

    d.editFrame->completer()->setDefaultModel(d.userModel);
    d.editFrame->completer()->setSlashModel(d.commandModel);

    connect(d.editFrame, SIGNAL(send(QString)), this, SLOT(onSend(QString)));
    connect(d.editFrame, SIGNAL(typed(QString)), this, SLOT(showHelp(QString)));

    d.helpLabel->hide();
    d.findFrame->setTextEdit(d.textBrowser);

    QShortcut* shortcut = new QShortcut(Qt::Key_Escape, this);
    connect(shortcut, SIGNAL(activated()), this, SLOT(onEscPressed()));

    connect(qApp, SIGNAL(settingsChanged(Settings)), this, SLOT(applySettings(Settings)));
    applySettings(Application::settings());
}

MessageView::~MessageView()
{
}

QString MessageView::receiver() const
{
    return d.receiver;
}

void MessageView::setReceiver(const QString& receiver)
{
    d.receiver = receiver;
}

bool MessageView::isChannelView() const
{
    if (d.receiver.isEmpty())
        return false;

    switch (d.receiver.at(0).unicode())
    {
        case '#':
        case '&':
        case '!':
        case '+':
            return true;
        default:
            return false;
    }
}

void MessageView::showHelp(const QString& text, bool error)
{
    QString syntax;
    if (text == "/")
    {
        QStringList commands = CommandParser::availableCommands();
        syntax = commands.join(" ");
    }
    else if (text.startsWith('/'))
    {
        QStringList words = text.mid(1).split(' ');
        QString command = words.value(0);
        QStringList suggestions = CommandParser::suggestedCommands(command, words.mid(1));
        if (suggestions.count() == 1)
            syntax = CommandParser::syntax(suggestions.first());
        else
            syntax = suggestions.join(" ");

        if (syntax.isEmpty() && error)
            syntax = tr("Unknown command '%1'").arg(command.toUpper());
    }

    d.helpLabel->setVisible(!syntax.isEmpty());
    QPalette pal;
    if (error)
        pal.setColor(QPalette::WindowText, Qt::red);
    d.helpLabel->setPalette(pal);
    d.helpLabel->setText(syntax);
}

void MessageView::appendMessage(const QString& message)
{
    if (!message.isEmpty())
    {
        // workaround the link activation merge char format bug
        QString copy = message;
        if (copy.endsWith(""))
            copy += " ";

        d.textBrowser->append(copy);
    }
}

bool MessageView::eventFilter(QObject* receiver, QEvent* event)
{
    Q_UNUSED(receiver);
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        // for example:
        // - Ctrl+C goes to the browser
        // - Ctrl+V goes to the line edit
        // - Shift+7 ("/") goes to the line edit
        switch (keyEvent->key())
        {
            case Qt::Key_Shift:
            case Qt::Key_Control:
            case Qt::Key_Meta:
            case Qt::Key_Alt:
            case Qt::Key_AltGr:
                break;
            default:
                if (!keyEvent->matches(QKeySequence::Copy))
                {
                    QApplication::sendEvent(d.editFrame->lineEdit(), keyEvent);
                    d.editFrame->lineEdit()->setFocus();
                    return true;
                }
                break;
        }
    }
    return false;
}

void MessageView::onEscPressed()
{
    d.helpLabel->hide();
    d.findFrame->hide();
    setFocus(Qt::OtherFocusReason);
}

void MessageView::onSend(const QString& text)
{
    IrcCommand* cmd = d.parser.parseCommand(d.receiver, text);
    if (cmd)
    {
        d.session->sendCommand(cmd);

        if (cmd->type() == IrcCommand::Message || cmd->type() == IrcCommand::CtcpAction)
        {
            IrcMessage* msg = IrcMessage::fromCommand(d.session->nickName(), cmd);
            receiveMessage(msg);
            delete msg;
        }
    }
    else if (d.parser.hasError())
    {
        showHelp(text, true);
    }
}

void MessageView::applySettings(const Settings& settings)
{
    d.formatter.setTimeStamp(settings.timeStamp);
    d.textBrowser->setFont(settings.font);
    d.textBrowser->document()->setMaximumBlockCount(settings.maxBlockCount);

    QString backgroundColor = settings.colors.value(Settings::Background);
    d.textBrowser->setStyleSheet(QString("QTextBrowser { background-color: %1 }").arg(backgroundColor));

    d.textBrowser->document()->setDefaultStyleSheet(
        QString(
            ".highlight { color: %1 }"
            ".message   { color: %2 }"
            ".notice    { color: %3 }"
            ".action    { color: %4 }"
            ".event     { color: %5 }"
        ).arg(settings.colors.value((Settings::Highlight)))
         .arg(settings.colors.value((Settings::Message)))
         .arg(settings.colors.value((Settings::Notice)))
         .arg(settings.colors.value((Settings::Action)))
         .arg(settings.colors.value((Settings::Event))));
}

void MessageView::receiveMessage(IrcMessage* message)
{
    bool append = true;
    bool hilite = false;
    bool matches = false;

    switch (message->type())
    {
    case IrcMessage::Join:
        append = Application::settings().messages.value(Settings::Joins);
        hilite = Application::settings().highlights.value(Settings::Joins);
        break;
    case IrcMessage::Kick:
        append = Application::settings().messages.value(Settings::Kicks);
        hilite = Application::settings().highlights.value(Settings::Kicks);
        break;
    case IrcMessage::Mode:
        append = Application::settings().messages.value(Settings::Modes);
        hilite = Application::settings().highlights.value(Settings::Modes);
        break;
    case IrcMessage::Nick:
        append = Application::settings().messages.value(Settings::Nicks);
        hilite = Application::settings().highlights.value(Settings::Nicks);
        break;
    case IrcMessage::Notice:
        matches = static_cast<IrcNoticeMessage*>(message)->message().contains(d.session->nickName());
        hilite = true;
        break;
    case IrcMessage::Part:
        append = Application::settings().messages.value(Settings::Parts);
        hilite = Application::settings().highlights.value(Settings::Parts);
        break;
    case IrcMessage::Private:
        matches = !isChannelView() || static_cast<IrcPrivateMessage*>(message)->message().contains(d.session->nickName());
        hilite = true;
        break;
    case IrcMessage::Quit:
        append = Application::settings().messages.value(Settings::Quits);
        hilite = Application::settings().highlights.value(Settings::Quits);
        break;
    case IrcMessage::Topic:
        append = Application::settings().messages.value(Settings::Topics);
        hilite = Application::settings().highlights.value(Settings::Topics);
        break;
    case IrcMessage::Unknown:
        qWarning() << "unknown:" << message;
        append = false;
        break;
    case IrcMessage::Invite:
    case IrcMessage::Numeric:
    case IrcMessage::Ping:
    case IrcMessage::Pong:
    case IrcMessage::Error:
        break;
    }

    if (matches)
        emit alert(this, true);
    else if (hilite)
        emit highlight(this, true);
    if (append)
        appendMessage(d.formatter.formatMessage(message));
}

void MessageView::addUser(const QString& user)
{
    // TODO: this is far from optimal
    QStringList users = d.userModel->stringList();
    users.append(user);
    d.userModel->setStringList(users);
}

void MessageView::removeUser(const QString& user)
{
    // TODO: this is far from optimal
    QStringList users = d.userModel->stringList();
    if (users.removeOne(user))
        d.userModel->setStringList(users);
}

void MessageView::onCustomCommand(const QString& command, const QStringList& params)
{
    if (command == "QUERY")
        emit query(params.value(0));
    else if (command == "SETTINGS")
        Application::showSettings();
    else if (command == "CONNECT")
        QMetaObject::invokeMethod(window(), "connectTo", Q_ARG(QString, params.value(0)), params.count() > 1 ? Q_ARG(quint16, params.value(1).toInt()) : QGenericArgument());
}
<|endoftext|>