<commit_before>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <limits>

#include <utils.hpp>

#ifndef OBSERVATION_HPP
#define OBSERVATION_HPP

namespace AstroData {

class Observation {
public:
  Observation();
  ~Observation();

  // Getters
  // General observation parameters
  unsigned int getNrBatches() const;
  unsigned int getNrStations() const;
  unsigned int getNrPaddedStations(unsigned int padding) const;
  unsigned int getNrBeams() const;
  unsigned int getNrPaddedBeams(unsigned int padding) const;
  unsigned int getNrSynthesizedBeams() const;
  unsigned int getNrPaddedSynthesizedBeams(const unsigned int padding) const;
  float getSamplingTime() const;
  unsigned int getNrSamplesPerBatch() const;
  unsigned int getNrSamplesPerPaddedBatch(unsigned int padding) const;
  // Frequency parameters
  unsigned int getNrSubbands() const;
  unsigned int getNrChannels() const;
  unsigned int getNrChannelsPerSubband() const;
  unsigned int getNrPaddedSubbands(unsigned int padding) const;
  unsigned int getNrPaddedChannels(unsigned int padding) const;
  unsigned int getNrZappedChannels() const;
  float getSubbandMinFreq() const;
  float getSubbandMaxFreq() const;
  float getSubbandBandwidth() const;
  float getMinFreq() const;
  float getMaxFreq() const;
  float getChannelBandwidth() const;
  // Dispersion measures
  unsigned int getNrSamplesPerBatchSubbanding() const;
  unsigned int getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const;
  unsigned int getNrDelayBatchesSubbanding() const;
  unsigned int getNrDelayBatches() const;
  unsigned int getNrDMsSubbanding() const;
  unsigned int getNrDMs() const;
  unsigned int getNrPaddedDMsSubbanding(unsigned int padding) const;
  unsigned int getNrPaddedDMs(unsigned int padding) const;
  unsigned int getNrSamplesPerSubbandingDispersedChannel() const;
  unsigned int getNrSamplesPerDispersedChannel() const;
  unsigned int getNrSamplesPerPaddedSubbandingDispersedChannel(unsigned int padding) const;
  unsigned int getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const;
  float getFirstDMSubbanding() const;
  float getFirstDM() const;
  float getLastDMSubbanding() const;
  float getLastDM() const;
  float getDMStep_subbanding() const;
  float getDMStep() const;
  // Periods
  unsigned int getNrPeriods() const;
  unsigned int getNrPaddedPeriods(unsigned int padding) const;
  unsigned int getFirstPeriod() const;
  unsigned int getLastPeriod() const;
  unsigned int getPeriodStep() const;
  unsigned int getNrBins() const;
  unsigned int getNrPaddedBins(unsigned int padding) const;

  // Setters
  // General observation parameters
  void setNrBatches(const unsigned int batches);
  void setNrStations(const unsigned int stations);
  void setNrBeams(const unsigned int beams);
  void setNrSynthesizedBeams(const unsigned int beams);
  void setSamplingTime(const float sampling);
  void setNrSamplesPerBatch(const unsigned int samples);
  // Frequency parameters
  void setFrequencyRange(const unsigned int subbands, const unsigned int channels, const float baseFrequency, const float bandwidth);
  void setNrZappedChannels(const unsigned int zappedChannels);
  // Dispersion measures
  void setNrSamplesPerBatchSubbanding(const unsigned int samples);
  void setNrDelayBatchesSubbanding(const unsigned int batches);
  void setNrDelayBatches(const unsigned int batches);
  void setNrSamplesPerSubbandingDispersedChannel(const unsigned int samples);
  void setNrSamplesPerDispersedChannel(const unsigned int samples);
  void setDMSubbandingRange(const unsigned int dms, const float baseDM, const float step);
  void setDMRange(const unsigned int dms, const float baseDM, const float step);
  // Periods
  void setPeriodRange(const unsigned int periods, const unsigned int basePeriod, const unsigned int step);
  void setNrBins(const unsigned int bins);

private:
  unsigned int nrBatches;
  unsigned int nrStations;
  unsigned int nrBeams;
  unsigned int nrSynthesizedBeams;
  float samplingTime;
  unsigned int nrSamplesPerBatch;
  unsigned int nrSamplesPerBatch_subbanding;
  unsigned int nrSamplesPerDispersedChannel;
  unsigned int nrSamplesPerDispersedChannel_subbanding;

  unsigned int nrSubbands;
  unsigned int nrChannels;
  unsigned int nrChannelsPerSubband;
  unsigned int nrZappedChannels;
  float minSubbandFreq;
  float maxSubbandFreq;
  float subbandBandwidth;
  float minChannelFreq;
  float maxChannelFreq;
  float channelBandwidth;

  unsigned int nrDelayBatches;
  unsigned int nrDelayBatches_subbanding;
  unsigned int nrDMs;
  unsigned int nrDMs_subbanding;
  float firstDM;
  float firstDM_subbanding;
  float lastDM;
  float lastDM_subbanding;
  float DMStep;
  float DMStep_subbanding;

  unsigned int nrPeriods;
  unsigned int firstPeriod;
  unsigned int lastPeriod;
  unsigned int periodStep;
  unsigned int nrBins;
};

// Implementations
inline unsigned int Observation::getNrBatches() const {
  return nrBatches;
}

inline unsigned int Observation::getNrStations() const {
  return nrStations;
}

inline unsigned int Observation::getNrPaddedStations(unsigned int padding) const {
  return isa::utils::pad(nrStations, padding);
}

inline unsigned int Observation::getNrBeams() const {
  return nrBeams;
}

inline unsigned int Observation::getNrPaddedBeams(unsigned int padding) const {
  return isa::utils::pad(nrBeams, padding);
}

inline unsigned int Observation::getNrSynthesizedBeams() const {
  return nrSynthesizedBeams;
}

inline unsigned int Observation::getNrPaddedSynthesizedBeams(unsigned int padding) const {
  return isa::utils::pad(nrSynthesizedBeams, padding);
}

inline unsigned int Observation::getNrSamplesPerBatch() const {
  return nrSamplesPerBatch;
}

inline float Observation::getSamplingTime() const {
  return samplingTime;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatch(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerBatch, padding);
}

inline unsigned int Observation::getNrSubbands() const {
  return nrSubbands;
}

inline unsigned int Observation::getNrChannelsPerSubband() const {
  return nrChannelsPerSubband;
}

inline unsigned int Observation::getNrChannels() const {
  return nrChannels;
}

inline unsigned int Observation::getNrPaddedSubbands(unsigned int padding) const {
  return isa::utils::pad(nrSubbands, padding);
}

inline unsigned int Observation::getNrPaddedChannels(unsigned int padding) const {
  return isa::utils::pad(nrChannels, padding);
}

inline unsigned int Observation::getNrZappedChannels() const {
  return nrZappedChannels;
}

inline unsigned int Observation::getNrSamplesPerPaddedSubbandingDispersedChannel(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerDispersedChannel_subbanding, padding);
}

inline unsigned int Observation::getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerDispersedChannel, padding);
}

inline float Observation::getSubbandMinFreq() const {
  return minSubbandFreq;
}

inline float Observation::getSubbandMaxFreq() const {
  return maxSubbandFreq;
}

inline float Observation::getSubbandBandwidth() const {
  return subbandBandwidth;
}

inline float Observation::getMinFreq() const {
  return minChannelFreq;
}

inline float Observation::getMaxFreq() const {
  return maxChannelFreq;
}

inline float Observation::getChannelBandwidth() const {
  return channelBandwidth;
}

inline unsigned int Observation::getNrSamplesPerSubbandingDispersedChannel() const {
  return nrSamplesPerDispersedChannel_subbanding;
}

inline unsigned int Observation::getNrSamplesPerDispersedChannel() const {
  return nrSamplesPerDispersedChannel;
}

inline unsigned int Observation::getNrSamplesPerBatchSubbanding() const {
  return nrSamplesPerBatch_subbanding;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerBatch_subbanding, padding);
}

inline unsigned int Observation::getNrDelayBatchesSubbanding() const {
  return nrDelayBatches_subbanding;
}

inline unsigned int Observation::getNrDelayBatches() const {
  return nrDelayBatches;
}

inline unsigned int Observation::getNrDMsSubbanding() const {
  return nrDMsSubbanding;
}

inline unsigned int Observation::getNrDMs() const {
  return nrDMs;
}

inline unsigned int Observation::getNrPaddedDMsSubbanding(unsigned int padding) const {
  return isa::utils::pad(nrDMsSubbanding, padding);
}

inline unsigned int Observation::getNrPaddedDMs(unsigned int padding) const {
  return isa::utils::pad(nrDMs, padding);
}

inline float Observation::getFirstDMSubbanding() const {
  return firstDM_subbanding;
}

inline float Observation::getFirstDM() const {
  return firstDM;
}

inline float Observation::getLastDMSubbanding() const {
  return lastDM_subbanding;
}

inline float Observation::getLastDM() const {
  return lastDM;
}

inline float Observation::getDMStep_subbanding() const {
  return DMStep_subbanding;
}

