Back to index

scribus-ng  1.3.4.dfsg+svn20071115
util.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008                           util.cpp  -  description
00009                              -------------------
00010     begin                : Fri Sep 14 2001
00011     copyright            : (C) 2001 by Franz Schmid
00012     email                : Franz.Schmid@altmuehlnet.de
00013  ***************************************************************************/
00014 
00015 /***************************************************************************
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 #include "util.h"
00025 #include <qbitmap.h>
00026 #include <qfile.h>
00027 #include <qfileinfo.h>
00028 #include <qtextstream.h>
00029 // #include <qdatastream.h>
00030 // #include <qregexp.h>
00031 #include <qdir.h>
00032 #include <qdom.h>
00033 #include <qcheckbox.h>
00034 #include <qwidget.h>
00035 
00036 // #include <algorithm>
00037 // #include <cstdlib>
00038 #include <cmath>
00039 #include <algorithm>
00040 #include "scconfig.h"
00041 
00042 //#ifdef HAVE_UNISTD_H
00043 //#include <unistd.h>
00044 //#endif
00045 
00046 #if defined(_WIN32)
00047 #if defined(_MSC_VER)
00048 #define __STDC__ 1 // hack to get md5_buffer correctly identified
00049 #endif
00050 #include <valarray>
00051 #include <windows.h>
00052 #endif
00053 
00054 #include "md5.h"
00055 
00056 // #include <setjmp.h>
00057 #include "commonstrings.h"
00058 // #include "pagestructs.h"
00059 // #include "prefsfile.h"
00060 // #include "prefscontext.h"
00061 // #include "prefstable.h"
00062 // #include "prefsmanager.h"
00063 // #include "qprocess.h"
00064 #include "scmessagebox.h"
00065 #include "scpixmapcache.h"
00066 #include "scpaths.h"
00067 // #include "text/nlsconfig.h"
00068 
00069 extern "C"
00070 {
00071 #define XMD_H           // shut JPEGlib up
00072 #if defined(Q_OS_UNIXWARE)
00073 #  define HAVE_BOOLEAN  // libjpeg under Unixware seems to need this
00074 #endif
00075 #include <jpeglib.h>
00076 #include <jerror.h>
00077 #undef HAVE_STDLIB_H
00078 #ifdef const
00079 #  undef const          // remove crazy C hackery in jconfig.h
00080 #endif
00081 }
00082 
00083 #include "pageitem.h"
00084 #include "scribus.h"
00085 #include "scribusdoc.h"
00086 #include "scribusview.h"
00087 /*#include <ft2build.h>
00088 #include FT_FREETYPE_H
00089 #include FT_OUTLINE_H
00090 #include FT_GLYPH_H
00091 */
00092 #include <zlib.h>
00093 
00094 
00095 using namespace std;
00096 
00097 void sDebug(QString message)
00098 {
00099        qDebug("%s", message.ascii());
00100 }
00101 
00102 int System(const QStringList & args, const QString fileStdErr, const QString fileStdOut)
00103 {
00104        QStringList stdErrData;
00105        QStringList stdOutData;
00106        QProcess proc(args);
00107        if ( !proc.start() )
00108               return 1;
00109        /* start was OK */
00110        /* wait a little bit */
00111        while( proc.isRunning() || proc.canReadLineStdout() || proc.canReadLineStderr() )
00112        {
00113               // Otherwise Scribus will sleep a *lot* when proc has huge std output
00114               if ( !proc.canReadLineStdout() && !proc.canReadLineStderr()) {
00115 #ifndef _WIN32
00116                      usleep(5000);
00117 #else
00118                      Sleep(5);
00119 #endif
00120               }
00121               // Some configurations needs stdout and stderr to be read
00122               // if needed before the created process can exit
00123               if ( proc.canReadLineStdout() )
00124                      stdOutData.append( proc.readLineStdout() );
00125               if ( proc.canReadLineStderr() )
00126                      stdErrData.append( proc.readLineStderr() );
00127        }
00128        // TODO: What about proc.normalExit() ?
00129        int ex = proc.exitStatus();
00130        QStringList::iterator pIterator;
00131        QStringList::iterator pEnd;
00132        if ( !fileStdErr.isEmpty() )
00133        {
00134               QFile ferr(fileStdErr);
00135               if ( ferr.open(IO_WriteOnly) )
00136               {
00137                      pEnd = stdErrData.end();
00138                      QTextStream errStream(&ferr);
00139                      for ( pIterator = stdErrData.begin(); pIterator != pEnd; pIterator++ )
00140                             errStream << *pIterator << endl;
00141                      ferr.close();
00142               }
00143        }
00144 
00145        if ( !fileStdOut.isEmpty() )
00146        {
00147               QFile fout(fileStdOut);
00148               if ( fout.open(IO_WriteOnly) )
00149               {
00150                      pEnd = stdOutData.end();
00151                      QTextStream outStream(&fout);
00152                      for ( pIterator = stdOutData.begin(); pIterator != pEnd; pIterator++ )
00153                             outStream << *pIterator << endl;
00154                      fout.close();
00155               }
00156        }
00157        return ex;
00158 }
00159 
00160 // On Windows, return short path name, else return longPath;
00161 QString getShortPathName(QString longPath)
00162 {
00163        QString shortPath(longPath);
00164 #if defined _WIN32
00165        QFileInfo fInfo(longPath);
00166        if(fInfo.exists())
00167        {
00168               char shortName[MAX_PATH + 1];
00169               // An error should not be blocking as ERROR_INVALID_PARAMETER can simply mean
00170               // that volume does not support 8.3 filenames, so return longPath in this case
00171               int ret = GetShortPathName(QDir::convertSeparators(longPath).local8Bit(), shortName, sizeof(shortName));
00172               if( ret != ERROR_INVALID_PARAMETER && ret < sizeof(shortName))
00173                      shortPath = shortName;
00174        }
00175 #endif
00176        return shortPath;
00177 }
00178 
00179 int copyFile(QString source, QString target)
00180 {
00181        int bytesread;
00182        if ((source.isNull()) || (target.isNull()))
00183               return -1;
00184        if (source == target)
00185               return -1;
00186        QFile s(source);
00187        if (!s.exists())
00188               return -1;
00189        QFile t(target);
00190        QByteArray bb( 65536 );
00191        if (s.open(IO_ReadOnly))
00192        {
00193               if (t.open(IO_WriteOnly))
00194               {
00195                      bytesread = s.readBlock( bb.data(), bb.size() );
00196                      while( bytesread > 0 )
00197                      {
00198                             t.writeBlock( bb.data(), bytesread );
00199                             bytesread = s.readBlock( bb.data(), bb.size() );
00200                      }
00201                      t.close();
00202               }
00203               s.close();
00204        }
00205        return 0;
00206 }
00207 
00208 int moveFile(QString source, QString target)
00209 {
00210        if ((source.isNull()) || (target.isNull()))
00211               return -1;
00212        if (source == target)
00213               return -1;
00214        copyFile(source, target);
00215        QFile::remove(source);
00216        return 0;
00217 }
00218 
00219 QString GetAttr(QDomElement *el, QString at, QString def)
00220 {
00221        return el->attribute(at, def);
00222 }
00223 
00224 QPixmap loadIcon(QString nam)
00225 {
00226        static ScPixmapCache<QString> pxCache;
00227        if (pxCache.contains(nam))
00228               return *pxCache[nam];
00229 
00230        QString iconFilePath(QString("%1%2").arg(ScPaths::instance().iconDir()).arg(nam));
00231        QPixmap *pm = new QPixmap();
00232        
00233        if (!QFile::exists(iconFilePath))
00234               qWarning("Unable to load icon %s: File not found", iconFilePath.ascii());
00235        else
00236        {
00237               pm->load(iconFilePath);
00238               if (pm->isNull())
00239                      qWarning("Unable to load icon %s: Got null pixmap", iconFilePath.ascii());
00240        }
00241        pxCache.insert(nam, pm);
00242        return *pm;
00243 }
00244 
00245 uint getDouble(QString in, bool raw)
00246 {
00247        QByteArray bb(4);
00248        if (raw)
00249        {
00250               bb[3] = static_cast<uchar>(QChar(in.at(0)));
00251               bb[2] = static_cast<uchar>(QChar(in.at(1)));
00252               bb[1] = static_cast<uchar>(QChar(in.at(2)));
00253               bb[0] = static_cast<uchar>(QChar(in.at(3)));
00254        }
00255        else
00256        {
00257               bb[0] = static_cast<uchar>(QChar(in.at(0)));
00258               bb[1] = static_cast<uchar>(QChar(in.at(1)));
00259               bb[2] = static_cast<uchar>(QChar(in.at(2)));
00260               bb[3] = static_cast<uchar>(QChar(in.at(3)));
00261        }
00262        uint ret;
00263        ret = bb[0] & 0xff;
00264        ret |= (bb[1] << 8) & 0xff00;
00265        ret |= (bb[2] << 16) & 0xff0000;
00266        ret |= (bb[3] << 24) & 0xff000000;
00267        return ret;
00268 }
00269 
00270 // Legacy implementation of LoadText with incorrect
00271 // handling of unicode data. This should be retired.
00272 // Use loadRawText instead.
00273 // FIXME XXX
00274 //
00275 bool loadText(QString filename, QString *Buffer)
00276 {
00277        QFile f(filename);
00278        QFileInfo fi(f);
00279        if (!fi.exists())
00280               return false;
00281        bool ret;
00282        QByteArray bb(f.size());
00283        if (f.open(IO_ReadOnly))
00284        {
00285               f.readBlock(bb.data(), f.size());
00286               f.close();
00287               for (uint posi = 0; posi < bb.size(); ++posi)
00288                      *Buffer += QChar(bb[posi]);
00289               /*
00290               int len = bb.size();
00291               int oldLen = Buffer->length();
00292               Buffer->setLength( oldLen + len + 1);
00293               // digged into Qt 3.3 sources to find that. Might break in Qt 4 -- AV
00294               unsigned short * ucsString = const_cast<unsigned short *>(Buffer->ucs2()) + oldLen;
00295               char * data = bb.data();
00296               for (uint posi = 0; posi < len; ++posi)
00297                      *ucsString++ = *data++;
00298               *ucsString = 0;
00299                */
00300               ret = true;
00301        }
00302        else
00303               ret = false;
00304        return ret;
00305 }
00306 
00307 bool loadRawText(const QString & filename, QCString & buf)
00308 {
00309        bool ret = false;
00310        QFile f(filename);
00311        QFileInfo fi(f);
00312        if (fi.exists())
00313        {
00314               QCString tempBuf(f.size() + 1);
00315               if (f.open(IO_ReadOnly))
00316               {
00317                      unsigned int bytesRead = f.readBlock(tempBuf.data(), f.size());
00318                      tempBuf[bytesRead] = '\0';
00319                      ret = bytesRead == f.size();
00320                      if (ret)
00321                             buf = tempBuf; // sharing makes this efficient
00322               }
00323        }
00324        if (f.isOpen())
00325               f.close();
00326        return ret;
00327 }
00328 
00329 bool loadRawBytes(const QString & filename, QByteArray & buf)
00330 {
00331        bool ret = false;
00332        QFile f(filename);
00333        QFileInfo fi(f);
00334        if (fi.exists())
00335        {
00336               QByteArray tempBuf(f.size());
00337               if (f.open(IO_ReadOnly))
00338               {
00339                      unsigned int bytesRead = f.readBlock(tempBuf.data(), f.size());
00340                      ret = bytesRead == f.size();
00341                      if (ret)
00342                             buf = tempBuf; // sharing makes this efficient
00343               }
00344        }
00345        if (f.isOpen())
00346               f.close();
00347        return ret;
00348 }
00349 
00350 QPointArray RegularPolygon(double w, double h, uint c, bool star, double factor, double rota)
00351 {
00352        uint cx = star ? c * 2 : c;
00353        double seg = 360.0 / cx;
00354        double sc = rota + 180.0;
00355        double di = factor;
00356        int mx = 0;
00357        int my = 0;
00358        //QPointArray pts = QPointArray();
00359        QPointArray pts(cx);
00360        for (uint x = 0; x < cx; ++x)
00361        {
00362               sc = seg * x + 180.0 + rota;
00363               if (star)
00364               {
00365                      double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
00366                      double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
00367                      mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
00368                      my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
00369               }
00370               else
00371               {
00372                      mx = qRound(sin(sc / 180 * M_PI) * (w/2) + (w/2));
00373                      my = qRound(cos(sc / 180 * M_PI) * (h/2) + (h/2));
00374               }
00375               //pts.resize(x+1);
00376               pts.setPoint(x, mx, my);
00377        }
00378        return pts;
00379 }
00380 
00381 FPointArray RegularPolygonF(double w, double h, uint c, bool star, double factor, double rota)
00382 {
00383        uint cx = star ? c * 2 : c;
00384        double seg = 360.0 / cx;
00385        double sc = rota + 180.0;
00386        double di = factor;
00387        double mx = 0;
00388        double my = 0;
00389        //FPointArray pts;
00390        FPointArray pts(cx);
00391        for (uint x = 0; x < cx; ++x)
00392        {
00393               sc = seg * x + 180.0 + rota;
00394               if (star)
00395               {
00396                      double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
00397                      double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
00398                      mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
00399                      my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
00400               }
00401               else
00402               {
00403                      mx = sin(sc / 180 * M_PI) * (w/2) + (w/2);
00404                      my = cos(sc / 180 * M_PI) * (h/2) + (h/2);
00405               }
00406               //pts.resize(x+1);
00407               pts.setPoint(x, mx, my);
00408        }
00409        return pts;
00410 }
00411 
00412 QPointArray FlattenPath(FPointArray ina, QValueList<uint> &Segs)
00413 {
00414        QPointArray Bez(4);
00415        QPointArray outa, cli;
00416        Segs.clear();
00417        if (ina.size() > 3)
00418        {
00419               for (uint poi=0; poi<ina.size()-3; poi += 4)
00420               {
00421                      if (ina.point(poi).x() > 900000 && cli.size() > 0)
00422                      {
00423                             outa.resize(outa.size()+1);
00424                             outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
00425                             Segs.append(outa.size());
00426                             continue;
00427                      }
00428                      BezierPoints(&Bez, ina.pointQ(poi), ina.pointQ(poi+1), ina.pointQ(poi+3), ina.pointQ(poi+2));
00429                      cli = Bez.cubicBezier();
00430                      outa.putPoints(outa.size(), cli.size()-1, cli);
00431               }
00432               outa.resize(outa.size()+1);
00433               outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
00434        }
00435        return outa;
00436 }
00437 
00438 double xy2Deg(double x, double y)
00439 {
00440        return (atan2(y,x)*(180.0/M_PI));
00441 }
00442 
00443 void BezierPoints(QPointArray *ar, QPoint n1, QPoint n2, QPoint n3, QPoint n4)
00444 {
00445        ar->setPoint(0, n1);
00446        ar->setPoint(1, n2);
00447        ar->setPoint(2, n3);
00448        ar->setPoint(3, n4);
00449        return;
00450 }
00451 
00452 void Level2Layer(ScribusDoc *currentDoc, struct Layer *ll, int Level)
00453 {
00454        uint layerCount=currentDoc->layerCount();
00455        for (uint la2 = 0; la2 < layerCount; ++la2)
00456        {
00457               if (currentDoc->Layers[la2].Level == Level)
00458               {
00459                      ll->isViewable = currentDoc->Layers[la2].isViewable;
00460                      ll->isPrintable = currentDoc->Layers[la2].isPrintable;
00461                      ll->LNr = currentDoc->Layers[la2].LNr;
00462                      ll->Name = currentDoc->Layers[la2].Name;
00463                      ll->flowControl = currentDoc->Layers[la2].flowControl;
00464                      ll->transparency = currentDoc->Layers[la2].transparency;
00465                      ll->blendMode = currentDoc->Layers[la2].blendMode;
00466                      break;
00467               }
00468        }
00469 }
00470 
00471 /* CB Replaced by ScribusDoc::layerLevelFromNumber
00472 int Layer2Level(ScribusDoc *currentDoc, int LayerNr)
00473 {
00474        int retVal=currentDoc->layerLevelFromNumber(LayerNr);
00475        int layerCount=currentDoc->layerCount();
00476        for (uint la2 = 0; la2 < layerCount; ++la2)
00477        {
00478               if (currentDoc->Layers[la2].LNr == LayerNr)
00479                      return currentDoc->Layers[la2].Level;
00480        }
00481        return 0;
00482 }
00483 */
00484 QString CompressStr(QString *in)
00485 {
00486        QString out = "";
00487        QByteArray bb(in->length());
00488        for (uint ax = 0; ax < in->length(); ++ax)
00489               bb[ax] = uchar(QChar(in->at(ax)));
00490        uLong exlen = uint(bb.size() * 0.001 + 16) + bb.size();
00491        QByteArray bc(exlen);
00492        int errcode = compress2((Byte *)bc.data(), &exlen, (Byte *)bb.data(), uLong(bb.size()), 9);
00493        if (errcode != Z_OK)
00494        {
00495               qDebug("compress2 failed with code %i", errcode);
00496               out = *in;
00497        }
00498        else {
00499               for (uint cl = 0; cl < exlen; ++cl)
00500                      out += QChar(bc[cl]);
00501        }
00502        return out;
00503 }
00504 
00505 QByteArray CompressArray(QByteArray *in)
00506 {
00507        QByteArray out;
00508        uLong exlen = uint(in->size() * 0.001 + 16) + in->size();
00509        QByteArray temp(exlen);
00510        int errcode = compress2((Byte *)temp.data(), &exlen, (Byte *)in->data(), uLong(in->size()), 9);
00511        if (errcode != Z_OK)
00512        {
00513               qDebug("compress2 failed with code %i", errcode);
00514               out = *in;
00515        }
00516        else {
00517               temp.resize(exlen);
00518               out = temp;
00519        }
00520        return out;
00521 }
00522 
00523 char *toHex( uchar u )
00524 {
00525        static char hexVal[3];
00526        int i = 1;
00527        while ( i >= 0 )
00528        {
00529               ushort hex = (u & 0x000f);
00530               if ( hex < 0x0a )
00531                      hexVal[i] = '0'+hex;
00532               else
00533                      hexVal[i] = 'A'+(hex-0x0a);
00534               u = u >> 4;
00535               i--;
00536        }
00537        hexVal[2] = '\0';
00538        return hexVal;
00539 }
00540 
00541 QString String2Hex(QString *in, bool lang)
00542 {
00543        int i = 0;
00544        QString out = "";
00545        for( uint xi = 0; xi < in->length(); ++xi )
00546        {
00547               out += toHex(uchar(QChar(in->at(xi))));
00548               ++i;
00549               if ((i>40) && (lang))
00550               {
00551                      out += '\n';
00552                      i=0;
00553               }
00554        }
00555        return out;
00556 }
00557 
00558 QByteArray ComputeMD5Sum(QByteArray *in)
00559 {
00560        QByteArray MDsum(16);
00561        md5_buffer (in->data(), in->size(), reinterpret_cast<void*>(MDsum.data()));
00562        return MDsum;
00563 }
00564 
00565 QString Path2Relative(QString Path)
00566 {
00567        QString       Ndir("");
00568        QStringList Pdir;
00569        QFileInfo Bfi = QFileInfo(Path);
00570        QStringList Bdir;
00571        bool end = true;
00572        uint dcoun = 0;
00573        uint dcoun2 = 0;
00574 
00575 #ifndef _WIN32
00576        Pdir = QStringList::split("/", QDir::currentDirPath());
00577        Bdir = QStringList::split("/", Bfi.dirPath(true));
00578 #else
00579        // On win32, file systems are case insensitive
00580        Pdir = QStringList::split("/", QDir::currentDirPath().lower());
00581        Bdir = QStringList::split("/", Bfi.dirPath(true).lower());
00582        // We must check that both path are located on same drive
00583        if( Pdir.size() > 0 && Bdir.size() > 0 )
00584        {
00585               QString drive = Bdir.front();
00586               QString currentDrive = Pdir.front();
00587               if( drive != currentDrive )
00588                      return Path;
00589        }
00590 #endif
00591 
00592        while (end)
00593        {
00594               if (Pdir[dcoun] == Bdir[dcoun])
00595                      dcoun++;
00596               else
00597                      break;
00598               if (dcoun > Pdir.count())
00599                      break;
00600        }
00601        dcoun2 = dcoun;
00602 
00603 #ifdef _WIN32
00604        Bdir = QStringList::split("/", Bfi.dirPath(true));
00605 #endif
00606 
00607        for (uint ddx2 = dcoun; ddx2 < Pdir.count(); ddx2++)
00608               Ndir += "../";
00609        for (uint ddx = dcoun2; ddx < Bdir.count(); ddx++)
00610               Ndir += Bdir[ddx]+"/";
00611        Ndir += Bfi.fileName();
00612        return Ndir;
00613 }
00614 
00615 /***************************************************************************
00616     begin                : Wed Oct 29 2003
00617     copyright            : (C) 2003 The Scribus Team
00618     email                : paul@all-the-johnsons.co.uk
00619  ***************************************************************************/
00620 // check if the file exists, if it does, ask if they're sure
00621 // return true if they're sure, else return false;
00622 
00623 bool overwrite(QWidget *parent, QString filename)
00624 {
00625        bool retval = true;
00626        QFileInfo fi(filename);
00627        if (fi.exists())
00628        {
00629               QString fn = QDir::convertSeparators(filename);
00630               int t = ScMessageBox::warning(parent, QObject::tr("File exists"),
00631                                                                "<qt>"+ QObject::tr("A file named '%1' already exists.<br/>Do you want to replace it with the file you are saving?").arg(fn) +"</qt>",
00632                                                                QObject::tr("&Replace"), CommonStrings::tr_Cancel, "", 1, 1);
00633               if (t == 1)
00634                      retval = false;
00635        }
00636        return retval;
00637 }
00638 
00639 void WordAndPara(PageItem* currItem, int *w, int *p, int *c, int *wN, int *pN, int *cN)
00640 {
00641        QChar Dat = QChar(32);
00642        int para = 0;
00643        int ww = 0;
00644        int cc = 0;
00645        int paraN = 0;
00646        int wwN = 0;
00647        int ccN = 0;
00648        bool first = true;
00649        PageItem *nextItem = currItem;
00650        PageItem *nbl = currItem;
00651        while (nextItem != 0)
00652        {
00653               if (nextItem->prevInChain() != 0)
00654                      nextItem = nextItem->prevInChain();
00655               else
00656                      break;
00657        }
00658        while (nextItem != 0)
00659        {
00660               for (int a = QMAX(nextItem->firstInFrame(),0); a <= nextItem->lastInFrame() && a < nextItem->itemText.length(); ++a)
00661               {
00662                      QChar b = nextItem->itemText.text(a);
00663                      if (b == SpecialChars::PARSEP)
00664                      {
00665                             para++;
00666                      }
00667                      if ((!b.isLetterOrNumber()) && (Dat.isLetterOrNumber()) && (!first))
00668                      {
00669                             ww++;
00670                      }
00671                      cc++;
00672                      Dat = b;
00673                      first = false;
00674               }
00675               nbl = nextItem;
00676               nextItem = nextItem->nextInChain();
00677        }
00678        if (nbl->frameOverflows()) {
00679               paraN++;
00680               for (int a = nbl->lastInFrame()+1; a < nbl->itemText.length(); ++a)
00681               {
00682                      QChar b = nbl->itemText.text(a);
00683                      if (b == SpecialChars::PARSEP)
00684                      {
00685                             paraN++;
00686                      }
00687                      if ((!b.isLetterOrNumber()) && (Dat.isLetterOrNumber()) && (!first))
00688                      {
00689                             wwN++;
00690                      }
00691                      ccN++;
00692                      Dat = b;
00693                      first = false;
00694               }
00695        }             
00696        else {
00697               para++;
00698        }
00699        if (Dat.isLetterOrNumber())
00700        {
00701               if (nbl->frameOverflows())
00702                      wwN++;
00703               else
00704                      ww++;
00705        }
00706        *w = ww;
00707        *p = para;
00708        *c = cc;
00709        *wN = wwN;
00710        *pN = paraN;
00711        *cN = ccN;
00712 }
00713 
00714 void ReOrderText(ScribusDoc *currentDoc, ScribusView *view)
00715 {
00716        double savScale = view->scale();
00717        view->setScale(1.0);
00718        currentDoc->RePos = true;
00719        QPixmap pgPix(10, 10);
00720        QRect rd = QRect(0,0,9,9);
00721        ScPainter *painter = new ScPainter(&pgPix, pgPix.width(), pgPix.height());
00722        for (uint azz=0; azz<currentDoc->MasterItems.count(); ++azz)
00723        {
00724               PageItem *currItem = currentDoc->MasterItems.at(azz);
00725               if (currItem->itemType() == PageItem::PathText)
00726                      currItem->DrawObj(painter, rd);
00727        }
00728        for (uint azz=0; azz<currentDoc->Items->count(); ++azz)
00729        {
00730               PageItem *currItem = currentDoc->Items->at(azz);
00731               if (currItem->itemType() == PageItem::TextFrame)
00732                      currItem->asTextFrame()->layout();
00733               else if (currItem->itemType() == PageItem::PathText)
00734                      currItem->DrawObj(painter, rd);
00735        }
00736        currentDoc->RePos = false;
00737        view->setScale(savScale);
00738        delete painter;
00739 }
00740 
00747 bool compareQStrings(QString s1, QString s2)
00748 {
00749        if (QString::localeAwareCompare(s1, s2) >= 0)
00750               return false;
00751        return true;
00752 }
00753 
00754 QStringList sortQStringList(QStringList aList)
00755 {
00756        std::vector<QString> sortList;
00757        QStringList retList;
00758        QStringList::Iterator it;
00759        for (it = aList.begin(); it != aList.end(); ++it)
00760               sortList.push_back(*it);
00761        std::sort(sortList.begin(), sortList.end(), compareQStrings);
00762        for(uint i = 0; i < sortList.size(); i++)
00763               retList.append(sortList[i]);
00764        return retList;
00765 }
00766 
00767 void GetItemProps(bool newVersion, QDomElement *obj, struct CopyPasteBuffer *OB)
00768 {
00769        QString tmp;
00770        int x, y;
00771        double xf, yf, xf2;
00772        OB->PType = static_cast<PageItem::ItemType>(obj->attribute("PTYPE").toInt());
00773        OB->Width=obj->attribute("WIDTH").toDouble();
00774        OB->Height=obj->attribute("HEIGHT").toDouble();
00775        OB->RadRect = obj->attribute("RADRECT", "0").toDouble();
00776        OB->ClipEdited = obj->attribute("CLIPEDIT", "0").toInt();
00777        OB->FrameType = obj->attribute("FRTYPE", "0").toInt();
00778        OB->Pwidth=obj->attribute("PWIDTH").toDouble();
00779        OB->Pcolor = obj->attribute("PCOLOR");
00780        if ((!newVersion) && (OB->PType == 4))
00781        {
00782               OB->TxtFill = obj->attribute("PCOLOR2");
00783               OB->Pcolor2 = CommonStrings::None;
00784        }
00785        else
00786        {
00787               OB->Pcolor2 = obj->attribute("PCOLOR2");
00788               OB->TxtFill = obj->attribute("TXTFILL", "Black");
00789        }
00790        OB->Shade = obj->attribute("SHADE").toInt();
00791        OB->Shade2 = obj->attribute("SHADE2").toInt();
00792        OB->FillRule = obj->attribute("fillRule", "1").toInt();
00793        OB->TxtStroke=obj->attribute("TXTSTROKE", CommonStrings::None);
00794        OB->ShTxtFill=obj->attribute("TXTFILLSH", "100").toInt();
00795        OB->ShTxtStroke=obj->attribute("TXTSTRSH", "100").toInt();
00796        OB->TxtScale=qRound(obj->attribute("TXTSCALE", "100").toDouble() * 10);
00797        OB->TxtScaleV=qRound(obj->attribute("TXTSCALEV", "100").toDouble() * 10);
00798        OB->TxTBase=qRound(obj->attribute("TXTBASE", "0").toDouble() * 10);
00799        OB->TxTStyle=obj->attribute("TXTSTYLE", "0").toInt();
00800        OB->TxtShadowX=qRound(obj->attribute("TXTSHX", "5").toDouble() * 10);
00801        OB->TxtShadowY=qRound(obj->attribute("TXTSHY", "-5").toDouble() * 10);
00802        OB->TxtOutline=qRound(obj->attribute("TXTOUT", "1").toDouble() * 10);
00803        OB->TxtUnderPos=qRound(obj->attribute("TXTULP", "-0.1").toDouble() * 10);
00804        OB->TxtUnderWidth=qRound(obj->attribute("TXTULW", "-0.1").toDouble() * 10);
00805        OB->TxtStrikePos=qRound(obj->attribute("TXTSTP", "-0.1").toDouble() * 10);
00806        OB->TxtStrikeWidth=qRound(obj->attribute("TXTSTW", "-0.1").toDouble() * 10);
00807        OB->Cols = obj->attribute("COLUMNS", "1").toInt();
00808        OB->ColGap = obj->attribute("COLGAP", "0.0").toDouble();
00809        OB->GrType = obj->attribute("GRTYP", "0").toInt();
00810        OB->fill_gradient.clearStops();
00811        if (OB->GrType != 0)
00812        {
00813               if (OB->GrType == 8)
00814               {
00815                      OB->pattern = obj->attribute("pattern", "");
00816                      OB->patternScaleX = obj->attribute("pScaleX", "100.0").toDouble();
00817                      OB->patternScaleY = obj->attribute("pScaleY", "100.0").toDouble();
00818                      OB->patternOffsetX = obj->attribute("pOffsetX", "0.0").toDouble();
00819                      OB->patternOffsetY = obj->attribute("pOffsetY", "0.0").toDouble();
00820                      OB->patternRotation = obj->attribute("pRotation", "0.0").toDouble();
00821               }
00822               else
00823               {
00824                      OB->GrStartX = obj->attribute("GRSTARTX", "0.0").toDouble();
00825                      OB->GrStartY = obj->attribute("GRSTARTY", "0.0").toDouble();
00826                      OB->GrEndX = obj->attribute("GRENDX", "0.0").toDouble();
00827                      OB->GrEndY = obj->attribute("GRENDY", "0.0").toDouble();
00828                      OB->GrColor = obj->attribute("GRCOLOR","");
00829                      if (OB->GrColor.isEmpty())
00830                             OB->GrColor = "Black";
00831                      OB->GrColor2 = obj->attribute("GRCOLOR2","Black");
00832                      if (OB->GrColor2.isEmpty())
00833                             OB->GrColor2 = "Black";
00834                      OB->GrShade = obj->attribute("GRSHADE", "100").toInt();
00835                      OB->GrShade2 = obj->attribute("GRSHADE2", "100").toInt();
00836               }
00837        }
00838        OB->Rot=obj->attribute("ROT").toDouble();
00839        OB->PLineArt=Qt::PenStyle(obj->attribute("PLINEART").toInt());
00840        OB->PLineEnd=Qt::PenCapStyle(obj->attribute("PLINEEND", "0").toInt());
00841        OB->PLineJoin=Qt::PenJoinStyle(obj->attribute("PLINEJOIN", "0").toInt());
00842        OB->LineSp=obj->attribute("LINESP").toDouble();
00843        OB->LineSpMode = obj->attribute("LINESPMode", "0").toInt();
00844        OB->LocalScX=obj->attribute("LOCALSCX").toDouble();
00845        OB->LocalScY=obj->attribute("LOCALSCY").toDouble();
00846        OB->LocalX=obj->attribute("LOCALX").toDouble();
00847        OB->LocalY=obj->attribute("LOCALY").toDouble();
00848        OB->PicArt=obj->attribute("PICART").toInt();
00849        OB->flippedH = obj->attribute("FLIPPEDH").toInt() % 2;
00850        OB->flippedV = obj->attribute("FLIPPEDV").toInt() % 2;
00851 /*     OB->BBoxX=obj->attribute("BBOXX").toDouble();
00852        OB->BBoxH=obj->attribute("BBOXH").toDouble(); */
00853        OB->ScaleType = obj->attribute("SCALETYPE", "1").toInt();
00854        OB->AspectRatio = obj->attribute("RATIO", "0").toInt();
00855        OB->isPrintable=obj->attribute("PRINTABLE").toInt();
00856        OB->m_isAnnotation=obj->attribute("ANNOTATION", "0").toInt();
00857        OB->m_annotation.setType(obj->attribute("ANTYPE", "0").toInt());
00858        OB->m_annotation.setAction(obj->attribute("ANACTION",""));
00859        OB->m_annotation.setE_act(obj->attribute("ANEACT",""));
00860        OB->m_annotation.setX_act(obj->attribute("ANXACT",""));
00861        OB->m_annotation.setD_act(obj->attribute("ANDACT",""));
00862        OB->m_annotation.setFo_act(obj->attribute("ANFOACT",""));
00863        OB->m_annotation.setBl_act(obj->attribute("ANBLACT",""));
00864        OB->m_annotation.setK_act(obj->attribute("ANKACT",""));
00865        OB->m_annotation.setF_act(obj->attribute("ANFACT",""));
00866        OB->m_annotation.setV_act(obj->attribute("ANVACT",""));
00867        OB->m_annotation.setC_act(obj->attribute("ANCACT",""));
00868        OB->m_annotation.setActionType(obj->attribute("ANACTYP", "0").toInt());
00869        OB->m_annotation.setExtern(obj->attribute("ANEXTERN",""));
00870        if ((!OB->m_annotation.Extern().isEmpty()) && (OB->m_annotation.ActionType() != 8))
00871        {
00872               QFileInfo efp(OB->m_annotation.Extern());
00873               OB->m_annotation.setExtern(efp.absFilePath());
00874        }
00875        OB->m_annotation.setZiel(obj->attribute("ANZIEL", "0").toInt());
00876        OB->AnName=obj->attribute("ANNAME","");
00877        OB->m_annotation.setToolTip(obj->attribute("ANTOOLTIP",""));
00878        OB->m_annotation.setRollOver(obj->attribute("ANROLL",""));
00879        OB->m_annotation.setDown(obj->attribute("ANDOWN",""));
00880        OB->m_annotation.setBwid(obj->attribute("ANBWID", "1").toInt());
00881        OB->m_annotation.setBsty(obj->attribute("ANBSTY", "0").toInt());
00882        OB->m_annotation.setFeed(obj->attribute("ANFEED", "1").toInt());
00883        OB->m_annotation.setFlag(obj->attribute("ANFLAG", "0").toInt());
00884        OB->m_annotation.setFont(obj->attribute("ANFONT", "4").toInt());
00885        OB->m_annotation.setFormat(obj->attribute("ANFORMAT", "0").toInt());
00886        OB->m_annotation.setVis(obj->attribute("ANVIS", "0").toInt());
00887        OB->m_annotation.setIsChk(static_cast<bool>(obj->attribute("ANCHK", "0").toInt()));
00888        OB->m_annotation.setAAact(static_cast<bool>(obj->attribute("ANAA", "0").toInt()));
00889        OB->m_annotation.setHTML(static_cast<bool>(obj->attribute("ANHTML", "0").toInt()));
00890        OB->m_annotation.setUseIcons(static_cast<bool>(obj->attribute("ANICON", "0").toInt()));
00891        OB->m_annotation.setChkStil(obj->attribute("ANCHKS", "0").toInt());
00892        OB->m_annotation.setMaxChar(obj->attribute("ANMC", "-1").toInt());
00893        OB->m_annotation.setBorderColor(obj->attribute("ANBCOL",CommonStrings::None));
00894        OB->m_annotation.setIPlace(obj->attribute("ANPLACE", "1").toInt());
00895        OB->m_annotation.setScaleW(obj->attribute("ANSCALE", "0").toInt());
00896        if (obj->attribute("TRANSPARENT", "0").toInt() == 1)
00897               OB->Pcolor = CommonStrings::None;
00898        OB->textAlignment=obj->attribute("ALIGN", "0").toInt();
00899        if ( obj->hasAttribute("TEXTFLOWMODE") )
00900               OB->TextflowMode = (PageItem::TextFlowMode) obj->attribute("TEXTFLOWMODE", "0").toInt();
00901        else if ( obj->attribute("TEXTFLOW").toInt() )
00902        {
00903               if (obj->attribute("TEXTFLOW2", "0").toInt())
00904                      OB->TextflowMode = PageItem::TextFlowUsesBoundingBox;
00905               else if (obj->attribute("TEXTFLOW3", "0").toInt())
00906                      OB->TextflowMode = PageItem::TextFlowUsesContourLine;
00907               else
00908                      OB->TextflowMode = PageItem::TextFlowUsesFrameShape;    
00909        }
00910        else
00911               OB->TextflowMode = PageItem::TextFlowDisabled;
00912        OB->Extra=obj->attribute("EXTRA").toDouble();
00913        OB->TExtra=obj->attribute("TEXTRA", "1").toDouble();
00914        OB->BExtra=obj->attribute("BEXTRA", "1").toDouble();
00915        OB->RExtra=obj->attribute("REXTRA", "1").toDouble();
00916        OB->PoShow = obj->attribute("PLTSHOW", "0").toInt();
00917        OB->BaseOffs = obj->attribute("BASEOF", "0").toDouble();
00918        OB->textPathType =  obj->attribute("textPathType", "0").toInt();
00919        OB->textPathFlipped = static_cast<bool>(obj->attribute("textPathFlipped", "0").toInt());
00920        OB->ISize = qRound(obj->attribute("ISIZE", "12").toDouble() * 10);
00921        if (obj->hasAttribute("EXTRAV"))
00922               OB->ExtraV = qRound(obj->attribute("EXTRAV", "0").toDouble() / obj->attribute("ISIZE", "12").toDouble() * 1000.0);
00923        else
00924               OB->ExtraV = obj->attribute("TXTKERN").toInt();
00925        OB->Pfile=obj->attribute("PFILE");
00926        OB->Pfile2=obj->attribute("PFILE2","");
00927        OB->Pfile3=obj->attribute("PFILE3","");
00928        OB->IProfile=obj->attribute("PRFILE","");
00929        OB->EmProfile=obj->attribute("EPROF","");
00930        OB->IRender = obj->attribute("IRENDER", "1").toInt();
00931        OB->UseEmbedded = obj->attribute("EMBEDDED", "1").toInt();
00932        OB->Locked = static_cast<bool>(obj->attribute("LOCK", "0").toInt());
00933        OB->LockRes = static_cast<bool>(obj->attribute("LOCKR", "0").toInt());
00934        OB->Reverse = static_cast<bool>(obj->attribute("REVERS", "0").toInt());
00935        OB->isTableItem = static_cast<bool>(obj->attribute("isTableItem", "0").toInt());
00936        OB->TopLine = static_cast<bool>(obj->attribute("TopLine", "0").toInt());
00937        OB->LeftLine = static_cast<bool>(obj->attribute("LeftLine", "0").toInt());
00938        OB->RightLine = static_cast<bool>(obj->attribute("RightLine", "0").toInt());
00939        OB->BottomLine = static_cast<bool>(obj->attribute("BottomLine", "0").toInt());
00940        OB->TopLinkID =  obj->attribute("TopLINK", "-1").toInt();
00941        OB->LeftLinkID =  obj->attribute("LeftLINK", "-1").toInt();
00942        OB->RightLinkID =  obj->attribute("RightLINK", "-1").toInt();
00943        OB->BottomLinkID =  obj->attribute("BottomLINK", "-1").toInt();
00944        OB->Transparency = obj->attribute("TransValue", "0.0").toDouble();
00945        if (obj->hasAttribute("TransValueS"))
00946               OB->TranspStroke = obj->attribute("TransValueS", "0.0").toDouble();
00947        else
00948               OB->TranspStroke = OB->Transparency;
00949        OB->TransBlend = obj->attribute("TransBlend", "0").toInt();
00950        OB->TransBlendS = obj->attribute("TransBlendS", "0").toInt();
00951        tmp = "";
00952        if (obj->hasAttribute("NUMCLIP"))
00953        {
00954               OB->Clip.resize(obj->attribute("NUMCLIP").toUInt());
00955               tmp = obj->attribute("CLIPCOOR");
00956               QTextStream fc(&tmp, IO_ReadOnly);
00957               for (uint c=0; c<obj->attribute("NUMCLIP").toUInt(); ++c)
00958               {
00959                      fc >> x;
00960                      fc >> y;
00961                      OB->Clip.setPoint(c, x, y);
00962               }
00963        }
00964        else
00965               OB->Clip.resize(0);
00966        tmp = "";
00967        if (obj->hasAttribute("NUMPO"))
00968        {
00969               OB->PoLine.resize(obj->attribute("NUMPO").toUInt());
00970               tmp = obj->attribute("POCOOR");
00971               QTextStream fp(&tmp, IO_ReadOnly);
00972               for (uint cx=0; cx<obj->attribute("NUMPO").toUInt(); ++cx)
00973               {
00974                      fp >> xf;
00975                      fp >> yf;
00976                      OB->PoLine.setPoint(cx, xf, yf);
00977               }
00978        }
00979        else
00980               OB->PoLine.resize(0);
00981        tmp = "";
00982        if (obj->hasAttribute("NUMCO"))
00983        {
00984               OB->ContourLine.resize(obj->attribute("NUMCO").toUInt());
00985               tmp = obj->attribute("COCOOR");
00986               QTextStream fp(&tmp, IO_ReadOnly);
00987               for (uint cx=0; cx<obj->attribute("NUMCO").toUInt(); ++cx)
00988               {
00989                      fp >> xf;
00990                      fp >> yf;
00991                      OB->ContourLine.setPoint(cx, xf, yf);
00992               }
00993        }
00994        else
00995               OB->ContourLine.resize(0);
00996        tmp = "";
00997        if ((obj->hasAttribute("NUMTAB")) && (obj->attribute("NUMTAB", "0").toInt() != 0))
00998        {
00999               ParagraphStyle::TabRecord tb;
01000               tmp = obj->attribute("TABS");
01001               QTextStream tgv(&tmp, IO_ReadOnly);
01002               OB->TabValues.clear();
01003               for (int cxv = 0; cxv < obj->attribute("NUMTAB", "0").toInt(); cxv += 2)
01004               {
01005                      tgv >> xf;
01006                      tgv >> xf2;
01007                      tb.tabPosition = xf2;
01008                      tb.tabType = static_cast<int>(xf);
01009                      tb.tabFillChar = QChar();
01010                      OB->TabValues.append(tb);
01011               }
01012               tmp = "";
01013        }
01014        else
01015               OB->TabValues.clear();
01016        if ((obj->hasAttribute("NUMDASH")) && (obj->attribute("NUMDASH", "0").toInt() != 0))
01017        {
01018               tmp = obj->attribute("DASHS");
01019               QTextStream dgv(&tmp, IO_ReadOnly);
01020               OB->DashValues.clear();
01021               for (int cxv = 0; cxv < obj->attribute("NUMDASH", "0").toInt(); ++cxv)
01022               {
01023                      dgv >> xf;
01024                      OB->DashValues.append(xf);
01025               }
01026               tmp = "";
01027        }
01028        else
01029               OB->DashValues.clear();
01030        OB->DashOffset = obj->attribute("DASHOFF", "0.0").toDouble();
01031 }
01032 
01033 FPoint getMaxClipF(FPointArray* Clip)
01034 {
01035        FPoint np, rp;
01036        double mx = 0;
01037        double my = 0;
01038        uint clipSize=Clip->size();
01039        for (uint c = 0; c < clipSize; ++c)
01040        {
01041               np = Clip->point(c);
01042               if (np.x() > 900000)
01043                      continue;
01044               if (np.x() > mx)
01045                      mx = np.x();
01046               if (np.y() > my)
01047                      my = np.y();
01048        }
01049        rp.setXY(mx, my);
01050        return rp;
01051 }
01052 
01053 FPoint getMinClipF(FPointArray* Clip)
01054 {
01055        FPoint np, rp;
01056        double mx = 99999;
01057        double my = 99999;
01058        uint clipSize=Clip->size();
01059        for (uint c = 0; c < clipSize; ++c)
01060        {
01061               np = Clip->point(c);
01062               if (np.x() > 900000)
01063                      continue;
01064               if (np.x() < mx)
01065                      mx = np.x();
01066               if (np.y() < my)
01067                      my = np.y();
01068        }
01069        rp.setXY(mx, my);
01070        return rp;
01071 }
01072 
01073 QString checkFileExtension(const QString &currName, const QString &extension)
01074 {
01075        QString newName(currName);
01076        //If filename ends with a period, just add the extension
01077        if (newName.right(1)==".")
01078        {
01079               newName+=extension.lower();
01080               return newName;
01081        }
01082        //If filename doesnt end with the period+extension, add it on
01083        QString dotExt("." + extension.lower());
01084        if (!newName.endsWith(dotExt,false))
01085               newName+=dotExt;
01086        return newName;
01087 }
01088 
01089 QString getFileNameByPage(ScribusDoc* currDoc, uint pageNo, QString extension)
01090 {
01091        QString number;
01092        number = number.setNum(pageNo + currDoc->FirstPnum);
01093        QString defaultName = currDoc->DocName;
01094        if (defaultName.isNull())
01095               defaultName = "export";
01096        else
01097        {
01098               QFileInfo fi(defaultName);
01099               defaultName = fi.baseName(true);
01100        }
01101        return QString("%1-%2%3.%4").arg(defaultName).arg(QObject::tr("page", "page export")).arg(number).arg(extension);
01102 }
01103 
01104 bool compareDouble(double a, double b)
01105 {
01106        if(a > -21473 && b > -21473 && a < 21474 && b < 21474)
01107        {
01108               long al = static_cast<long>(10000 * a);
01109               long bl = static_cast<long>(10000 * b);
01110               return al == bl;
01111        }
01112        return a == b;
01113 }
01114 
01115 inline double square(double x)
01116 {
01117        return x*x;
01118 }
01119 
01120 inline double distance(double x, double y)
01121 {
01122        return sqrt(x*x+y*y);
01123 }
01124 
01125 double constrainAngle(double angle, double constrain)
01126 {
01127        double newAngle=angle;
01128        double constrainTo=constrain;
01129        if (newAngle<0.0)
01130               newAngle+=360.0;
01131        newAngle=qRound(angle/constrainTo)*constrainTo;
01132        if (newAngle==360.0)
01133               newAngle=0.0;
01134        return newAngle;
01135 }
01136 
01137 double getRotationFromMatrix(QWMatrix& matrix, double def)
01138 {
01139        double value = def;
01140        double norm = sqrt(fabs(matrix.det()));
01141        if (norm > 0.0000001)
01142        {
01143               double m11 = matrix.m11() / norm;
01144               double m12 = matrix.m12() / norm;
01145               double m21 = matrix.m21() / norm;
01146               double m22 = matrix.m22() / norm;
01147               if (fabs(m11) <= 1.0 && fabs(m12) <= 1.0 && fabs(m21) <= 1.0 && fabs(m22) <= 1.0)
01148               {
01149                      QWMatrix mat(m11, m12, m21, m22, 0, 0);
01150                      if (abs(mat.det()-1.0) < 0.00001 && (mat.m12() == -mat.m21()))
01151                      {
01152                             double ac = acos(mat.m11());
01153                             value = (mat.m21() >= 0.0) ? ac : (-ac);
01154                      }
01155               }
01156        }
01157        return value;
01158 }
01159 
01160 const QString getStringFromSequence(DocumentSectionType type, uint position)
01161 {
01162        QString retVal("");
01163        switch( type )
01164        {
01165               case Type_1_2_3:
01166                      retVal=QString::number(position);
01167                      break;
01168               case Type_A_B_C:
01169                      retVal=numberToLetterSequence(position).upper();
01170                      break;
01171               case Type_a_b_c:
01172                      retVal=numberToLetterSequence(position);
01173                      break;
01174               case Type_I_II_III:
01175                      retVal=arabicToRoman(position);
01176                      break;
01177               case Type_i_ii_iii:
01178                      //well, for lower case people will want that, even if its "wrong"
01179                      //ie, X=10, x=10000
01180                      retVal=arabicToRoman(position).lower();
01181                      break;
01182               case Type_None:
01183                      break;
01184               default:
01185                      break;
01186        }
01187        return retVal;
01188 }
01189 
01190 const QString numberToLetterSequence(uint i)
01191 {
01192        QString retVal("");
01193        unsigned digits = 1;
01194        unsigned offset = 0;
01195        uint column=i;
01196        --column;
01197 
01198        if( column > 4058115285U ) return  QString("@");
01199 
01200        for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ )
01201               offset += limit;
01202 
01203        for( unsigned c = column - offset; digits; --digits, c/=26 )
01204               retVal.prepend( QChar( 'a' + (c%26) ) );
01205        return retVal;
01206 }
01207 
01208 const QString arabicToRoman(uint i)
01209 {
01210        QString roman("");
01211        int arabic = i;
01212        while (arabic - 1000000 >= 0){
01213        roman += "m";
01214        arabic -= 1000000;
01215        }
01216        while (arabic - 900000 >= 0){
01217        roman += "cm";
01218        arabic -= 900000;
01219        }
01220        while (arabic - 500000 >= 0){
01221        roman += "d";
01222        arabic -= 500000;
01223        }
01224        while (arabic - 400000 >= 0){
01225        roman += "cd";
01226        arabic -= 400000;
01227        }
01228        while (arabic - 100000 >= 0){
01229        roman += "c";
01230        arabic -= 100000;
01231        }
01232        while (arabic - 90000 >= 0){
01233        roman += "xc";
01234        arabic -= 90000;
01235        }
01236        while (arabic - 50000 >= 0){
01237        roman += "l";
01238        arabic -= 50000;
01239        }
01240        while (arabic - 40000 >= 0){
01241        roman += "xl";
01242        arabic -= 40000;
01243        }
01244        while (arabic - 10000 >= 0){
01245        roman += "x";
01246        arabic -= 10000;
01247        }
01248        while (arabic - 9000 >= 0){
01249        roman += "Mx";
01250        arabic -= 9000;
01251        }
01252        while (arabic - 5000 >= 0){
01253        roman += "v";
01254        arabic -= 5000;
01255        }
01256        while (arabic - 4000 >= 0){
01257        roman += "Mv";
01258        arabic -= 4000;
01259        }
01260        while (arabic - 1000 >= 0){
01261        roman += "M";
01262        arabic -= 1000;
01263        }
01264        while (arabic - 900 >= 0){
01265        roman += "CM";
01266        arabic -= 900;
01267        }
01268        while (arabic - 500 >= 0){
01269        roman += "D";
01270        arabic -= 500;
01271        }
01272        while (arabic - 400 >= 0){
01273        roman += "CD";
01274        arabic -= 400;
01275        }
01276        while (arabic - 100 >= 0){
01277        roman += "C";
01278        arabic -= 100;
01279        }
01280        while (arabic - 90 >= 0){
01281        roman += "XC";
01282        arabic -= 90;
01283        }
01284        while (arabic - 50 >= 0){
01285        roman += "L";
01286        arabic -= 50;
01287        }
01288        while (arabic - 40 >= 0){
01289        roman += "XL";
01290        arabic -= 40;
01291        }
01292        while (arabic - 10 >= 0){
01293        roman += "X";
01294        arabic -= 10;
01295        }
01296        while (arabic - 9 >= 0){
01297        roman += "IX";
01298        arabic -= 9;
01299        }
01300        while (arabic - 5 >= 0){
01301        roman += "V";
01302        arabic -= 5;
01303        }
01304        while (arabic - 4 >= 0){
01305        roman += "IV";
01306        arabic -= 4;
01307        }
01308        while (arabic - 1 >= 0){
01309        roman += "I";
01310        arabic -= 1;
01311        }
01312        return roman;
01313 }
01314 
01315 //CB Moved from scribus.cpp
01316 void parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount)
01317 {
01318        QString tmp(pages);
01319        QString token;
01320        int from, to, pageNr;
01321        do
01322        {
01323               if (tmp.find(",") == -1)
01324               {
01325                      token = tmp;
01326                      tmp = "";
01327               }
01328               else
01329               {
01330                      token = tmp.left(tmp.find(","));
01331                      tmp = tmp.right(tmp.length() - tmp.find(",") - 1);
01332               }
01333 
01334               token = token.stripWhiteSpace();
01335               if (token == "*") // Import all source doc pages
01336               {
01337                      for (int i = 1; i <= sourcePageCount; ++i)
01338                             pageNs->push_back(i);
01339               }
01340               else if (token.find("-") != -1) // import a range of source doc pages
01341               {
01342                      from = QString(token.left(token.find("-"))).toInt();
01343                      to = QString(token.right(token.length() - token.find("-") - 1)).toInt();
01344                      if ((from != 0) && (to != 0))
01345                      {
01346                             if (from > sourcePageCount)
01347                                    from = sourcePageCount;
01348                             if (to > sourcePageCount)
01349                                    to = sourcePageCount;
01350                             if (from == to)
01351                                    pageNs->push_back(to);
01352                             else if (from < to)
01353                             {
01354                                    for (int i = from; i <= to; ++i)
01355                                           pageNs->push_back(i);
01356                             }
01357                             else
01358                             {
01359                                    for (int i = from; i >= to; --i)
01360                                           pageNs->push_back(i);
01361                             }
01362                      }
01363               }
01364               else // import single source doc page
01365               {
01366                      pageNr = token.toInt();
01367                      if ((pageNr > 0) && (pageNr <= sourcePageCount))
01368                             pageNs->push_back(pageNr);
01369               }
01370        } while (!tmp.isEmpty());
01371 }
01372 
01373 
01374 int findParagraphStyle(ScribusDoc* doc, const ParagraphStyle& parStyle)
01375 {
01376        bool named = !parStyle.name().isEmpty();
01377 //qDebug(QString("looking up %1/ %2").arg(parStyle.name()).arg(parStyle.alignment())); 
01378        if (named) {
01379               for (uint i=0; i < doc->paragraphStyles().count(); ++i)
01380               {
01381 //qDebug(QString("%1 %2").arg(i).arg(doc->paragraphStyles()[i].name()));
01382                      if (parStyle.name() == doc->paragraphStyles()[i].name()) {
01383                             return i;
01384                      }
01385               }
01386               assert(false);
01387               return -1;
01388        }
01389        else {
01390               return -1;
01391        }
01392 }
01393 
01394 int findParagraphStyle(ScribusDoc* doc, const QString &name)
01395 {
01396        for (uint i=0; i < doc->paragraphStyles().count(); ++i)
01397        {
01398               if (name == doc->paragraphStyles()[i].name()) {
01399                      return i;
01400               }
01401        }
01402        assert(false);
01403        return -1;
01404 }
01405 
01406 
01407 QPixmap getQCheckBoxPixmap(const bool checked, const QColor background)
01408 {
01409        QCheckBox *tmpItem = new QCheckBox("", 0, "tmpItem");
01410        tmpItem->setMaximumSize(QSize(30, 30));
01411        tmpItem->setMinimumSize(QSize(30, 30));
01412        tmpItem->setPaletteBackgroundColor(background);
01413        tmpItem->setChecked(checked);
01414        QPixmap pm = QPixmap::grabWidget(tmpItem);
01415        pm.setMask(pm.createHeuristicMask());
01416        delete tmpItem;
01417        return pm;
01418 }
01419 
01420 
01421 void tDebug(QString message)
01422 {
01423        QDateTime debugTime;
01424        qDebug("%s", QString("%1\t%2").arg(debugTime.currentDateTime().toString("hh:mm:ss:zzz")).arg(message).ascii());
01425 }
01426 
01427 QString setupImageFormats()
01428 {
01429        QString formats = "";
01430        QString formatD = QObject::tr("All Supported Formats")+" (";
01431        QString form1 = "";
01432        QString form2 = "";
01433        for ( uint i = 0; i < QImageIO::inputFormats().count(); ++i )
01434        {
01435               form1 = QString(QImageIO::inputFormats().at(i)).lower();
01436               form2 = QString(QImageIO::inputFormats().at(i)).upper();
01437               if (form1 == "jpeg")
01438               {
01439                      form1 = "jpg";
01440                      form2 = "JPG";
01441               }
01442               if ((form1 == "png") || (form1 == "xpm") || (form1 == "gif"))
01443               {
01444                      formats += form2 + " (*."+form1+" *."+form2+");;";
01445                      formatD += "*."+form1+" *."+form2+" ";
01446               }
01447               else if (form1 == "jpg")
01448               {
01449                      // JPEG is a special case because both .jpg and .jpeg
01450                      // are acceptable extensions.
01451                      formats += "JPEG (*.jpg *.jpeg *.JPG *.JPEG);;";
01452                      formatD += "*.jpg *.jpeg *.JPG *.JPEG ";
01453               }
01454        }
01455        formats += "TIFF (*.tif *.tiff *.TIF *.TIFF);;";
01456        formatD += "*.tif *.tiff *.TIF *.TIFF";
01457        formats += "PSD (*.psd *.PSD);;";
01458        formatD += " *.psd *.PSD";
01459        formats += "EPS (*.eps *.EPS);;EPSI (*.epsi *.EPSI);;PDF (*.pdf *.PDF);;" + QObject::tr("All Files (*)");
01460        formatD += " *.epsi *.EPSI *.eps *.EPS *.pdf *.PDF";
01461        formatD += ");;"+formats;
01462        return formatD;
01463 }
01464 
01465 QString getImageType(QString filename)
01466 {
01467        QString ret = "";
01468        QFile f(filename);
01469        QFileInfo fi(f);
01470        if (fi.exists())
01471        {
01472               QByteArray buf(20);
01473               if (f.open(IO_ReadOnly))
01474               {
01475                      f.readBlock(buf.data(), 20);
01476                      if ((buf[0] == '%') && (buf[1] == '!') && (buf[2] == 'P') && (buf[3] == 'S') && (buf[4] == '-') && (buf[5] == 'A'))
01477                             ret = "eps";
01478                      else if ((buf[0] == '\xC5') && (buf[1] == '\xD0') && (buf[2] == '\xD3') && (buf[3] == '\xC6'))
01479                             ret = "eps";
01480                      else if ((buf[0] == 'G') && (buf[1] == 'I') && (buf[2] == 'F') && (buf[3] == '8'))
01481                             ret = "gif";
01482                      else if ((buf[0] == '\xFF') && (buf[1] == '\xD8') && (buf[2] == '\xFF'))
01483                             ret = "jpg";
01484                      else if ((buf[0] == '%') && (buf[1] == 'P') && (buf[2] == 'D') && (buf[3] == 'F'))
01485                             ret = "pdf";
01486                      else if ((buf[0] == '\x89') && (buf[1] == 'P') && (buf[2] == 'N') && (buf[3] == 'G'))
01487                             ret = "png";
01488                      else if ((buf[0] == '8') && (buf[1] == 'B') && (buf[2] == 'P') && (buf[3] == 'S'))
01489                             ret = "psd";
01490                      else if (((buf[0] == 'I') && (buf[1] == 'I') && (buf[2] == '\x2A')) || ((buf[0] == 'M') && (buf[1] == 'M') && (buf[3] == '\x2A')))
01491                             ret = "tif";
01492                      else if ((buf[0] == '/') && (buf[1] == '*') && (buf[2] == ' ') && (buf[3] == 'X') && (buf[4] == 'P') && (buf[5] == 'M'))
01493                             ret = "xpm";
01494               }
01495        }
01496        if (f.isOpen())
01497               f.close();
01498        return ret;
01499        
01500 }