root/src/libs/print/libprint/JobData.cpp
/*
 * JobData.cpp
 * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
 */

#include "JobData.h"

#include <Debug.h>
#include <InterfaceDefs.h>
#include <Message.h>

#include <sstream>

#include "PrinterCap.h"
#include "DbgMsg.h"

static const char *kJDXRes                  = "xres";
static const char *kJDYRes                  = "yres";
static const char *kJDCopies                = "copies";
static const char *kJDOrientation           = "orientation";
static const char *kJDScaling               = "scale";
static const char *kJDScaledPaperRect       = "paper_rect";
static const char *kJDScaledPrintableRect   = "printable_rect";
static const char *kJDFirstPage             = "first_page";
static const char *kJDLastPage              = "last_page";

static const char *kJDShowPreview           = "JJJJ_showPreview";
static const char *kJDPaper                 = "JJJJ_paper";
static const char *kJDNup                   = "JJJJ_nup";
static const char *kJDGamma                 = "JJJJ_gamma";
static const char *kJDInkDensity            = "JJJJ_ink_density";
static const char *kJDPaperSource           = "JJJJ_paper_source";
static const char *kJDCollate               = "JJJJ_collate";
static const char *kJDReverse               = "JJJJ_reverse";
static const char *kJDPrintStyle            = "JJJJ_print_style";
static const char *kJDBindingLocation       = "JJJJ_binding_location";
static const char *kJDPageOrder             = "JJJJ_page_order";
static const char *kJDColor                 = "JJJJ_color";
static const char *kJDDitherType            = "JJJJ_dither_type";
static const char *kJDPaperRect             = "JJJJ_paper_rect";
static const char* kJDPrintableRect         = "JJJJ_printable_rect";
static const char* kJDPageSelection         = "JJJJ_page_selection";
static const char* kJDMarginUnit            = "JJJJ_margin_unit";
static const char* kJDPhysicalRect          = "JJJJ_physical_rect";
static const char* kJDScaledPhysicalRect    = "JJJJ_scaled_physical_rect";
static const char* kJDResolution            = "JJJJ_resolution";
static const char* kJDDriverSpecificSettings = "JJJJ_driverSpecificSettings";


DriverSpecificSettings::DriverSpecificSettings()
{
}


DriverSpecificSettings::DriverSpecificSettings(
        const DriverSpecificSettings& settings)
        :
        fSettings(settings.fSettings)
{
}


DriverSpecificSettings &
DriverSpecificSettings::operator=(const DriverSpecificSettings &settings)
{
        fSettings = settings.fSettings;
        return *this;
}


void
DriverSpecificSettings::MakeEmpty()
{
        fSettings.MakeEmpty();
}


bool
DriverSpecificSettings::HasString(const char* key) const
{
        const char* value;
        return fSettings.FindString(key, &value) == B_OK;
}


const char*
DriverSpecificSettings::GetString(const char* key) const
{
        ASSERT(HasString(key));
        const char* value = NULL;
        fSettings.FindString(key, &value);
        return value;
}


void
DriverSpecificSettings::SetString(const char* key, const char* value)
{
        if (HasString(key))
                fSettings.ReplaceString(key, value);
        else
                fSettings.AddString(key, value);
}


bool
DriverSpecificSettings::HasBoolean(const char* key) const
{
        bool value;
        return fSettings.FindBool(key, &value) == B_OK;
}


bool
DriverSpecificSettings::GetBoolean(const char* key) const
{
        ASSERT(HasBoolean(key));
        bool value;
        fSettings.FindBool(key, &value);
        return value;
}


void
DriverSpecificSettings::SetBoolean(const char* key, bool value)
{
        if (HasBoolean(key))
                fSettings.ReplaceBool(key, value);
        else
                fSettings.AddBool(key, value);
}


bool
DriverSpecificSettings::HasInt(const char* key) const
{
        int32 value;
        return fSettings.FindInt32(key, &value) == B_OK;
}


int32
DriverSpecificSettings::GetInt(const char* key) const
{
        ASSERT(HasInt(key));
        int32 value;
        fSettings.FindInt32(key, &value);
        return value;
}


void
DriverSpecificSettings::SetInt(const char* key, int32 value)
{
        if (HasInt(key))
                fSettings.ReplaceInt32(key, value);
        else
                fSettings.AddInt32(key, value);
}


bool
DriverSpecificSettings::HasDouble(const char* key) const
{
        double value;
        return fSettings.FindDouble(key, &value) == B_OK;
}


double
DriverSpecificSettings::GetDouble(const char* key) const
{
        ASSERT(HasDouble(key));
        double value;
        fSettings.FindDouble(key, &value);
        return value;
}