inline float Observation::getDMStep() const {
  return DMStep;
}

inline unsigned int Observation::getNrPeriods() const {
  return nrPeriods;
}

inline unsigned int Observation::getNrPaddedPeriods(unsigned int padding) const {
  return isa::utils::pad(nrPeriods, padding);
}

inline unsigned int Observation::getNrBins() const {
  return nrBins;
}

inline unsigned int Observation::getNrPaddedBins(unsigned int padding) const {
  return isa::utils::pad(nrBins, padding);
}

inline unsigned int Observation::getFirstPeriod() const {
  return firstPeriod;
}

inline unsigned int Observation::getLastPeriod() const {
  return lastPeriod;
}

inline unsigned int Observation::getPeriodStep() const {
  return periodStep;
}

inline void Observation::setNrBatches(const unsigned int batches) {
  nrBatches = batches;
}

inline void Observation::setNrStations(const unsigned int stations) {
  nrStations = stations;
}

inline void Observation::setNrBeams(const unsigned int beams) {
  nrBeams = beams;
}

inline void Observation::setNrSynthesizedBeams(const unsigned int beams) {
  nrSynthesizedBeams = beams;
}

inline void Observation::setNrDelayBatchesSubbanding(const unsigned int batches) {
  nrDelayBatches_subbanding = batches;
}

inline void Observation::setNrDelayBatches(const unsigned int batches) {
  nrDelayBatches = batches;
}

inline void Observation::setSamplingTime(const float sampling) {
  samplingTime = sampling;
}

inline void Observation::setNrSamplesPerBatch(const unsigned int samples) {
  nrSamplesPerBatch = samples;
}

inline void Observation::setNrSamplesPerBatchSubbanding(const unsigned int samples) {
  nrSamplesPerBatch_subbanding = samples;
}

inline void Observation::setNrSamplesPerSubbandingDispersedChannel(const unsigned int samples) {
  nrSamplesPerDispersedChannel_subbanding = samples;
}

inline void Observation::setNrSamplesPerDispersedChannel(const unsigned int samples) {
  nrSamplesPerDispersedChannel = samples;
}

inline void Observation::setNrZappedChannels(const unsigned int zappedChannels) {
  nrZappedChannels = zappedChannels;
}

inline void Observation::setNrBins(const unsigned int bins) {
  nrBins = bins;
}

} // AstroData

#endif // OBSERVATION_HPP

<commit_msg>Removed old preprocessor stuff.<commit_after>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <limits>

#include <utils.hpp>

#pragma once

namespace AstroData {

class Observation {
public:
  Observation();
  ~Observation();

  // Getters
  // General observation parameters
  unsigned int getNrBatches() const;
  unsigned int getNrStations() const;
  unsigned int getNrPaddedStations(unsigned int padding) const;
  unsigned int getNrBeams() const;
  unsigned int getNrPaddedBeams(unsigned int padding) const;
  unsigned int getNrSynthesizedBeams() const;
  unsigned int getNrPaddedSynthesizedBeams(const unsigned int padding) const;
  float getSamplingTime() const;
  unsigned int getNrSamplesPerBatch() const;
  unsigned int getNrSamplesPerPaddedBatch(unsigned int padding) const;
  // Frequency parameters
  unsigned int getNrSubbands() const;
  unsigned int getNrChannels() const;
  unsigned int getNrChannelsPerSubband() const;
  unsigned int getNrPaddedSubbands(unsigned int padding) const;
  unsigned int getNrPaddedChannels(unsigned int padding) const;
  unsigned int getNrZappedChannels() const;
  float getSubbandMinFreq() const;
  float getSubbandMaxFreq() const;
  float getSubbandBandwidth() const;
  float getMinFreq() const;
  float getMaxFreq() const;
  float getChannelBandwidth() const;
  // Dispersion measures
  unsigned int getNrSamplesPerBatchSubbanding() const;
  unsigned int getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const;
  unsigned int getNrDelayBatchesSubbanding() const;
  unsigned int getNrDelayBatches() const;
  unsigned int getNrDMsSubbanding() const;
  unsigned int getNrDMs() const;
  unsigned int getNrPaddedDMsSubbanding(unsigned int padding) const;
  unsigned int getNrPaddedDMs(unsigned int padding) const;
  unsigned int getNrSamplesPerSubbandingDispersedChannel() const;
  unsigned int getNrSamplesPerDispersedChannel() const;
  unsigned int getNrSamplesPerPaddedSubbandingDispersedChannel(unsigned int padding) const;
  unsigned int getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const;
  float getFirstDMSubbanding() const;
  float getFirstDM() const;
  float getLastDMSubbanding() const;
  float getLastDM() const;
  float getDMStep_subbanding() const;
  float getDMStep() const;
  // Periods
  unsigned int getNrPeriods() const;
  unsigned int getNrPaddedPeriods(unsigned int padding) const;
  unsigned int getFirstPeriod() const;
  unsigned int getLastPeriod() const;
  unsigned int getPeriodStep() const;
  unsigned int getNrBins() const;
  unsigned int getNrPaddedBins(unsigned int padding) const;

  // Setters
  // General observation parameters
  void setNrBatches(const unsigned int batches);
  void setNrStations(const unsigned int stations);
  void setNrBeams(const unsigned int beams);
  void setNrSynthesizedBeams(const unsigned int beams);
  void setSamplingTime(const float sampling);
  void setNrSamplesPerBatch(const unsigned int samples);
  // Frequency parameters
  void setFrequencyRange(const unsigned int subbands, const unsigned int channels, const float baseFrequency, const float bandwidth);
  void setNrZappedChannels(const unsigned int zappedChannels);
  // Dispersion measures
  void setNrSamplesPerBatchSubbanding(const unsigned int samples);
  void setNrDelayBatchesSubbanding(const unsigned int batches);
  void setNrDelayBatches(const unsigned int batches);
  void setNrSamplesPerSubbandingDispersedChannel(const unsigned int samples);
  void setNrSamplesPerDispersedChannel(const unsigned int samples);
  void setDMSubbandingRange(const unsigned int dms, const float baseDM, const float step);
  void setDMRange(const unsigned int dms, const float baseDM, const float step);
  // Periods
  void setPeriodRange(const unsigned int periods, const unsigned int basePeriod, const unsigned int step);
  void setNrBins(const unsigned int bins);

private:
  unsigned int nrBatches;
  unsigned int nrStations;
  unsigned int nrBeams;
  unsigned int nrSynthesizedBeams;
  float samplingTime;
  unsigned int nrSamplesPerBatch;
  unsigned int nrSamplesPerBatch_subbanding;
  unsigned int nrSamplesPerDispersedChannel;
  unsigned int nrSamplesPerDispersedChannel_subbanding;

  unsigned int nrSubbands;
  unsigned int nrChannels;
  unsigned int nrChannelsPerSubband;
  unsigned int nrZappedChannels;
  float minSubbandFreq;
  float maxSubbandFreq;
  float subbandBandwidth;
  float minChannelFreq;
  float maxChannelFreq;
  float channelBandwidth;

  unsigned int nrDelayBatches;
  unsigned int nrDelayBatches_subbanding;
  unsigned int nrDMs;
  unsigned int nrDMs_subbanding;
  float firstDM;
  float firstDM_subbanding;
  float lastDM;
  float lastDM_subbanding;
  float DMStep;
  float DMStep_subbanding;

  unsigned int nrPeriods;
  unsigned int firstPeriod;
  unsigned int lastPeriod;
  unsigned int periodStep;
  unsigned int nrBins;
};

// Implementations
inline unsigned int Observation::getNrBatches() const {
  return nrBatches;
}

inline unsigned int Observation::getNrStations() const {
  return nrStations;
}

inline unsigned int Observation::getNrPaddedStations(unsigned int padding) const {
  return isa::utils::pad(nrStations, padding);
}

inline unsigned int Observation::getNrBeams() const {
  return nrBeams;
}

inline unsigned int Observation::getNrPaddedBeams(unsigned int padding) const {
  return isa::utils::pad(nrBeams, padding);
}

inline unsigned int Observation::getNrSynthesizedBeams() const {
  return nrSynthesizedBeams;
}

inline unsigned int Observation::getNrPaddedSynthesizedBeams(unsigned int padding) const {
  return isa::utils::pad(nrSynthesizedBeams, padding);
}

inline unsigned int Observation::getNrSamplesPerBatch() const {
  return nrSamplesPerBatch;
}

inline float Observation::getSamplingTime() const {
  return samplingTime;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatch(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerBatch, padding);
}

inline unsigned int Observation::getNrSubbands() const {
  return nrSubbands;
}

inline unsigned int Observation::getNrChannelsPerSubband() const {
  return nrChannelsPerSubband;
}

inline unsigned int Observation::getNrChannels() const {
  return nrChannels;
}

inline unsigned int Observation::getNrPaddedSubbands(unsigned int padding) const {
  return isa::utils::pad(nrSubbands, padding);
}

inline unsigned int Observation::getNrPaddedChannels(unsigned int padding) const {
  return isa::utils::pad(nrChannels, padding);
}

inline unsigned int Observation::getNrZappedChannels() const {
  return nrZappedChannels;
}

inline unsigned int Observation::getNrSamplesPerPaddedSubbandingDispersedChannel(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerDispersedChannel_subbanding, padding);
}

