// pageSize.cpp
//
// Part of KVIEWSHELL - A framework for multipage text/gfx viewers
//
// (C) 2002 Stefan Kebekus
// Distributed under the GPL

// Add header files alphabetically

#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#include <math.h>
#include <qstringlist.h>

#include "pageSize.h"

struct pageSizeItem 
{
  const char *name;
  float width;         // in mm
  float height;        // in mm
  const char *preferredUnit;
};

// TODO: make default paper size depend on the current locale
// --e.g. use "US Letter" if metric system is "imperial".

#define defaultMetricPaperSize 4 // Default paper size is "DIN A4"
#define defaultImperialPaperSize 8 // Default paper size is "US Letter"

static pageSizeItem staticList[] = { {"DIN A0",    841.0, 1189.0, "mm"}, 
				     {"DIN A1",    594.0, 841.0, "mm"}, 
				     {"DIN A2",    420.0, 594.0, "mm"}, 
				     {"DIN A3",    297.0, 420.0, "mm"}, 
				     {"DIN A4",    210.0, 297.0, "mm"},
				     {"DIN A5",    148.5, 210.0, "mm"}, 
				     {"DIN B4",    250.0, 353.0, "mm"}, 
				     {"DIN B5",    176.0, 250.0, "mm"},
				     {"US Letter", 215.9, 279.4, "in"}, 
				     {"US Legal",  215.9, 355.6, "in"},
				     {0,  0.0, 0.0, 0} // marks the end of the list.
};


pageSize::pageSize(void)
{
  currentSize = defaultPageSize();
  pageWidth  = staticList[currentSize].width;
  pageHeight = staticList[currentSize].height;
}


void pageSize::setPageSize(QString name)
{
  // See if we can recognize the string
  QString currentName;
  for(int i=0; staticList[i].name != 0; i++) {
    currentName = staticList[i].name;
    if (currentName == name) {
      currentSize = i;  
      // Set page width/height accordingly
      pageWidth  = staticList[currentSize].width;
      pageHeight = staticList[currentSize].height;
      emit(sizeChanged(pageWidth, pageHeight));
      return;
    }
  }

  // Check if the string is of type "<number>x<number>"
  bool wok, hok;
  pageWidth  = name.section('x',0,0).toFloat(&wok);
  pageHeight = name.section('x',1,1).toFloat(&hok);
  if (wok && hok) {
    rectifySizes();
    emit(sizeChanged(pageWidth, pageHeight));
    reconstructCurrentSize();
    return;
  }

  // Last resource. Set the default, in case the string is
  // unintelligible to us.
  currentSize = defaultPageSize();
  pageWidth  = staticList[currentSize].width;
  pageHeight = staticList[currentSize].height;
  emit(sizeChanged(pageWidth, pageHeight));
}


void pageSize::setPageSize(QString width, QString widthUnits, QString height, QString heightUnits)
{
  pageWidth  = width.toFloat();
  pageHeight = height.toFloat();

  if ((widthUnits != "cm") && (widthUnits != "mm") && (widthUnits != "in")) {
    kdDebug() << "Unrecognized page width unit '" << widthUnits << "'. Assuming mm" << endl;
    widthUnits = "mm";
  }
  if (widthUnits == "cm")
    pageWidth *= 10.0;
  if (widthUnits == "in")
    pageWidth *= 25.4;

  if ((heightUnits != "cm") && (heightUnits != "mm") && (heightUnits != "in")) {
    kdDebug() << "Unrecognized page height unit '" << widthUnits << "'. Assuming mm" << endl;
    heightUnits = "mm";
  }
  if (heightUnits == "cm")
    pageHeight *= 10.0;
  if (heightUnits == "in")
    pageHeight *= 25.4;

  rectifySizes();
  emit(sizeChanged(pageWidth, pageHeight));
  reconstructCurrentSize();
}


void pageSize::rectifySizes(void)
{
  // Now do some sanity checks to make sure that values are not
  // outrageous. We allow values between 5cm and 50cm.
  if (pageWidth < 50)
    pageWidth = 50;
  if (pageWidth > 500)
    pageWidth = 500;
  if (pageHeight < 50)
    pageHeight = 50;
  if (pageHeight > 500)
    pageHeight = 500;
  return;
}

QString pageSize::preferredUnit(void)
{
  if (currentSize >= 0)
    return staticList[currentSize].preferredUnit;

  // User-defined size. Give a preferred unit depening on the locale.
  if (KGlobal::locale()-> measureSystem() == KLocale::Metric)
    return "mm";
  else
    return "in";
}


QString pageSize::widthString(QString unit)
{
  QString answer = "--";

  if (unit == "cm")
    answer.setNum(pageWidth/10.0);
  if (unit == "mm")
    answer.setNum(pageWidth);
  if (unit == "in")
    answer.setNum(pageWidth/25.4);

  return answer;
}


QString pageSize::heightString(QString unit)
{
  QString answer = "--";

  if (unit == "cm")
    answer.setNum(pageHeight/10.0);
  if (unit == "mm")
    answer.setNum(pageHeight);
  if (unit == "in")
    answer.setNum(pageHeight/25.4);

  return answer;
}


QStringList pageSize::pageSizeNames(void)
{
  QStringList names;
  
  for(int i=0; staticList[i].name != 0; i++) 
    names << staticList[i].name;

  return names;
}


QString pageSize::formatName(void)
{
  if (currentSize >= 0)
    return staticList[currentSize].name;
  else 
    return QString::null;
}


QString pageSize::serialize(void)
{
  if (currentSize >= 0)
    return staticList[currentSize].name;
  else 
    return QString("%1x%2").arg(pageWidth).arg(pageHeight);
}


void pageSize::reconstructCurrentSize(void)
{
  for(int i=0; staticList[i].name != 0; i++) 
    if ((fabs(staticList[i].width - pageWidth) <= 2) && (fabs(staticList[i].height - pageHeight) <= 2)) {
      currentSize = i;
      pageWidth  = staticList[currentSize].width;
      pageHeight = staticList[currentSize].height;
      return;
    }
  currentSize = -1;
  return;
}

int pageSize::defaultPageSize(void)
{
  if (KGlobal::locale()-> measureSystem() == KLocale::Metric)
    return defaultMetricPaperSize;
  else
    return defaultImperialPaperSize;
}

#include "pageSize.moc"