void
DriverSpecificSettings::SetDouble(const char* key, double value)
{
        if (HasDouble(key))
                fSettings.ReplaceDouble(key, value);
        else
                fSettings.AddDouble(key, value);
}


BMessage&
DriverSpecificSettings::Message()
{
        return fSettings;
}


JobData::JobData(BMessage *message, const PrinterCap *printerCap, SettingType settingType)
{
        Load(message, printerCap, settingType);
}


JobData::~JobData()
{
}


JobData::JobData(const JobData &jobData)
{
        *this = jobData;
}


JobData&
JobData::operator=(const JobData &jobData)
{
        fShowPreview           = jobData.fShowPreview;
        fPaper                 = jobData.fPaper;
        fResolutionID          = jobData.fResolutionID;
        fXRes                  = jobData.fXRes;
        fYRes                  = jobData.fYRes;
        fOrientation           = jobData.fOrientation;
        fScaling               = jobData.fScaling;
        fPaperRect             = jobData.fPaperRect;
        fScaledPaperRect       = jobData.fScaledPaperRect;
        fPrintableRect         = jobData.fPrintableRect;
        fScaledPrintableRect   = jobData.fScaledPrintableRect;
        fNup                   = jobData.fNup;
        fFirstPage             = jobData.fFirstPage;
        fLastPage              = jobData.fLastPage;
        fGamma                 = jobData.fGamma;
        fInkDensity            = jobData.fInkDensity;
        fPaperSource           = jobData.fPaperSource;
        fCopies                = jobData.fCopies;
        fCollate               = jobData.fCollate;
        fReverse               = jobData.fReverse;
        fPrintStyle            = jobData.fPrintStyle;
        fBindingLocation       = jobData.fBindingLocation;
        fPageOrder             = jobData.fPageOrder;
        fSettingType           = jobData.fSettingType;
        fMsg                   = jobData.fMsg;
        fColor                 = jobData.fColor;
        fDitherType            = jobData.fDitherType;
        fPageSelection         = jobData.fPageSelection;
        fMarginUnit            = jobData.fMarginUnit;
        fPhysicalRect          = jobData.fPhysicalRect;
        fScaledPhysicalRect    = jobData.fScaledPhysicalRect;
        fDriverSpecificSettings = jobData.fDriverSpecificSettings;
        return *this;
}