inline unsigned int Observation::getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerDispersedChannel, padding);
}

inline float Observation::getSubbandMinFreq() const {
  return minSubbandFreq;
}

inline float Observation::getSubbandMaxFreq() const {
  return maxSubbandFreq;
}

inline float Observation::getSubbandBandwidth() const {
  return subbandBandwidth;
}

inline float Observation::getMinFreq() const {
  return minChannelFreq;
}

inline float Observation::getMaxFreq() const {
  return maxChannelFreq;
}

inline float Observation::getChannelBandwidth() const {
  return channelBandwidth;
}

inline unsigned int Observation::getNrSamplesPerSubbandingDispersedChannel() const {
  return nrSamplesPerDispersedChannel_subbanding;
}

inline unsigned int Observation::getNrSamplesPerDispersedChannel() const {
  return nrSamplesPerDispersedChannel;
}

inline unsigned int Observation::getNrSamplesPerBatchSubbanding() const {
  return nrSamplesPerBatch_subbanding;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerBatch_subbanding, padding);
}

inline unsigned int Observation::getNrDelayBatchesSubbanding() const {
  return nrDelayBatches_subbanding;
}

inline unsigned int Observation::getNrDelayBatches() const {
  return nrDelayBatches;
}

inline unsigned int Observation::getNrDMsSubbanding() const {
  return nrDMsSubbanding;
}

inline unsigned int Observation::getNrDMs() const {
  return nrDMs;
}

inline unsigned int Observation::getNrPaddedDMsSubbanding(unsigned int padding) const {
  return isa::utils::pad(nrDMsSubbanding, padding);
}

inline unsigned int Observation::getNrPaddedDMs(unsigned int padding) const {
  return isa::utils::pad(nrDMs, padding);
}

inline float Observation::getFirstDMSubbanding() const {
  return firstDM_subbanding;
}

inline float Observation::getFirstDM() const {
  return firstDM;
}

inline float Observation::getLastDMSubbanding() const {
  return lastDM_subbanding;
}

inline float Observation::getLastDM() const {
  return lastDM;
}

inline float Observation::getDMStep_subbanding() const {
  return DMStep_subbanding;
}

inline float Observation::getDMStep() const {
  return DMStep;
}

inline unsigned int Observation::getNrPeriods() const {
  return nrPeriods;
}

inline unsigned int Observation::getNrPaddedPeriods(unsigned int padding) const {
  return isa::utils::pad(nrPeriods, padding);
}

inline unsigned int Observation::getNrBins() const {
  return nrBins;
}

inline unsigned int Observation::getNrPaddedBins(unsigned int padding) const {
  return isa::utils::pad(nrBins, padding);
}

inline unsigned int Observation::getFirstPeriod() const {
  return firstPeriod;
}

inline unsigned int Observation::getLastPeriod() const {
  return lastPeriod;
}

inline unsigned int Observation::getPeriodStep() const {
  return periodStep;
}

inline void Observation::setNrBatches(const unsigned int batches) {
  nrBatches = batches;
}

inline void Observation::setNrStations(const unsigned int stations) {
  nrStations = stations;
}

inline void Observation::setNrBeams(const unsigned int beams) {
  nrBeams = beams;
}

inline void Observation::setNrSynthesizedBeams(const unsigned int beams) {
  nrSynthesizedBeams = beams;
}

inline void Observation::setNrDelayBatchesSubbanding(const unsigned int batches) {
  nrDelayBatches_subbanding = batches;
}

inline void Observation::setNrDelayBatches(const unsigned int batches) {
  nrDelayBatches = batches;
}

inline void Observation::setSamplingTime(const float sampling) {
  samplingTime = sampling;
}

inline void Observation::setNrSamplesPerBatch(const unsigned int samples) {
  nrSamplesPerBatch = samples;
}

inline void Observation::setNrSamplesPerBatchSubbanding(const unsigned int samples) {
  nrSamplesPerBatch_subbanding = samples;
}

inline void Observation::setNrSamplesPerSubbandingDispersedChannel(const unsigned int samples) {
  nrSamplesPerDispersedChannel_subbanding = samples;
}

inline void Observation::setNrSamplesPerDispersedChannel(const unsigned int samples) {
  nrSamplesPerDispersedChannel = samples;
}

inline void Observation::setNrZappedChannels(const unsigned int zappedChannels) {
  nrZappedChannels = zappedChannels;
}

inline void Observation::setNrBins(const unsigned int bins) {
  nrBins = bins;
}

} // AstroData

<|endoftext|>


<commit_before>// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <kuniqueapplication.h>
#include <klocale.h>
#include <kglobal.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <knotifyclient.h>
#include <dcopclient.h>
#include <kcrash.h>

#include "kmkernel.h" //control center

#undef Status // stupid X headers
#include "kmailIface_stub.h" // to call control center of master kmail

#include <kaboutdata.h>

#include "kmversion.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of msg."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'addres'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to msg."), 0 },
  { "msg <file>",		I18N_NOOP("Read msg-body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of msg."), 0 },
  { "attach <url>",             I18N_NOOP("Add an attachment to the mail, this can be repeated"), 0 },
  { "check",			I18N_NOOP("Check for new mail only."), 0 },
  { "composer",			I18N_NOOP("Open only composer window."), 0 },
  { "+[address]",		I18N_NOOP("Send msg to 'address'."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

//-----------------------------------------------------------------------------

extern "C" {

static void setSignalHandler(void (*handler)(int));

// Crash recovery signal handler
static void signalHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
static void crashHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

static void setSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(crashHandler);
}

}
//-----------------------------------------------------------------------------

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };

  virtual int newInstance();

  void commitData(QSessionManager& sm) {
    kernel->notClosedByUser();
    KApplication::commitData( sm );
  }
};

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL::List attachURLs;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = QString::fromLocal8Bit(args->getOption("subject"));
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = QString::fromLocal8Bit(args->getOption("cc"));
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = QString::fromLocal8Bit(args->getOption("bcc"));
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile = QString::fromLocal8Bit(args->getOption("msg"));
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = QString::fromLocal8Bit(args->getOption("body"));
  }

  QCStringList attachList = args->getOptionList("attach");
  if (!attachList.isEmpty())
  {
     mailto = true;
     for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it )
       if ( !(*it).isEmpty() )
         attachURLs += KURL( QString::fromLocal8Bit( *it ) );
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (!to.isEmpty())
      to += ", ";
     if (strncasecmp(args->arg(i),"mailto:",7)==0)
       to += args->arg(i);
     else
       to += args->arg(i);
     mailto = true;
  }

  args->clear();

  if (!kernel->firstInstance() || !kapp->isRestored())
    kernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURLs);
  kernel->setFirstInstance(FALSE);
  return 0;
}

namespace
{
QString getMyHostName(void)
{
  char hostNameC[256];
  // null terminate this C string
  hostNameC[255] = 0;
  // set the string to 0 length if gethostname fails
  if(gethostname(hostNameC, 255))
    hostNameC[0] = 0;
  return QString::fromLocal8Bit(hostNameC);
}
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KAboutData about("kmail", I18N_NOOP("KMail"),
                   KMAIL_VERSION,
		   I18N_NOOP("The KDE Email client."),
		   KAboutData::License_GPL,
                   I18N_NOOP("(c) 1997-2002, The KMail developers"),
		   0,
		   "http://kmail.kde.org");
  about.addAuthor( "Michael H\303\244ckel", I18N_NOOP("Current maintainer"), "haeckel@kde.org" );
  about.addAuthor( "Don Sanders", I18N_NOOP("Core developer and former maintainer"), "sanders@kde.org" );
  about.addAuthor( "Stefan Taferner ", I18N_NOOP("Original author"), "taferner@kde.org" );
  about.addAuthor( "Ingo Kl\303\266cker", I18N_NOOP("Encryption"), "ingo.kloecker@epost.de" );
  about.addAuthor( "Marc Mutz", I18N_NOOP("Core developer"), "mutz@kde.org" );
  about.addAuthor( "Daniel Naber", I18N_NOOP("Documentation"), "daniel.naber@t-online.de" );
  about.addAuthor( "Andreas Gungl", I18N_NOOP("Encryption"), "a.gungl@gmx.de" );