void
JobData::Load(BMessage* message, const PrinterCap* printerCap,
        SettingType settingType)
{
        fMsg = message;
        fSettingType = settingType;

        const PaperCap *paperCap = NULL;

        if (message->HasBool(kJDShowPreview))
                fShowPreview = message->FindBool(kJDShowPreview);
        else
                fShowPreview = false;

        if (message->HasInt32(kJDPaper))
                fPaper = (Paper)message->FindInt32(kJDPaper);
        else if (printerCap->Supports(PrinterCap::kPaper)) {
                paperCap = (const PaperCap *)printerCap->GetDefaultCap(
                        PrinterCap::kPaper);
                fPaper = paperCap->fPaper;
        } else
                fPaper = kA4;

        if (message->HasInt32(kJDResolution)) {
                message->FindInt32(kJDResolution, &fResolutionID);
        } else if (printerCap->Supports(PrinterCap::kResolution)) {
                fResolutionID = printerCap->GetDefaultCap(PrinterCap::kResolution)
                        ->ID();
        } else {
                // should not reach here!
                fResolutionID = 0;
        }

        if (message->HasInt64(kJDXRes)) {
                int64 xres64;
                message->FindInt64(kJDXRes, &xres64);
                fXRes = xres64;
        } else if (printerCap->Supports(PrinterCap::kResolution)) {
                fXRes = ((const ResolutionCap *)printerCap->GetDefaultCap(
                        PrinterCap::kResolution))->fXResolution;
        } else {
                fXRes = 300;
        }

        if (message->HasInt64(kJDYRes)) {
                int64 yres64;
                message->FindInt64(kJDYRes, &yres64);
                fYRes = yres64;
        } else if (printerCap->Supports(PrinterCap::kResolution)) {
                fYRes = ((const ResolutionCap *)printerCap->GetDefaultCap(
                        PrinterCap::kResolution))->fYResolution;
        } else {
                fYRes = 300;
        }

        if (message->HasInt32(kJDOrientation))
                fOrientation = (Orientation)message->FindInt32(kJDOrientation);
        else if (printerCap->Supports(PrinterCap::kOrientation))
                fOrientation = ((const OrientationCap *)printerCap->GetDefaultCap(
                        PrinterCap::kOrientation))->fOrientation;
        else
                fOrientation = kPortrait;

        if (message->HasFloat(kJDScaling))
                fScaling = message->FindFloat(kJDScaling);
        else
                fScaling = 100.0f;

        if (message->HasRect(kJDPaperRect)) {
                fPaperRect = message->FindRect(kJDPaperRect);
        } else if (paperCap != NULL) {
                fPaperRect = paperCap->fPaperRect;
        }

        if (message->HasRect(kJDScaledPaperRect)) {
                fScaledPaperRect = message->FindRect(kJDScaledPaperRect);
        } else {
                fScaledPaperRect = fPaperRect;
        }

        if (message->HasRect(kJDPrintableRect)) {
                fPrintableRect = message->FindRect(kJDPrintableRect);
        } else if (paperCap != NULL) {
                fPrintableRect = paperCap->fPhysicalRect;
        }

        if (message->HasRect(kJDScaledPrintableRect)) {
                fScaledPrintableRect = message->FindRect(kJDScaledPrintableRect);
        } else {
                fScaledPrintableRect = fPrintableRect;
        }

        if (message->HasRect(kJDPhysicalRect)) {
                fPhysicalRect = message->FindRect(kJDPhysicalRect);
        } else if (paperCap != NULL) {
                fPhysicalRect = paperCap->fPhysicalRect;
        }

        if (message->HasRect(kJDScaledPhysicalRect)) {
                fScaledPhysicalRect = message->FindRect(kJDScaledPhysicalRect);
        } else {
                fScaledPhysicalRect = fPhysicalRect;
        }

        if (message->HasInt32(kJDFirstPage))
                fFirstPage = message->FindInt32(kJDFirstPage);
        else
                fFirstPage = 1;

        if (message->HasInt32(kJDLastPage))
                fLastPage = message->FindInt32(kJDLastPage);
        else
                fLastPage = -1;

        if (message->HasInt32(kJDNup))
                fNup = message->FindInt32(kJDNup);
        else
                fNup = 1;

        if (message->HasFloat(kJDGamma))
                fGamma = fMsg->FindFloat(kJDGamma);
        else
                fGamma = 0.25f;

        if (message->HasFloat(kJDInkDensity))
                fInkDensity = fMsg->FindFloat(kJDInkDensity);
        else
                fInkDensity = 0.0f;

        if (message->HasInt32(kJDPaperSource))
                fPaperSource = (PaperSource)fMsg->FindInt32(kJDPaperSource);
        else if (printerCap->Supports(PrinterCap::kPaperSource))
                fPaperSource = ((const PaperSourceCap *)printerCap->GetDefaultCap(
                        PrinterCap::kPaperSource))->fPaperSource;
        else
                fPaperSource = kAuto;

        if (message->HasInt32(kJDCopies))
                fCopies = message->FindInt32(kJDCopies);
        else
                fCopies = 1;

        if (message->HasBool(kJDCollate))
                fCollate = message->FindBool(kJDCollate);
        else
                fCollate = false;

        if (message->HasBool(kJDReverse))
                fReverse = message->FindBool(kJDReverse);
        else
                fReverse = false;

        if (message->HasInt32(kJDPrintStyle))
                fPrintStyle = (PrintStyle)message->FindInt32(kJDPrintStyle);
        else if (printerCap->Supports(PrinterCap::kPrintStyle))
                fPrintStyle = ((const PrintStyleCap *)printerCap->GetDefaultCap(
                        PrinterCap::kPrintStyle))->fPrintStyle;
        else
                fPrintStyle = kSimplex;

        if (message->HasInt32(kJDBindingLocation))
                fBindingLocation = (BindingLocation)message->FindInt32(
                        kJDBindingLocation);
        else if (printerCap->Supports(PrinterCap::kBindingLocation))
                fBindingLocation = ((const BindingLocationCap *)printerCap->
                        GetDefaultCap(PrinterCap::kBindingLocation))->fBindingLocation;
        else
                fBindingLocation = kLongEdgeLeft;

        if (message->HasInt32(kJDPageOrder))
                fPageOrder = (PageOrder)message->FindInt32(kJDPageOrder);
        else
                fPageOrder = kAcrossFromLeft;

        if (message->HasInt32(kJDColor))
                fColor = (Color)message->FindInt32(kJDColor);
        else if (printerCap->Supports(PrinterCap::kColor))
                fColor = ((const ColorCap *)printerCap->GetDefaultCap(
                        PrinterCap::kColor))->fColor;
        else
                fColor = kMonochrome;

        if (message->HasInt32(kJDDitherType))
                fDitherType = (Halftone::DitherType)message->FindInt32(kJDDitherType);
        else
                fDitherType = Halftone::kTypeFloydSteinberg;

        if (message->HasInt32(kJDPageSelection))
                fPageSelection = (PageSelection)message->FindInt32(kJDPageSelection);
        else
                fPageSelection = kAllPages;

        if (message->HasInt32(kJDMarginUnit))
                fMarginUnit = (MarginUnit)message->FindInt32(kJDMarginUnit);
        else
                fMarginUnit = kUnitInch;

        if (message->HasMessage(kJDDriverSpecificSettings))
                message->FindMessage(kJDDriverSpecificSettings,
                        &fDriverSpecificSettings.Message());
}


void
JobData::Save(BMessage* message)
{
        if (message == NULL) {
                message = fMsg;
        }

        // page settings
        message->RemoveName(kJDPaper);
        message->AddInt32(kJDPaper, fPaper);

        message->RemoveName(kJDResolution);
        message->AddInt32(kJDResolution, fResolutionID);

        message->RemoveName(kJDXRes);
        message->AddInt64(kJDXRes, fXRes);

        message->RemoveName(kJDYRes);
        message->AddInt64(kJDYRes, fYRes);

        message->RemoveName(kJDOrientation);
        message->AddInt32(kJDOrientation, fOrientation);

        message->RemoveName(kJDScaling);
        message->AddFloat(kJDScaling, fScaling);

        message->RemoveName(kJDPaperRect);
        message->AddRect(kJDPaperRect, fPaperRect);

        message->RemoveName(kJDScaledPaperRect);
        message->AddRect(kJDScaledPaperRect, fScaledPaperRect);

        message->RemoveName(kJDPrintableRect);
        message->AddRect(kJDPrintableRect, fPrintableRect);

        message->RemoveName(kJDScaledPrintableRect);
        message->AddRect(kJDScaledPrintableRect, fScaledPrintableRect);

        message->RemoveName(kJDPhysicalRect);
        message->AddRect(kJDPhysicalRect, fPhysicalRect);

        message->RemoveName(kJDScaledPhysicalRect);
        message->AddRect(kJDScaledPhysicalRect, fScaledPhysicalRect);

        message->RemoveName(kJDMarginUnit);
        message->AddInt32(kJDMarginUnit, fMarginUnit);

        // page settings end here

        // job settings

        // make sure job settings are not present in page settings
        message->RemoveName(kJDShowPreview);
        if (fSettingType == kJobSettings)
                message->AddBool(kJDShowPreview, fShowPreview);

        message->RemoveName(kJDNup);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDNup, fNup);

        message->RemoveName(kJDFirstPage);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDFirstPage, fFirstPage);

        message->RemoveName(kJDLastPage);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDLastPage, fLastPage);

        message->RemoveName(kJDGamma);
        if (fSettingType == kJobSettings)
                message->AddFloat(kJDGamma, fGamma);

        message->RemoveName(kJDInkDensity);
        if (fSettingType == kJobSettings)
                message->AddFloat(kJDInkDensity, fInkDensity);

        message->RemoveName(kJDPaperSource);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDPaperSource, fPaperSource);

        message->RemoveName(kJDCopies);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDCopies, fCopies);

        message->RemoveName(kJDCollate);
        if (fSettingType == kJobSettings)
                message->AddBool(kJDCollate, fCollate);

        message->RemoveName(kJDReverse);
        if (fSettingType == kJobSettings)
                message->AddBool(kJDReverse, fReverse);

        message->RemoveName(kJDPrintStyle);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDPrintStyle, fPrintStyle);

        message->RemoveName(kJDBindingLocation);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDBindingLocation, fBindingLocation);

        message->RemoveName(kJDPageOrder);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDPageOrder, fPageOrder);

        message->RemoveName(kJDColor);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDColor, fColor);

        message->RemoveName(kJDDitherType);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDDitherType, fDitherType);

        message->RemoveName(kJDPageSelection);
        if (fSettingType == kJobSettings)
                message->AddInt32(kJDPageSelection, fPageSelection);

        message->RemoveName(kJDDriverSpecificSettings);
        if (fSettingType == kJobSettings)
        {
                message->AddMessage(kJDDriverSpecificSettings,
                        &fDriverSpecificSettings.Message());
        }
}


DriverSpecificSettings&
JobData::Settings()
{
        return fDriverSpecificSettings;
}


const DriverSpecificSettings&
JobData::Settings() const
{
        return fDriverSpecificSettings;
}