  about.addAuthor( "Toyohiro Asukai", 0, "toyohiro@ksmplus.com" );
  about.addAuthor( "Waldo Bastian", 0, "bastian@kde.org" );
  about.addAuthor( "Carsten Burghardt", 0, "carsten.burghardt@web.de" );
  about.addAuthor( "Steven Brown", 0, "swbrown@ucsd.edu" );
  about.addAuthor( "Cristi Dumitrescu", 0, "cristid@chip.ro" );
  about.addAuthor( "Philippe Fremy", 0, "pfremy@chez.com" );
  about.addAuthor( "Kurt Granroth", 0, "granroth@kde.org" );
  about.addAuthor( "Heiko Hund", 0, "heiko@ist.eigentlich.net" );
  about.addAuthor( "Igor Janssen", 0, "rm@linux.ru.net" );
  about.addAuthor( "Matt Johnston", 0, "matt@caifex.org" );
  about.addAuthor( "Christer Kaivo-oja", 0, "whizkid@telia.com" );
  about.addAuthor( "Lars Knoll", 0, "knoll@kde.org" );
  about.addAuthor( "J. Nick Koston", 0, "bdraco@darkorb.net" );
  about.addAuthor( "Stephan Kulow", 0, "coolo@kde.org" );
  about.addAuthor( "Guillaume Laurent", 0, "glaurent@telegraph-road.org" );
  about.addAuthor( "Sam Magnuson", 0, "sam@trolltech.com" );
  about.addAuthor( "Laurent Montel", 0, "lmontel@mandrakesoft.com" );
  about.addAuthor( "Matt Newell", 0, "newellm@proaxis.com" );
  about.addAuthor( "Denis Perchine", 0, "dyp@perchine.com" );
  about.addAuthor( "Samuel Penn", 0, "sam@bifrost.demon.co.uk" );
  about.addAuthor( "Carsten Pfeiffer", 0, "pfeiffer@kde.org" );
  about.addAuthor( "Sven Radej", 0, "radej@kde.org" );
  about.addAuthor( "Mark Roberts", 0, "mark@taurine.demon.co.uk" );
  about.addAuthor( "Wolfgang Rohdewald", 0, "wrohdewald@dplanet.ch" );
  about.addAuthor( "Espen Sand", 0, "espen@kde.org" );
  about.addAuthor( "Jan Simonson", 0, "jan@simonson.pp.se" );
  about.addAuthor( "George Staikos", 0, "staikos@kde.org" );
  about.addAuthor( "Jason Stephenson", 0, "panda@mis.net" );
  about.addAuthor( "Jacek Stolarczyk", 0, "jacek@mer.chemia.polsl.gliwice.pl" );
  about.addAuthor( "Roberto S. Teixeira", 0, "maragato@kde.org" );
  about.addAuthor( "Ronen Tzur", 0, "rtzur@shani.net" );
  about.addAuthor( "Mario Weilguni", 0, "mweilguni@sime.com" );
  about.addAuthor( "Wynn Wilkes", 0, "wynnw@calderasystems.com" );
  about.addAuthor( "Robert D. Williams", 0, "rwilliams@kde.org" );
  about.addAuthor( "Markus Wuebben", 0, "markus.wuebben@kde.org" );
  about.addAuthor( "Thorsten Zachmann", 0, "t.zachmann@zagge.de" );
  about.addAuthor( "Karl-Heinz Zimmer", 0, "khz@kde.org" );

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options

  if (!KMailApplication::start())
     return 0;

  KMailApplication app;
  KGlobal::locale()->insertCatalogue("libkdenetwork");

  // Check and create a lock file to prevent concurrent access to kmail files
  const QString lockLocation = locateLocal("appdata", "lock");
  KSimpleConfig config(lockLocation);
  int oldPid = config.readNumEntry("pid", -1);
  const QString oldHostName = config.readEntry("hostname");
  const QString hostName = getMyHostName();
  // proceed if there is no lock at present
  if (oldPid != -1 &&
  // proceed if the lock is our pid, or if the lock is from the same host
      oldPid != getpid() && hostName != oldHostName &&
  // proceed if the pid doesn't exist
      (kill(oldPid, 0) != -1 || errno != ESRCH))
  {
    QString msg = i18n("Only one instance of KMail can be run at "
      "any one time. It is already running on a different display "
      "with PID %1 on host %2 according to the lock file located "
      "at %3.").arg(oldPid).arg(oldHostName).arg(lockLocation);

    KNotifyClient::userEvent( msg,  KNotifyClient::Messagebox,
      KNotifyClient::Error );
    fprintf(stderr, "*** KMail is already running with PID %d on host %s\n",
            oldPid, oldHostName.local8Bit().data());
    return 1;
  }

  config.writeEntry("pid", getpid());
  config.writeEntry("hostname", hostName);
  config.sync();

  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  setSignalHandler(signalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  // Go!
  int ret = kapp->exec();

  // clean up
  kmailKernel.cleanup();
  config.writeEntry("pid", -1);
  config.sync();
  return ret;
}

<commit_msg>Making KMail use dollar sign expansion ( env variables ) in order to make configuring it trivial in a multi-user environment (e.g. skel kmailrc file with [Account 1] login=$USER ... )<commit_after>// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <kuniqueapplication.h>
#include <klocale.h>
#include <kglobal.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <knotifyclient.h>
#include <dcopclient.h>
#include <kcrash.h>

#include "kmkernel.h" //control center

#undef Status // stupid X headers
#include "kmailIface_stub.h" // to call control center of master kmail

#include <kaboutdata.h>

#include "kmversion.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of msg."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'addres'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to msg."), 0 },
  { "msg <file>",		I18N_NOOP("Read msg-body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of msg."), 0 },
  { "attach <url>",             I18N_NOOP("Add an attachment to the mail, this can be repeated"), 0 },
  { "check",			I18N_NOOP("Check for new mail only."), 0 },
  { "composer",			I18N_NOOP("Open only composer window."), 0 },
  { "+[address]",		I18N_NOOP("Send msg to 'address'."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

//-----------------------------------------------------------------------------

extern "C" {

static void setSignalHandler(void (*handler)(int));

// Crash recovery signal handler
static void signalHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
static void crashHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

static void setSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(crashHandler);
}

}
//-----------------------------------------------------------------------------

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };

  virtual int newInstance();

  void commitData(QSessionManager& sm) {
    kernel->notClosedByUser();
    KApplication::commitData( sm );
  }
};

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL::List attachURLs;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = QString::fromLocal8Bit(args->getOption("subject"));
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = QString::fromLocal8Bit(args->getOption("cc"));
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = QString::fromLocal8Bit(args->getOption("bcc"));
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile = QString::fromLocal8Bit(args->getOption("msg"));
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = QString::fromLocal8Bit(args->getOption("body"));
  }

  QCStringList attachList = args->getOptionList("attach");
  if (!attachList.isEmpty())
  {
     mailto = true;
     for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it )
       if ( !(*it).isEmpty() )
         attachURLs += KURL( QString::fromLocal8Bit( *it ) );
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (!to.isEmpty())
      to += ", ";
     if (strncasecmp(args->arg(i),"mailto:",7)==0)
       to += args->arg(i);
     else
       to += args->arg(i);
     mailto = true;
  }

  args->clear();

  if (!kernel->firstInstance() || !kapp->isRestored())
    kernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURLs);
  kernel->setFirstInstance(FALSE);
  return 0;
}

namespace
{
QString getMyHostName(void)
{
  char hostNameC[256];
  // null terminate this C string
  hostNameC[255] = 0;
  // set the string to 0 length if gethostname fails
  if(gethostname(hostNameC, 255))
    hostNameC[0] = 0;
  return QString::fromLocal8Bit(hostNameC);
}
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KAboutData about("kmail", I18N_NOOP("KMail"),
                   KMAIL_VERSION,
		   I18N_NOOP("The KDE Email client."),
		   KAboutData::License_GPL,
                   I18N_NOOP("(c) 1997-2002, The KMail developers"),
		   0,
		   "http://kmail.kde.org");
  about.addAuthor( "Michael H\303\244ckel", I18N_NOOP("Current maintainer"), "haeckel@kde.org" );
  about.addAuthor( "Don Sanders", I18N_NOOP("Core developer and former maintainer"), "sanders@kde.org" );
  about.addAuthor( "Stefan Taferner ", I18N_NOOP("Original author"), "taferner@kde.org" );
  about.addAuthor( "Ingo Kl\303\266cker", I18N_NOOP("Encryption"), "ingo.kloecker@epost.de" );
  about.addAuthor( "Marc Mutz", I18N_NOOP("Core developer"), "mutz@kde.org" );
  about.addAuthor( "Daniel Naber", I18N_NOOP("Documentation"), "daniel.naber@t-online.de" );
  about.addAuthor( "Andreas Gungl", I18N_NOOP("Encryption"), "a.gungl@gmx.de" );

  about.addAuthor( "Toyohiro Asukai", 0, "toyohiro@ksmplus.com" );
  about.addAuthor( "Waldo Bastian", 0, "bastian@kde.org" );
  about.addAuthor( "Carsten Burghardt", 0, "carsten.burghardt@web.de" );
  about.addAuthor( "Steven Brown", 0, "swbrown@ucsd.edu" );
  about.addAuthor( "Cristi Dumitrescu", 0, "cristid@chip.ro" );
  about.addAuthor( "Philippe Fremy", 0, "pfremy@chez.com" );
  about.addAuthor( "Kurt Granroth", 0, "granroth@kde.org" );
  about.addAuthor( "Heiko Hund", 0, "heiko@ist.eigentlich.net" );
  about.addAuthor( "Igor Janssen", 0, "rm@linux.ru.net" );
  about.addAuthor( "Matt Johnston", 0, "matt@caifex.org" );
  about.addAuthor( "Christer Kaivo-oja", 0, "whizkid@telia.com" );
  about.addAuthor( "Lars Knoll", 0, "knoll@kde.org" );
  about.addAuthor( "J. Nick Koston", 0, "bdraco@darkorb.net" );
  about.addAuthor( "Stephan Kulow", 0, "coolo@kde.org" );
  about.addAuthor( "Guillaume Laurent", 0, "glaurent@telegraph-road.org" );
  about.addAuthor( "Sam Magnuson", 0, "sam@trolltech.com" );
  about.addAuthor( "Laurent Montel", 0, "lmontel@mandrakesoft.com" );
  about.addAuthor( "Matt Newell", 0, "newellm@proaxis.com" );
  about.addAuthor( "Denis Perchine", 0, "dyp@perchine.com" );
  about.addAuthor( "Samuel Penn", 0, "sam@bifrost.demon.co.uk" );
  about.addAuthor( "Carsten Pfeiffer", 0, "pfeiffer@kde.org" );
  about.addAuthor( "Sven Radej", 0, "radej@kde.org" );
  about.addAuthor( "Mark Roberts", 0, "mark@taurine.demon.co.uk" );
  about.addAuthor( "Wolfgang Rohdewald", 0, "wrohdewald@dplanet.ch" );
  about.addAuthor( "Espen Sand", 0, "espen@kde.org" );
  about.addAuthor( "Jan Simonson", 0, "jan@simonson.pp.se" );
  about.addAuthor( "George Staikos", 0, "staikos@kde.org" );
  about.addAuthor( "Jason Stephenson", 0, "panda@mis.net" );
  about.addAuthor( "Jacek Stolarczyk", 0, "jacek@mer.chemia.polsl.gliwice.pl" );
  about.addAuthor( "Roberto S. Teixeira", 0, "maragato@kde.org" );
  about.addAuthor( "Ronen Tzur", 0, "rtzur@shani.net" );
  about.addAuthor( "Mario Weilguni", 0, "mweilguni@sime.com" );
  about.addAuthor( "Wynn Wilkes", 0, "wynnw@calderasystems.com" );
  about.addAuthor( "Robert D. Williams", 0, "rwilliams@kde.org" );
  about.addAuthor( "Markus Wuebben", 0, "markus.wuebben@kde.org" );
  about.addAuthor( "Thorsten Zachmann", 0, "t.zachmann@zagge.de" );
  about.addAuthor( "Karl-Heinz Zimmer", 0, "khz@kde.org" );

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options

  if (!KMailApplication::start())
     return 0;

  KMailApplication app;
  KGlobal::locale()->insertCatalogue("libkdenetwork");

  // Check and create a lock file to prevent concurrent access to kmail files
  const QString lockLocation = locateLocal("appdata", "lock");
  KSimpleConfig config(lockLocation);
  int oldPid = config.readNumEntry("pid", -1);
  const QString oldHostName = config.readEntry("hostname");
  const QString hostName = getMyHostName();
  // proceed if there is no lock at present
  if (oldPid != -1 &&
  // proceed if the lock is our pid, or if the lock is from the same host
      oldPid != getpid() && hostName != oldHostName &&
  // proceed if the pid doesn't exist
      (kill(oldPid, 0) != -1 || errno != ESRCH))
  {
    QString msg = i18n("Only one instance of KMail can be run at "
      "any one time. It is already running on a different display "
      "with PID %1 on host %2 according to the lock file located "
      "at %3.").arg(oldPid).arg(oldHostName).arg(lockLocation);

    KNotifyClient::userEvent( msg,  KNotifyClient::Messagebox,
      KNotifyClient::Error );
    fprintf(stderr, "*** KMail is already running with PID %d on host %s\n",
            oldPid, oldHostName.local8Bit().data());
    return 1;
  }

  config.writeEntry("pid", getpid());
  config.writeEntry("hostname", hostName);
  config.sync();

  kapp->config()->setDollarExpansion( true );
  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  setSignalHandler(signalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  // Go!
  int ret = kapp->exec();

  // clean up
  kmailKernel.cleanup();
  config.writeEntry("pid", -1);
  config.sync();
  return ret;
}

<|endoftext|>


<commit_before>// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#include <config.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef HAVE_PATHS_H
#include <paths.h>
#endif

#include <kuniqueapp.h>
#include <klocale.h>
#include <kglobal.h>
#include <dcopclient.h>
#include <kcrash.h>

#include "kmkernel.h" //control center

#undef Status // stupid X headers
#include "kmailIface_stub.h" // to call control center of master kmail

#include <kaboutdata.h>
#include <kdebug.h>

#include "kmversion.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of msg."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'addres'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to msg."), 0 },
  { "msg <file>",		I18N_NOOP("Read msg-body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of msg."), 0 },
  { "attach <url>",     I18N_NOOP("Add an attachment to the mail"), 0 },
  { "check",			I18N_NOOP("Check for new mail only."), 0 },
  { "composer",			I18N_NOOP("Open only composer window."), 0 },
  { "+[address]",		I18N_NOOP("Send msg to 'address'."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

//-----------------------------------------------------------------------------

extern "C" {

static void setSignalHandler(void (*handler)(int));

// Crash recovery signal handler
static void signalHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
static void crashHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

static void setSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(crashHandler);
}

}
//-----------------------------------------------------------------------------

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };

  virtual int newInstance();
};

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL attachURL = QString::null;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = args->getOption("subject");
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = args->getOption("cc");
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = args->getOption("bcc");
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile = QString::fromLocal8Bit(args->getOption("msg"));
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = args->getOption("body");
  }

  if (args->getOption("attach"))
  {
     mailto = true;
     attachURL = QString::fromLocal8Bit(args->getOption("attach"));
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (!to.isEmpty())
      to += ", ";
     if (strncasecmp(args->arg(i),"mailto:",7)==0)
       to += args->arg(i);
     else
       to += args->arg(i);
     mailto = true;
  }

  args->clear();

  kernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURL) ;
  return 0;
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KAboutData about("kmail", I18N_NOOP("KMail"),
                   KMAIL_VERSION,
		   I18N_NOOP("A KDE E-Mail client."),
		   KAboutData::License_GPL,
                   I18N_NOOP("(c) 1997-2001, The KMail developers"),
		   0,
		   "http://kmail.kde.org");
  about.addAuthor( "Don Sanders", I18N_NOOP("Current maintainer"), "don@sanders.org" );
  about.addAuthor( "Waldo Bastian", QString::null, "bastian@kde.org" );
  about.addAuthor( "Andreas Gungl", QString::null, "a.gungl@gmx.de" );
  about.addAuthor( "Michael Haeckel", QString::null, "michael@haeckel.net" );
  about.addAuthor( "Lars Knoll", QString::null, "knoll@kde.org" );
  about.addAuthor( "J. Nick Koston", QString::null, "bdraco@darkorb.net" );
  about.addAuthor( "Stephan Kulow", QString::null, "coolo@kde.org" );
  about.addAuthor( "Daniel Naber", QString::null, "daniel.naber@t-online.de" );
  about.addAuthor( "Sven Radej", QString::null, "radej@kde.org" );
  about.addAuthor( "Espen Sand", QString::null, "espen@kde.org" );
  about.addAuthor( "George Staikos", QString::null, "staikos@kde.org" );
  about.addAuthor( "Stefan Taferner ", QString::null, "taferner@kde.org" );
  about.addAuthor( "Mario Weilguni", QString::null, "mweilguni@sime.com" );
  about.addAuthor( "Robert D. Williams", QString::null, "rwilliams@kde.org" );
  about.addAuthor( "Markus Wuebben", QString::null, "markus.wuebben@kde.org" );

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options

  if (!KMailApplication::start())
     return 0;

  KMailApplication app;
  KGlobal::locale()->insertCatalogue("libkdenetwork");

  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  setSignalHandler(signalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  // Go!
  int ret = kapp->exec();

  // clean up
  kmailKernel.cleanup();
  return ret;
}

<commit_msg>+  about.addAuthor( "Marc Mutz", QString::null, "mutz@kde.org" );<commit_after>// KMail startup and initialize code
// Author: Stefan Taferner <taferner@alpin.or.at>

#include <config.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef HAVE_PATHS_H
#include <paths.h>
#endif

#include <kuniqueapp.h>
#include <klocale.h>
#include <kglobal.h>
#include <dcopclient.h>
#include <kcrash.h>

#include "kmkernel.h" //control center

#undef Status // stupid X headers
#include "kmailIface_stub.h" // to call control center of master kmail

#include <kaboutdata.h>
#include <kdebug.h>

#include "kmversion.h"

// OLD about text.  This is horrbly outdated.
/*const char* aboutText =
    "KMail [" KMAIL_VERSION "] by\n\n"
    "Stefan Taferner <taferner@kde.org>,\n"
    "Markus Wbben <markus.wuebben@kde.org>\n\n"
    "based on the work of:\n"
    "Lynx <lynx@topaz.hknet.com>,\n"
    "Stephan Meyer <Stephan.Meyer@pobox.com>,\n"
    "and the above authors.\n\n"
    "This program is covered by the GPL.\n\n"
    "Please send bugreports to taferner@kde.org";
*/

static KCmdLineOptions kmoptions[] =
{
  { "s", 0 , 0 },
  { "subject <subject>",	I18N_NOOP("Set subject of msg."), 0 },
  { "c", 0 , 0 },
  { "cc <address>",		I18N_NOOP("Send CC: to 'address'."), 0 },
  { "b", 0 , 0 },
  { "bcc <address>",		I18N_NOOP("Send BCC: to 'addres'."), 0 },
  { "h", 0 , 0 },
  { "header <header>",		I18N_NOOP("Add 'header' to msg."), 0 },
  { "msg <file>",		I18N_NOOP("Read msg-body from 'file'."), 0 },
  { "body <text>",              I18N_NOOP("Set body of msg."), 0 },
  { "attach <url>",     I18N_NOOP("Add an attachment to the mail"), 0 },
  { "check",			I18N_NOOP("Check for new mail only."), 0 },
  { "composer",			I18N_NOOP("Open only composer window."), 0 },
  { "+[address]",		I18N_NOOP("Send msg to 'address'."), 0 },
//  { "+[file]",                  I18N_NOOP("Show message from file 'file'."), 0 },
  { 0, 0, 0}
};

//-----------------------------------------------------------------------------

extern "C" {

static void setSignalHandler(void (*handler)(int));

// Crash recovery signal handler
static void signalHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
static void crashHandler(int sigId)
{
  setSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  kernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

static void setSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(crashHandler);
}

}
//-----------------------------------------------------------------------------

class KMailApplication : public KUniqueApplication
{
public:
  KMailApplication() : KUniqueApplication() { };

  virtual int newInstance();
};

int KMailApplication::newInstance()
{
  QString to, cc, bcc, subj, body;
  KURL messageFile = QString::null;
  KURL attachURL = QString::null;
  bool mailto = false;
  bool checkMail = false;
  //bool viewOnly = false;

  // process args:
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  if (args->getOption("subject"))
  {
     mailto = true;
     subj = args->getOption("subject");
  }

  if (args->getOption("cc"))
  {
     mailto = true;
     cc = args->getOption("cc");
  }

  if (args->getOption("bcc"))
  {
     mailto = true;
     bcc = args->getOption("bcc");
  }

  if (args->getOption("msg"))
  {
     mailto = true;
     messageFile = QString::fromLocal8Bit(args->getOption("msg"));
  }

  if (args->getOption("body"))
  {
     mailto = true;
     body = args->getOption("body");
  }

  if (args->getOption("attach"))
  {
     mailto = true;
     attachURL = QString::fromLocal8Bit(args->getOption("attach"));
  }

  if (args->isSet("composer"))
    mailto = true;

  if (args->isSet("check"))
    checkMail = true;

  for(int i= 0; i < args->count(); i++)
  {
    if (!to.isEmpty())
      to += ", ";
     if (strncasecmp(args->arg(i),"mailto:",7)==0)
       to += args->arg(i);
     else
       to += args->arg(i);
     mailto = true;
  }

  args->clear();

  kernel->action (mailto, checkMail, to, cc, bcc, subj, body, messageFile, attachURL) ;
  return 0;
}

int main(int argc, char *argv[])
{
  // WABA: KMail is a KUniqueApplication. Unfortunately this makes debugging
  // a bit harder: You should pass --nofork as commandline argument when using
  // a debugger. In gdb you can do this by typing "set args --nofork" before
  // typing "run".

  KAboutData about("kmail", I18N_NOOP("KMail"),
                   KMAIL_VERSION,
		   I18N_NOOP("A KDE E-Mail client."),
		   KAboutData::License_GPL,
                   I18N_NOOP("(c) 1997-2001, The KMail developers"),
		   0,
		   "http://kmail.kde.org");
  about.addAuthor( "Don Sanders", I18N_NOOP("Current maintainer"), "don@sanders.org" );
  about.addAuthor( "Waldo Bastian", QString::null, "bastian@kde.org" );
  about.addAuthor( "Andreas Gungl", QString::null, "a.gungl@gmx.de" );
  about.addAuthor( "Michael Haeckel", QString::null, "michael@haeckel.net" );
  about.addAuthor( "Lars Knoll", QString::null, "knoll@kde.org" );
  about.addAuthor( "J. Nick Koston", QString::null, "bdraco@darkorb.net" );
  about.addAuthor( "Stephan Kulow", QString::null, "coolo@kde.org" );
  about.addAuthor( "Marc Mutz", QString::null, "mutz@kde.org" );
  about.addAuthor( "Daniel Naber", QString::null, "daniel.naber@t-online.de" );
  about.addAuthor( "Sven Radej", QString::null, "radej@kde.org" );
  about.addAuthor( "Espen Sand", QString::null, "espen@kde.org" );
  about.addAuthor( "George Staikos", QString::null, "staikos@kde.org" );
  about.addAuthor( "Stefan Taferner ", QString::null, "taferner@kde.org" );
  about.addAuthor( "Mario Weilguni", QString::null, "mweilguni@sime.com" );
  about.addAuthor( "Robert D. Williams", QString::null, "rwilliams@kde.org" );
  about.addAuthor( "Markus Wuebben", QString::null, "markus.wuebben@kde.org" );

  KCmdLineArgs::init(argc, argv, &about);
  KCmdLineArgs::addCmdLineOptions( kmoptions ); // Add kmail options

  if (!KMailApplication::start())
     return 0;

  KMailApplication app;
  KGlobal::locale()->insertCatalogue("libkdenetwork");

  kapp->dcopClient()->suspend(); // Don't handle DCOP requests yet

  //local, do the init
  KMKernel kmailKernel;
  kmailKernel.init();
  kapp->dcopClient()->setDefaultObject( kmailKernel.objId() );

  // and session management
  kmailKernel.doSessionManagement();

  // any dead letters?
  kmailKernel.recoverDeadLetters();

  setSignalHandler(signalHandler);

  kapp->dcopClient()->resume(); // Ok. We are ready for DCOP requests.
  // Go!
  int ret = kapp->exec();

  // clean up
  kmailKernel.cleanup();
  return ret;
}

<|endoftext|>


<commit_before>#include "Chip8.hpp"

Chip8::Chip8()
{

   // Set up the SFML stuff
   window.create(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Chip8 Emulator");
   window.setFramerateLimit(CLOCK_SPEED);
   pixel.setSize(sf::Vector2f(PIXEL_WIDTH, PIXEL_HEIGHT));
   pixel.setFillColor(sf::Color::White);

   // Initialize
   clearScreen();
   opcode = 0;
   for(int i = 0; i < MEMORY_SIZE; i++)
      memory[i] = 0;
   for(int i = 0; i < NUM_REGISTERS; i++)
      V[i] = 0;
   I = 0;
   pc = PROGRAM_START;
   delayTimer = 0;
   soundTimer = 0;
   for(int i = 0; i < STACK_SIZE; i++)
      stack[i] = 0;
   sp = 0;
   for(int i = 0; i < NUM_KEYS; i++)
      key[i] = 0;
   drawFlag = false;

   // Load fontset
   loadFontSet();

}

void Chip8::loadFontSet()
{

   unsigned char chip8_fontset[FONTSET_SIZE] =
   {
      0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
      0x20, 0x60, 0x20, 0x20, 0x70, // 1
      0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
      0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
      0x90, 0x90, 0xF0, 0x10, 0x10, // 4
      0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
      0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
      0xF0, 0x10, 0x20, 0x40, 0x40, // 7
      0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
      0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
      0xF0, 0x90, 0xF0, 0x90, 0x90, // A
      0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
      0xF0, 0x80, 0x80, 0x80, 0xF0, // C
      0xE0, 0x90, 0x90, 0x90, 0xE0, // D
      0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
      0xF0, 0x80, 0xF0, 0x80, 0x80  // F
   };

   for(int i = 0; i < FONTSET_SIZE; i++)
      memory[i] = chip8_fontset[i];

}

void Chip8::drawGraphics()
{

   window.clear();

   for(int i = 0; i < PIXELS_X; i++)
   {
      for(int j = 0; j < PIXELS_Y; j++)
      {
         if(graphics[i + (j * PIXELS_X)])
         {
            pixel.setPosition(sf::Vector2f(i * PIXEL_WIDTH, j * PIXEL_HEIGHT));
            window.draw(pixel);
         }
      }
   }

   window.display();

   drawFlag = false;

}

void Chip8::tick()
{

   // Fetch opcode
   opcode = memory[pc] << 8 | memory[pc + 1];

   // Decode opcode
   switch(opcode & 0xF000)
   {
   case 0x0000:
      {
         switch(opcode & 0x000F)
         {
         case 0x0000:   // 0x00E0: Clear screen
            clearScreen();
            break;
         case 0x000E:   // 0x00EE: Returns from subroutine
            pc = stack[--sp];
            break;
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   case 0x2000:   // 0x2NNN: Call subroutine at NNN
      {
         stack[sp++] = pc;
         pc = opcode & 0x0FFF;
         break;
      }
   case 0x6000:   // 0x6XNN: Sets VX to NN
      {
         V[(opcode & 0x0F00) >> 8] = (opcode & 0x00FF);
         pc += 2;
         break;
      }
   case 0x7000:   // 0x7XNN: Adds NN to VX
      {
         unsigned char add = opcode & 0x00FF;
         V[(opcode & 0x0F00) >> 8] += add;
         pc += 2;
         break;
      }
   case 0x8000:
      {
         switch(opcode & 0x000F)
         {
         case 0x0004:   // 0x8XY4: Add VX to VY and set VF if needed
            {
               if(V[(opcode & 0x00F0) >> 4] > (0xFF - V[(opcode & 0x0F00) >> 8]))   // Value at VY is larger than (max - value at VX)
                  V[0xF] = 1;
               else
                  V[0xF] = 0;
               V[(opcode & 0x0F00) >> 8] += V[(opcode & 0x00F0) >> 4];
               pc += 2;
               break;
            }
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   case 0xA000:   // 0xANNN: Sets I to the address NNN
      {
         I = opcode & 0x0FFF;
         pc += 2;
         break;
      }
   case 0xD000:   // 0xDXYN: Draw sprite at coordinates VX, VY with a width of 8 pixels and height of N.  Sprite starts at I
      {
         unsigned short x = V[(opcode & 0x0F00) >> 8];
         unsigned short y = V[(opcode & 0x00F0) >> 4];
         unsigned short height = opcode & 0x000F;
         unsigned short pix;

         V[0xF] = 0;
         for(int yline = 0; yline <  height; yline++)
         {
            pix = memory[I + yline];
            for(int xline = 0; xline < 8; xline++)
            {
               if((pix & (0x80 >> xline)) != 0)
               {
                  if(graphics[(x + xline + ((y + yline) * PIXELS_X))] == 1)
                     V[0xF] = 1;
                  graphics[x + xline + ((y + yline) * PIXELS_X)] ^= 1;
               }
            }
         }

         drawFlag = true;
         pc += 2;
         break;
      }
   case 0xE000:
      {
         switch(opcode & 0x00FF)
         {
         case 0x009E:   // 0xEX9E skips the next instruction if the key stored in VX is pressed
            {
               if(key[V[(opcode & 0x0F00) >> 8]] != 0)
                  pc += 4;
               else
                  pc += 2;
               break;
            }
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   case 0xF000:
      {
         switch(opcode & 0x00FF)
         {
         case 0x0029:   // 0xFX29: Sets I to the location of the sprite for the character in VX
            {
               unsigned char ch = V[(opcode & 0x0F00) >> 8];
               I = ch * 10;      // 10 bytes per character
               pc += 2;
               break;
            }
         case 0x0033:   // 0xFX33: Stores the binary-coded decimal representation of VX at I, I + 1, and I + 2
            {
               memory[I] = V[(opcode & 0x0F00) >> 8] / 100;
               memory[I + 1] = (V[(opcode & 0x0F00) >> 8] / 10) % 10;
               memory[I + 2] = (V[(opcode & 0x0F00) >> 8] % 100) % 10;
               pc += 2;
               break;
            }
         case 0x0065:   // 0xFX65: Fills V0 to VX with values from memory starting at address I
            {
               unsigned char numRegs = (opcode & 0x0F00) >> 8;
               for(int i = 0; i < numRegs; i++)
                  V[i] = memory[I + (i * 2)];
               pc += 2;
               break;
            }
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   default:
      {
         std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
      }
   }

   // Update timers
   if(delayTimer > 0)
      delayTimer--;

   if(soundTimer > 0)
   {
      std::cout<<"\a";
      soundTimer--;
   }

}

void Chip8::setKeys(sf::Event evt)
{

   switch(evt.key.code)
   {
   case sf::Keyboard::Num1:
      {
         key[1] = 1;
         break;
      }
   case sf::Keyboard::Num2:
      {
         key[2] = 1;
         break;
      }
   case sf::Keyboard::Num3:
      {
         key[3] = 1;
         break;
      }
   case sf::Keyboard::Num4:
      {
         key[0xC] = 1;
         break;
      }
   case sf::Keyboard::Q:
      {
         key[4] = 1;
         break;
      }
   case sf::Keyboard::W:
      {
         key[5] = 1;
         break;
      }
   case sf::Keyboard::E:
      {
         key[6] = 1;
         break;
      }
   case sf::Keyboard::R:
      {
         key[0xD] = 1;
         break;
      }
   case sf::Keyboard::A:
      {
         key[7] = 1;
         break;
      }
   case sf::Keyboard::S:
      {
         key[8] = 1;
         break;
      }
   case sf::Keyboard::D:
      {
         key[9] = 1;
         break;
      }
   case sf::Keyboard::F:
      {
         key[0xE] = 1;
         break;
      }
   case sf::Keyboard::Z:
      {
         key[0xA] = 1;
         break;
      }
   case sf::Keyboard::X:
      {
         key[0] = 1;
         break;
      }
   case sf::Keyboard::C:
      {
         key[0xB] = 1;
         break;
      }
   case sf::Keyboard::V:
      {
         key[0xF] = 1;
         break;
      }
   }

}

void Chip8::clearScreen()
{

   for(int i = 0; i < PIXELS_X * PIXELS_Y; i++)
      graphics[i] = 0;

}

void Chip8::dumpMemory()
{

   for(int i = 0; i < MEMORY_SIZE; i++)
      std::cout<<std::hex<<(int)memory[i];

   std::cout<<"\n";

}

void Chip8::dumpRegisters()
{

   for(int i = 0; i < NUM_REGISTERS; i++)
      std::cout<<std::hex<<(int)V[i];

   std::cout<<"\n";

}

void Chip8::dumpKeys()
{

   for(int i = 0; i < NUM_KEYS; i++)
      std::cout<<(int)key[i];

   std::cout<<"\n";

}

void Chip8::loadProgram(std::string fileName)
{

   std::ifstream input(fileName, std::ifstream::binary);

   if(input)
   {
      // Get the length of the file
      input.seekg(0, input.end);
      int length = input.tellg();
      input.seekg(0, input.beg);

      // Make our buffer
      unsigned char *buffer = new unsigned char[length];

      // Read from the file
      input.read((char*)buffer, length);

      if(!input)
         std::cout<<"Error reading file: only "<<input.gcount()<<" could be read\n";

      // Move the program into memory
      for(int i = 0; i < length; i++)
         memory[i + PROGRAM_START] = buffer[i];

      input.close();
      delete[] buffer;
   }
   else
      std::cout<<"Error reading file: "<<fileName<<"\n";

}

void Chip8::run()
{

   sf::Clock clock;
   clock.restart();

   const sf::Time FRAMETIME = sf::microseconds(1000000.f / CLOCK_SPEED);      // No in-class initialization allowed?

   while(window.isOpen())
   {
      sf::Event event;
      while(window.pollEvent(event))
      {
         // Request for closing the window
         if(event.type == sf::Event::Closed)
            window.close();
         if(event.type == sf::Event::KeyPressed)
            setKeys(event);
      }

      // The clock cycle for the CPU needs to be 60Hz
      sf::Time timeElapsed = clock.restart();
      if(timeElapsed > FRAMETIME)
         sf::sleep(FRAMETIME - timeElapsed);

      // Emulate
      tick();

      // Draw the graphics
      if(drawFlag)
         drawGraphics();
   }

}

Chip8::~Chip8()
{
}
<commit_msg>Fixed a bug with opcode 0x00EE<commit_after>#include "Chip8.hpp"

Chip8::Chip8()
{

   // Set up the SFML stuff
   window.create(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Chip8 Emulator");
   window.setFramerateLimit(CLOCK_SPEED);
   pixel.setSize(sf::Vector2f(PIXEL_WIDTH, PIXEL_HEIGHT));
   pixel.setFillColor(sf::Color::White);

   // Initialize
   clearScreen();
   opcode = 0;
   for(int i = 0; i < MEMORY_SIZE; i++)
      memory[i] = 0;
   for(int i = 0; i < NUM_REGISTERS; i++)
      V[i] = 0;
   I = 0;
   pc = PROGRAM_START;
   delayTimer = 0;
   soundTimer = 0;
   for(int i = 0; i < STACK_SIZE; i++)
      stack[i] = 0;
   sp = 0;
   for(int i = 0; i < NUM_KEYS; i++)
      key[i] = 0;
   drawFlag = false;

   // Load fontset
   loadFontSet();

}

void Chip8::loadFontSet()
{

   unsigned char chip8_fontset[FONTSET_SIZE] =
   {
      0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
      0x20, 0x60, 0x20, 0x20, 0x70, // 1
      0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
      0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
      0x90, 0x90, 0xF0, 0x10, 0x10, // 4
      0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
      0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
      0xF0, 0x10, 0x20, 0x40, 0x40, // 7
      0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
      0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
      0xF0, 0x90, 0xF0, 0x90, 0x90, // A
      0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
      0xF0, 0x80, 0x80, 0x80, 0xF0, // C
      0xE0, 0x90, 0x90, 0x90, 0xE0, // D
      0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
      0xF0, 0x80, 0xF0, 0x80, 0x80  // F
   };

   for(int i = 0; i < FONTSET_SIZE; i++)
      memory[i] = chip8_fontset[i];

}

void Chip8::drawGraphics()
{

   window.clear();

   for(int i = 0; i < PIXELS_X; i++)
   {
      for(int j = 0; j < PIXELS_Y; j++)
      {
         if(graphics[i + (j * PIXELS_X)])
         {
            pixel.setPosition(sf::Vector2f(i * PIXEL_WIDTH, j * PIXEL_HEIGHT));
            window.draw(pixel);
         }
      }
   }

   window.display();

   drawFlag = false;

}

void Chip8::tick()
{

   // Fetch opcode
   opcode = memory[pc] << 8 | memory[pc + 1];

   // Decode opcode
   switch(opcode & 0xF000)
   {
   case 0x0000:
      {
         switch(opcode & 0x000F)
         {
         case 0x0000:   // 0x00E0: Clear screen
            clearScreen();
            break;
         case 0x000E:   // 0x00EE: Returns from subroutine
            pc = stack[--sp] + 2;
            break;
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   case 0x2000:   // 0x2NNN: Call subroutine at NNN
      {
         stack[sp++] = pc;
         pc = opcode & 0x0FFF;
         break;
      }
   case 0x6000:   // 0x6XNN: Sets VX to NN
      {
         V[(opcode & 0x0F00) >> 8] = (opcode & 0x00FF);
         pc += 2;
         break;
      }
   case 0x7000:   // 0x7XNN: Adds NN to VX
      {
         unsigned char add = opcode & 0x00FF;
         V[(opcode & 0x0F00) >> 8] += add;
         pc += 2;
         break;
      }
   case 0x8000:
      {
         switch(opcode & 0x000F)
         {
         case 0x0004:   // 0x8XY4: Add VX to VY and set VF if needed
            {
               if(V[(opcode & 0x00F0) >> 4] > (0xFF - V[(opcode & 0x0F00) >> 8]))   // Value at VY is larger than (max - value at VX)
                  V[0xF] = 1;
               else
                  V[0xF] = 0;
               V[(opcode & 0x0F00) >> 8] += V[(opcode & 0x00F0) >> 4];
               pc += 2;
               break;
            }
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   case 0xA000:   // 0xANNN: Sets I to the address NNN
      {
         I = opcode & 0x0FFF;
         pc += 2;
         break;
      }
   case 0xD000:   // 0xDXYN: Draw sprite at coordinates VX, VY with a width of 8 pixels and height of N.  Sprite starts at I
      {
         unsigned short x = V[(opcode & 0x0F00) >> 8];
         unsigned short y = V[(opcode & 0x00F0) >> 4];
         unsigned short height = opcode & 0x000F;
         unsigned short pix;

         V[0xF] = 0;
         for(int yline = 0; yline <  height; yline++)
         {
            pix = memory[I + yline];
            for(int xline = 0; xline < 8; xline++)
            {
               if((pix & (0x80 >> xline)) != 0)
               {
                  if(graphics[(x + xline + ((y + yline) * PIXELS_X))] == 1)
                     V[0xF] = 1;
                  graphics[x + xline + ((y + yline) * PIXELS_X)] ^= 1;
               }
            }
         }

         drawFlag = true;
         pc += 2;
         break;
      }
   case 0xE000:
      {
         switch(opcode & 0x00FF)
         {
         case 0x009E:   // 0xEX9E skips the next instruction if the key stored in VX is pressed
            {
               if(key[V[(opcode & 0x0F00) >> 8]] != 0)
                  pc += 4;
               else
                  pc += 2;
               break;
            }
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   case 0xF000:
      {
         switch(opcode & 0x00FF)
         {
         case 0x0029:   // 0xFX29: Sets I to the location of the sprite for the character in VX
            {
               unsigned char ch = V[(opcode & 0x0F00) >> 8];
               I = ch * 10;      // 10 bytes per character
               pc += 2;
               break;
            }
         case 0x0033:   // 0xFX33: Stores the binary-coded decimal representation of VX at I, I + 1, and I + 2
            {
               memory[I] = V[(opcode & 0x0F00) >> 8] / 100;
               memory[I + 1] = (V[(opcode & 0x0F00) >> 8] / 10) % 10;
               memory[I + 2] = (V[(opcode & 0x0F00) >> 8] % 100) % 10;
               pc += 2;
               break;
            }
         case 0x0065:   // 0xFX65: Fills V0 to VX with values from memory starting at address I
            {
               unsigned char numRegs = (opcode & 0x0F00) >> 8;
               for(int i = 0; i < numRegs; i++)
                  V[i] = memory[I + (i * 2)];
               pc += 2;
               break;
            }
         default:
            {
               std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
            }
         }
         break;
      }
   default:
      {
         std::cout<<"Unknown opcode: 0x"<<std::hex<<opcode<<"\n";
      }
   }

   // Update timers
   if(delayTimer > 0)
      delayTimer--;

   if(soundTimer > 0)
   {
      std::cout<<"\a";
      soundTimer--;
   }

}

void Chip8::setKeys(sf::Event evt)
{

   switch(evt.key.code)
   {
   case sf::Keyboard::Num1:
      {
         key[1] = 1;
         break;
      }
   case sf::Keyboard::Num2:
      {
         key[2] = 1;
         break;
      }
   case sf::Keyboard::Num3:
      {
         key[3] = 1;
         break;
      }
   case sf::Keyboard::Num4:
      {
         key[0xC] = 1;
         break;
      }
   case sf::Keyboard::Q:
      {
         key[4] = 1;
         break;
      }
   case sf::Keyboard::W:
      {
         key[5] = 1;
         break;
      }
   case sf::Keyboard::E:
      {
         key[6] = 1;
         break;
      }
   case sf::Keyboard::R:
      {
         key[0xD] = 1;
         break;
      }
   case sf::Keyboard::A:
      {
         key[7] = 1;
         break;
      }
   case sf::Keyboard::S:
      {
         key[8] = 1;
         break;
      }
   case sf::Keyboard::D:
      {
         key[9] = 1;
         break;
      }
   case sf::Keyboard::F:
      {
         key[0xE] = 1;
         break;
      }
   case sf::Keyboard::Z:
      {
         key[0xA] = 1;
         break;
      }
   case sf::Keyboard::X:
      {
         key[0] = 1;
         break;
      }
   case sf::Keyboard::C:
      {
         key[0xB] = 1;
         break;
      }
   case sf::Keyboard::V:
      {
         key[0xF] = 1;
         break;
      }
   }

}

void Chip8::clearScreen()
{

   for(int i = 0; i < PIXELS_X * PIXELS_Y; i++)
      graphics[i] = 0;

}

void Chip8::dumpMemory()
{

   for(int i = 0; i < MEMORY_SIZE; i++)
      std::cout<<std::hex<<(int)memory[i];

   std::cout<<"\n";

}

void Chip8::dumpRegisters()
{

   for(int i = 0; i < NUM_REGISTERS; i++)
      std::cout<<std::hex<<(int)V[i];

   std::cout<<"\n";

}

void Chip8::dumpKeys()
{

   for(int i = 0; i < NUM_KEYS; i++)
      std::cout<<(int)key[i];

   std::cout<<"\n";

}

void Chip8::loadProgram(std::string fileName)
{

   std::ifstream input(fileName, std::ifstream::binary);

   if(input)
   {
      // Get the length of the file
      input.seekg(0, input.end);
      int length = input.tellg();
      input.seekg(0, input.beg);

      // Make our buffer
      unsigned char *buffer = new unsigned char[length];

      // Read from the file
      input.read((char*)buffer, length);

      if(!input)
         std::cout<<"Error reading file: only "<<input.gcount()<<" could be read\n";

      // Move the program into memory
      for(int i = 0; i < length; i++)
         memory[i + PROGRAM_START] = buffer[i];

      input.close();
      delete[] buffer;
   }
   else
      std::cout<<"Error reading file: "<<fileName<<"\n";

}

void Chip8::run()
{

   sf::Clock clock;
   clock.restart();

   const sf::Time FRAMETIME = sf::microseconds(1000000.f / CLOCK_SPEED);      // No in-class initialization allowed?

   while(window.isOpen())
   {
      sf::Event event;
      while(window.pollEvent(event))
      {
         // Request for closing the window
         if(event.type == sf::Event::Closed)
            window.close();
         if(event.type == sf::Event::KeyPressed)
            setKeys(event);
      }

      // The clock cycle for the CPU needs to be 60Hz
      sf::Time timeElapsed = clock.restart();
      if(timeElapsed > FRAMETIME)
         sf::sleep(FRAMETIME - timeElapsed);

      // Emulate
      tick();

      // Draw the graphics
      if(drawFlag)
         drawGraphics();
   }

}

Chip8::~Chip8()
{
}
<|endoftext|>