Subversion Repositories Scribus

Rev

Rev 5184 | Rev 5345 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
8 paul 7
/***************************************************************************
8
                          util.cpp  -  description
9
                             -------------------
10
    begin                : Fri Sep 14 2001
11
    copyright            : (C) 2001 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
9 Franz 23
 
2529 craig 24
#include "util.h"
8 paul 25
#include <qbitmap.h>
26
#include <qpainter.h>
27
#include <qfile.h>
28
#include <qfileinfo.h>
29
#include <qtextstream.h>
1541 fschmid 30
#include <qdatastream.h>
2295 cbradney 31
#include <qregexp.h>
19 Franz 32
#include <qdir.h>
2632 craig 33
#include <algorithm>
8 paul 34
#include <cstdlib>
35
#include <cmath>
2702 craig 36
 
37
#include "scconfig.h"
38
 
4506 cbradney 39
//#ifdef HAVE_UNISTD_H
40
//#include <unistd.h>
41
//#endif
2702 craig 42
 
2730 cbradney 43
#if defined(_WIN32)
44
#if defined(_MSC_VER)
45
#define __STDC__ 1 // hack to get md5_buffer correctly identified
46
#endif
3810 cbradney 47
#include <valarray>
2730 cbradney 48
#include <windows.h>
49
#endif
50
 
8 paul 51
#include "md5.h"
2730 cbradney 52
 
201 Franz 53
#include <setjmp.h>
3733 cbradney 54
#include "commonstrings.h"
3757 cbradney 55
#include "pagestructs.h"
2517 craig 56
#include "prefsfile.h"
57
#include "prefscontext.h"
58
#include "prefstable.h"
2834 cbradney 59
#include "prefsmanager.h"
3733 cbradney 60
#include "qprocess.h"
61
#include "scmessagebox.h"
62
#include "scpaths.h"
5184 avox 63
#include "text/nlsconfig.h"
128 Franz 64
 
1555 fschmid 65
extern "C"
66
{
201 Franz 67
#define XMD_H           // shut JPEGlib up
68
#if defined(Q_OS_UNIXWARE)
69
#  define HAVE_BOOLEAN  // libjpeg under Unixware seems to need this
70
#endif
71
#include <jpeglib.h>
72
#include <jerror.h>
73
#undef HAVE_STDLIB_H
74
#ifdef const
75
#  undef const          // remove crazy C hackery in jconfig.h
76
#endif
77
}
78
 
214 Franz 79
#include "scribus.h"
68 Franz 80
#include <ft2build.h>
81
#include FT_FREETYPE_H
82
#include FT_OUTLINE_H
83
#include FT_GLYPH_H
8 paul 84
#ifdef HAVE_LIBZ
85
        #include <zlib.h>
86
#endif
87
#ifdef HAVE_TIFF
88
        #include <tiffio.h>
89
#endif
90
#ifdef HAVE_CMS
44 Franz 91
        #include CMS_INC
1555 fschmid 92
extern cmsHPROFILE CMSoutputProf;
93
extern cmsHPROFILE CMSprinterProf;
1781 fschmid 94
extern cmsHTRANSFORM stdTransG;
95
extern cmsHTRANSFORM stdProofG;
96
extern cmsHTRANSFORM stdTransImgG;
97
extern cmsHTRANSFORM stdProofImgG;
1555 fschmid 98
extern bool BlackPoint;
99
extern bool SoftProofing;
100
extern bool Gamut;
101
extern bool CMSuse;
102
extern int IntentMonitor;
103
extern int IntentPrinter;
8 paul 104
#endif
105
 
3205 craig 106
 
690 cbradney 107
using namespace std;
108
 
3240 fschmid 109
void sDebug(QString message)
110
{
111
        qDebug("%s", message.ascii());
112
}
113
 
690 cbradney 114
QImage ProofImage(QImage *Image)
8 paul 115
{
116
#ifdef HAVE_CMS
690 cbradney 117
        QImage out = Image->copy();
8 paul 118
        if ((CMSuse) && (SoftProofing))
167 Franz 119
        {
3200 cbradney 120
                int outheight=out.height();
121
                for (int i=0; i < outheight; ++i)
8 paul 122
                {
123
                        LPBYTE ptr = out.scanLine(i);
1781 fschmid 124
                        cmsDoTransform(stdProofImgG, ptr, ptr, out.width());
8 paul 125
                }
167 Franz 126
        }
8 paul 127
        else
167 Franz 128
        {
129
                if (CMSuse)
8 paul 130
                {
3200 cbradney 131
                        int outheight=out.height();
132
                        for (int i=0; i < outheight; ++i)
8 paul 133
                        {
134
                                LPBYTE ptr = out.scanLine(i);
1781 fschmid 135
                                cmsDoTransform(stdTransImgG, ptr, ptr, out.width());
8 paul 136
                        }
137
                }
167 Franz 138
        }
8 paul 139
        return out;
140
#else
690 cbradney 141
        return Image->copy();
8 paul 142
#endif
143
}
144
 
4194 fschmid 145
int System(const QStringList & args, const QString fileStdErr, const QString fileStdOut)
204 Franz 146
{
4243 mrdocs 147
        QStringList stdErrData;
148
        QStringList stdOutData;
149
        QProcess proc(args);
4194 fschmid 150
        if ( !proc.start() )
204 Franz 151
                return 1;
152
        /* start was OK */
690 cbradney 153
        /* wait a little bit */
4243 mrdocs 154
        while( proc.isRunning() || proc.canReadLineStdout() || proc.canReadLineStderr() )
4194 fschmid 155
        {
4924 cbradney 156
                // Otherwise Scribus will sleep a *lot* when proc has huge std output
157
                if ( !proc.canReadLineStdout() && !proc.canReadLineStderr()) {
2730 cbradney 158
#ifndef _WIN32
5184 avox 159
                        usleep(5000);
2730 cbradney 160
#else
5184 avox 161
                        Sleep(5);
2730 cbradney 162
#endif
4924 cbradney 163
                }
4243 mrdocs 164
                // Some configurations needs stdout and stderr to be read
165
                // if needed before the created process can exit
166
                if ( proc.canReadLineStdout() )
167
                        stdOutData.append( proc.readLineStdout() );
168
                if ( proc.canReadLineStderr() )
169
                        stdErrData.append( proc.readLineStderr() );
4194 fschmid 170
        }
171
        // TODO: What about proc.normalExit() ?
172
        int ex = proc.exitStatus();
4505 cbradney 173
        QStringList::iterator pIterator;
174
        QStringList::iterator pEnd;
4194 fschmid 175
        if ( !fileStdErr.isEmpty() )
176
        {
177
                QFile ferr(fileStdErr);
178
                if ( ferr.open(IO_WriteOnly) )
179
                {
4243 mrdocs 180
                        pEnd = stdErrData.end();
181
                        QTextStream errStream(&ferr);
182
                        for ( pIterator = stdErrData.begin(); pIterator != pEnd; pIterator++ )
183
                                errStream << *pIterator << endl;
4194 fschmid 184
                        ferr.close();
185
                }
186
        }
187
 
188
        if ( !fileStdOut.isEmpty() )
189
        {
190
                QFile fout(fileStdOut);
191
                if ( fout.open(IO_WriteOnly) )
192
                {
4243 mrdocs 193
                        pEnd = stdOutData.end();
194
                        QTextStream outStream(&fout);
195
                        for ( pIterator = stdOutData.begin(); pIterator != pEnd; pIterator++ )
196
                                outStream << *pIterator << endl;
4194 fschmid 197
                        fout.close();
198
                }
199
        }
204 Franz 200
        return ex;
201
}
202
 
2885 fschmid 203
// On Windows, return short path name, else return longPath;
204
QString getShortPathName(QString longPath)
205
{
4505 cbradney 206
        QString shortPath(longPath);
2885 fschmid 207
#if defined _WIN32
208
        QFileInfo fInfo(longPath);
209
        if(fInfo.exists())
210
        {
211
                char shortName[MAX_PATH + 1];
212
                // An error should not be blocking as ERROR_INVALID_PARAMETER can simply mean
213
                // that volume does not support 8.3 filenames, so return longPath in this case
214
                int ret = GetShortPathName(QDir::convertSeparators(longPath).local8Bit(), shortName, sizeof(shortName));
215
                if( ret != ERROR_INVALID_PARAMETER && ret < sizeof(shortName))
216
                        shortPath = shortName;
217
        }
218
#endif
219
        return shortPath;
220
}
221
 
204 Franz 222
int copyFile(QString source, QString target)
223
{
4193 craig 224
        int bytesread;
204 Franz 225
        if ((source.isNull()) || (target.isNull()))
226
                return -1;
227
        if (source == target)
228
                return -1;
229
        QFile s(source);
230
        QFile t(target);
231
        if (!s.exists())
232
                return -1;
4193 craig 233
        QByteArray bb( 65536 );
204 Franz 234
        if (s.open(IO_ReadOnly))
235
        {
236
                if (t.open(IO_WriteOnly))
237
                {
4193 craig 238
                        bytesread = s.readBlock( bb.data(), bb.size() );
239
                        while( bytesread > 0 )
240
                        {
241
                                t.writeBlock( bb.data(), bytesread );
242
                                bytesread = s.readBlock( bb.data(), bb.size() );
243
                        }
204 Franz 244
                        t.close();
245
                }
4193 craig 246
                s.close();
204 Franz 247
        }
248
        return 0;
249
}
250
 
251
int moveFile(QString source, QString target)
252
{
253
        if ((source.isNull()) || (target.isNull()))
254
                return -1;
255
        if (source == target)
256
                return -1;
257
        copyFile(source, target);
2921 fschmid 258
        QFile::remove(source);
204 Franz 259
        return 0;
260
}
261
 
8 paul 262
QString GetAttr(QDomElement *el, QString at, QString def)
263
{
264
        return el->attribute(at, def);
265
}
266
 
267
QPixmap loadIcon(QString nam)
268
{
1693 craig 269
        QString iconFilePath = QString("%1/%2").arg(ScPaths::instance().iconDir()).arg(nam);
8 paul 270
        QPixmap pm;
1672 craig 271
        if (!QFile::exists(iconFilePath))
272
                qWarning("Unable to load icon %s: File not found", iconFilePath.ascii());
273
        else
274
        {
275
                pm.load(iconFilePath);
276
                if (pm.isNull())
277
                        qWarning("Unable to load icon %s: Got null pixmap", iconFilePath.ascii());
278
        }
8 paul 279
        return pm;
280
}
281
 
1109 fschmid 282
uint getDouble(QString in, bool raw)
283
{
284
        QByteArray bb(4);
285
        if (raw)
286
        {
287
                bb[3] = static_cast<uchar>(QChar(in.at(0)));
288
                bb[2] = static_cast<uchar>(QChar(in.at(1)));
289
                bb[1] = static_cast<uchar>(QChar(in.at(2)));
290
                bb[0] = static_cast<uchar>(QChar(in.at(3)));
291
        }
292
        else
293
        {
294
                bb[0] = static_cast<uchar>(QChar(in.at(0)));
295
                bb[1] = static_cast<uchar>(QChar(in.at(1)));
296
                bb[2] = static_cast<uchar>(QChar(in.at(2)));
297
                bb[3] = static_cast<uchar>(QChar(in.at(3)));
298
        }
299
        uint ret;
300
        ret = bb[0] & 0xff;
301
        ret |= (bb[1] << 8) & 0xff00;
302
        ret |= (bb[2] << 16) & 0xff0000;
303
        ret |= (bb[3] << 24) & 0xff000000;
304
        return ret;
305
}
306
 
3158 craig 307
// Legacy implementation of LoadText with incorrect
308
// handling of unicode data. This should be retired.
309
// Use loadRawText instead.
310
// FIXME XXX
311
//
690 cbradney 312
bool loadText(QString filename, QString *Buffer)
8 paul 313
{
690 cbradney 314
        QFile f(filename);
8 paul 315
        QFileInfo fi(f);
316
        if (!fi.exists())
317
                return false;
167 Franz 318
        bool ret;
8 paul 319
        QByteArray bb(f.size());
320
        if (f.open(IO_ReadOnly))
167 Franz 321
        {
8 paul 322
                f.readBlock(bb.data(), f.size());
323
                f.close();
690 cbradney 324
                for (uint posi = 0; posi < bb.size(); ++posi)
3027 fschmid 325
                        *Buffer += QChar(bb[posi]);
3497 avox 326
                /*
327
                int len = bb.size();
328
                int oldLen = Buffer->length();
329
                Buffer->setLength( oldLen + len + 1);
330
                // digged into Qt 3.3 sources to find that. Might break in Qt 4 -- AV
331
                unsigned short * ucsString = const_cast<unsigned short *>(Buffer->ucs2()) + oldLen;
332
                char * data = bb.data();
333
                for (uint posi = 0; posi < len; ++posi)
334
                        *ucsString++ = *data++;
335
                *ucsString = 0;
336
                 */
8 paul 337
                ret = true;
167 Franz 338
        }
8 paul 339
        else
340
                ret = false;
341
        return ret;
342
}
343
 
3646 craig 344
bool loadRawText(const QString & filename, QCString & buf)
3158 craig 345
{
346
        bool ret = false;
347
        QFile f(filename);
348
        QFileInfo fi(f);
349
        if (fi.exists())
350
        {
3646 craig 351
                QCString tempBuf(f.size() + 1);
3158 craig 352
                if (f.open(IO_ReadOnly))
353
                {
4193 craig 354
                        unsigned int bytesRead = f.readBlock(tempBuf.data(), f.size());
3646 craig 355
                        tempBuf[bytesRead] = '\0';
3158 craig 356
                        ret = bytesRead == f.size();
357
                        if (ret)
358
                                buf = tempBuf; // sharing makes this efficient
359
                }
360
        }
361
        if (f.isOpen())
362
                f.close();
363
        return ret;
364
}
365
 
5234 fschmid 366
bool loadRawBytes(const QString & filename, QByteArray & buf)
367
{
368
        bool ret = false;
369
        QFile f(filename);
370
        QFileInfo fi(f);
371
        if (fi.exists())
372
        {
373
                QByteArray tempBuf(f.size());
374
                if (f.open(IO_ReadOnly))
375
                {
376
                        unsigned int bytesRead = f.readBlock(tempBuf.data(), f.size());
377
                        ret = bytesRead == f.size();
378
                        if (ret)
379
                                buf = tempBuf; // sharing makes this efficient
380
                }
381
        }
382
        if (f.isOpen())
383
                f.close();
384
        return ret;
385
}
386
 
80 Franz 387
QPointArray RegularPolygon(double w, double h, uint c, bool star, double factor, double rota)
8 paul 388
{
167 Franz 389
        uint cx = star ? c * 2 : c;
80 Franz 390
        double seg = 360.0 / cx;
391
        double sc = rota + 180.0;
392
        double di = factor;
8 paul 393
        int mx = 0;
394
        int my = 0;
4505 cbradney 395
        //QPointArray pts = QPointArray();
396
        QPointArray pts(cx);
8 paul 397
        for (uint x = 0; x < cx; ++x)
167 Franz 398
        {
8 paul 399
                sc = seg * x + 180.0 + rota;
400
                if (star)
167 Franz 401
                {
402
                        double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
403
                        double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
404
                        mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
405
                        my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
406
                }
8 paul 407
                else
167 Franz 408
                {
8 paul 409
                        mx = qRound(sin(sc / 180 * M_PI) * (w/2) + (w/2));
410
                        my = qRound(cos(sc / 180 * M_PI) * (h/2) + (h/2));
167 Franz 411
                }
4505 cbradney 412
                //pts.resize(x+1);
8 paul 413
                pts.setPoint(x, mx, my);
167 Franz 414
        }
8 paul 415
        return pts;
416
}
417
 
80 Franz 418
FPointArray RegularPolygonF(double w, double h, uint c, bool star, double factor, double rota)
8 paul 419
{
167 Franz 420
        uint cx = star ? c * 2 : c;
80 Franz 421
        double seg = 360.0 / cx;
422
        double sc = rota + 180.0;
423
        double di = factor;
424
        double mx = 0;
425
        double my = 0;
4505 cbradney 426
        //FPointArray pts;
427
        FPointArray pts(cx);
8 paul 428
        for (uint x = 0; x < cx; ++x)
167 Franz 429
        {
8 paul 430
                sc = seg * x + 180.0 + rota;
431
                if (star)
167 Franz 432
                {
433
                        double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
434
                        double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
435
                        mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
436
                        my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
437
                }
8 paul 438
                else
167 Franz 439
                {
8 paul 440
                        mx = sin(sc / 180 * M_PI) * (w/2) + (w/2);
441
                        my = cos(sc / 180 * M_PI) * (h/2) + (h/2);
167 Franz 442
                }
4505 cbradney 443
                //pts.resize(x+1);
8 paul 444
                pts.setPoint(x, mx, my);
167 Franz 445
        }
8 paul 446
        return pts;
447
}
448
 
449
QPointArray FlattenPath(FPointArray ina, QValueList<uint> &Segs)
450
{
451
        QPointArray Bez(4);
452
        QPointArray outa, cli;
453
        Segs.clear();
454
        if (ina.size() > 3)
167 Franz 455
        {
456
                for (uint poi=0; poi<ina.size()-3; poi += 4)
8 paul 457
                {
5234 fschmid 458
                        if (ina.point(poi).x() > 900000 && cli.size() > 0)
8 paul 459
                        {
460
                                outa.resize(outa.size()+1);
461
                                outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
80 Franz 462
                                Segs.append(outa.size());
8 paul 463
                                continue;
167 Franz 464
                        }
8 paul 465
                        BezierPoints(&Bez, ina.pointQ(poi), ina.pointQ(poi+1), ina.pointQ(poi+3), ina.pointQ(poi+2));
466
                        cli = Bez.cubicBezier();
467
                        outa.putPoints(outa.size(), cli.size()-1, cli);
167 Franz 468
                }
8 paul 469
                outa.resize(outa.size()+1);
470
                outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
167 Franz 471
        }
8 paul 472
        return outa;
473
}
474
 
80 Franz 475
double xy2Deg(double x, double y)
8 paul 476
{
477
        return (atan2(y,x)*(180.0/M_PI));
478
}
479
 
480
void BezierPoints(QPointArray *ar, QPoint n1, QPoint n2, QPoint n3, QPoint n4)
481
{
482
        ar->setPoint(0, n1);
483
        ar->setPoint(1, n2);
484
        ar->setPoint(2, n3);
485
        ar->setPoint(3, n4);
486
        return;
487
}
488
 
690 cbradney 489
void Level2Layer(ScribusDoc *currentDoc, struct Layer *ll, int Level)
8 paul 490
{
2955 fschmid 491
        uint layerCount=currentDoc->layerCount();
2937 cbradney 492
        for (uint la2 = 0; la2 < layerCount; ++la2)
167 Franz 493
        {
690 cbradney 494
                if (currentDoc->Layers[la2].Level == Level)
8 paul 495
                {
1065 cbradney 496
                        ll->isViewable = currentDoc->Layers[la2].isViewable;
497
                        ll->isPrintable = currentDoc->Layers[la2].isPrintable;
690 cbradney 498
                        ll->LNr = currentDoc->Layers[la2].LNr;
1737 fschmid 499
                        ll->Name = currentDoc->Layers[la2].Name;
8 paul 500
                        break;
501
                }
167 Franz 502
        }
8 paul 503
}
504
 
2937 cbradney 505
/* CB Replaced by ScribusDoc::layerLevelFromNumber
2122 fschmid 506
int Layer2Level(ScribusDoc *currentDoc, int LayerNr)
507
{
2937 cbradney 508
        int retVal=currentDoc->layerLevelFromNumber(LayerNr);
509
        int layerCount=currentDoc->layerCount();
510
        for (uint la2 = 0; la2 < layerCount; ++la2)
2122 fschmid 511
        {
512
                if (currentDoc->Layers[la2].LNr == LayerNr)
513
                        return currentDoc->Layers[la2].Level;
514
        }
515
        return 0;
516
}
2937 cbradney 517
*/
8 paul 518
QString CompressStr(QString *in)
519
{
520
        QString out = "";
521
#ifdef HAVE_LIBZ
522
        QByteArray bb(in->length());
523
        for (uint ax = 0; ax < in->length(); ++ax)
524
                bb[ax] = uchar(QChar(in->at(ax)));
525
        uLong exlen = uint(bb.size() * 0.001 + 16) + bb.size();
526
        QByteArray bc(exlen);
2295 cbradney 527
        int errcode = compress2((Byte *)bc.data(), &exlen, (Byte *)bb.data(), uLong(bb.size()), 9);
3158 craig 528
        if (errcode != Z_OK)
529
        {
530
                qDebug("compress2 failed with code %i", errcode);
2295 cbradney 531
                out = *in;
532
        }
533
        else {
534
                for (uint cl = 0; cl < exlen; ++cl)
2884 fschmid 535
                        out += QChar(bc[cl]);
2295 cbradney 536
        }
8 paul 537
#else
538
        out = *in;
539
#endif
540
        return out;
541
}
542
 
5234 fschmid 543
QByteArray CompressArray(QByteArray *in)
544
{
545
        QByteArray out;
546
#ifdef HAVE_LIBZ
547
        uLong exlen = uint(in->size() * 0.001 + 16) + in->size();
548
        QByteArray temp(exlen);
549
        int errcode = compress2((Byte *)temp.data(), &exlen, (Byte *)in->data(), uLong(in->size()), 9);
550
        if (errcode != Z_OK)
551
        {
552
                qDebug("compress2 failed with code %i", errcode);
553
                out = *in;
554
        }
555
        else {
556
                temp.resize(exlen);
557
                out = temp;
558
        }
559
#else
560
        out = *in;
561
#endif
562
        return out;
563
}
564
 
8 paul 565
char *toHex( uchar u )
566
{
1555 fschmid 567
        static char hexVal[3];
568
        int i = 1;
569
        while ( i >= 0 )
167 Franz 570
        {
571
                ushort hex = (u & 0x000f);
572
                if ( hex < 0x0a )
1555 fschmid 573
                        hexVal[i] = '0'+hex;
167 Franz 574
                else
1555 fschmid 575
                        hexVal[i] = 'A'+(hex-0x0a);
167 Franz 576
                u = u >> 4;
1555 fschmid 577
                i--;
578
        }
579
        hexVal[2] = '\0';
580
        return hexVal;
8 paul 581
}
582
 
583
QString String2Hex(QString *in, bool lang)
584
{
585
        int i = 0;
586
        QString out = "";
587
        for( uint xi = 0; xi < in->length(); ++xi )
167 Franz 588
        {
8 paul 589
                out += toHex(uchar(QChar(in->at(xi))));
590
                ++i;
591
                if ((i>40) && (lang))
167 Franz 592
                {
8 paul 593
                        out += '\n';
594
                        i=0;
595
                }
167 Franz 596
        }
8 paul 597
        return out;
598
}
599
 
600
QByteArray ComputeMD5Sum(QByteArray *in)
601
{
602
        QByteArray MDsum(16);
49 paul 603
        md5_buffer (in->data(), in->size(), reinterpret_cast<void*>(MDsum.data()));
8 paul 604
        return MDsum;
605
}
606
 
19 Franz 607
QString Path2Relative(QString Path)
608
{
609
        QString Ndir = "";
3089 fschmid 610
        QStringList Pdir;
19 Franz 611
        QFileInfo Bfi = QFileInfo(Path);
3089 fschmid 612
        QStringList Bdir;
690 cbradney 613
        bool end = true;
19 Franz 614
        uint dcoun = 0;
615
        uint dcoun2 = 0;
3089 fschmid 616
 
617
#ifndef _WIN32
618
        Pdir = QStringList::split("/", QDir::currentDirPath());
619
        Bdir = QStringList::split("/", Bfi.dirPath(true));
620
#else
621
        // On win32, file systems are case insensitive
622
        Pdir = QStringList::split("/", QDir::currentDirPath().lower());
623
        Bdir = QStringList::split("/", Bfi.dirPath(true).lower());
624
        // We must check that both path are located on same drive
625
        if( Pdir.size() > 0 && Bdir.size() > 0 )
626
        {
627
                QString drive = Bdir.front();
628
                QString currentDrive = Pdir.front();
4546 subik 629
                if( drive != currentDrive )
3089 fschmid 630
                        return Path;
631
        }
632
#endif
633
 
690 cbradney 634
        while (end)
167 Franz 635
        {
19 Franz 636
                if (Pdir[dcoun] == Bdir[dcoun])
637
                        dcoun++;
638
                else
639
                        break;
640
                if (dcoun > Pdir.count())
641
                        break;
167 Franz 642
        }
19 Franz 643
        dcoun2 = dcoun;
3089 fschmid 644
 
645
#ifdef _WIN32
646
        Bdir = QStringList::split("/", Bfi.dirPath(true));
647
#endif
648
 
19 Franz 649
        for (uint ddx2 = dcoun; ddx2 < Pdir.count(); ddx2++)
650
                Ndir += "../";
651
        for (uint ddx = dcoun2; ddx < Bdir.count(); ddx++)
652
                Ndir += Bdir[ddx]+"/";
653
        Ndir += Bfi.fileName();
654
        return Ndir;
655
}
656
 
90 Franz 657
/***************************************************************************
658
    begin                : Wed Oct 29 2003
659
    copyright            : (C) 2003 The Scribus Team
660
    email                : paul@all-the-johnsons.co.uk
661
 ***************************************************************************/
662
// check if the file exists, if it does, ask if they're sure
663
// return true if they're sure, else return false;
664
 
665
bool overwrite(QWidget *parent, QString filename)
666
{
167 Franz 667
        bool retval = true;
668
        QFileInfo fi(filename);
669
        if (fi.exists())
1555 fschmid 670
        {
4546 subik 671
                int t = ScMessageBox::warning(parent, QObject::tr("File exists"),
3733 cbradney 672
                                                                        "<qt>"+ QObject::tr("A file named '%1' already exists.<br/>Do you want to replace it with the file you are saving?").arg(filename) +"</qt>",
673
                                                                        QObject::tr("&Replace"), CommonStrings::tr_Cancel, "", 1, 1);
674
                if (t == 1)
90 Franz 675
                        retval = false;
1555 fschmid 676
        }
677
        return retval;
90 Franz 678
}
124 Franz 679
 
1957 cbradney 680
void WordAndPara(PageItem* currItem, int *w, int *p, int *c, int *wN, int *pN, int *cN)
125 Franz 681
{
682
        QChar Dat = QChar(32);
683
        int para = 0;
684
        int ww = 0;
685
        int cc = 0;
686
        int paraN = 0;
687
        int wwN = 0;
688
        int ccN = 0;
689
        bool first = true;
5184 avox 690
#ifndef NLS_PROTO
1957 cbradney 691
        PageItem *nextItem = currItem;
692
        PageItem *nbl = currItem;
693
        while (nextItem != 0)
167 Franz 694
        {
1957 cbradney 695
                if (nextItem->BackBox != 0)
696
                        nextItem = nextItem->BackBox;
125 Franz 697
                else
698
                        break;
167 Franz 699
        }
1957 cbradney 700
        while (nextItem != 0)
167 Franz 701
        {
5184 avox 702
                for (uint a = 0; a < nextItem->itemText.length(); ++a)
1555 fschmid 703
                {
5184 avox 704
                        QChar b = nextItem->itemText.text(a);
125 Franz 705
                        if (b == QChar(13))
167 Franz 706
                        {
1957 cbradney 707
                                if (a >= nextItem->MaxChars)
125 Franz 708
                                        paraN++;
709
                                else
710
                                        para++;
167 Franz 711
                        }
125 Franz 712
                        if ((!b.isLetterOrNumber()) && (Dat.isLetterOrNumber()) && (!first))
167 Franz 713
                        {
1957 cbradney 714
                                if (a >= nextItem->MaxChars)
125 Franz 715
                                        wwN++;
716
                                else
717
                                        ww++;
167 Franz 718
                        }
1957 cbradney 719
                        if (a >= nextItem->MaxChars)
125 Franz 720
                                ccN++;
721
                        else
722
                                cc++;
1555 fschmid 723
                        Dat = b;
125 Franz 724
                        first = false;
1555 fschmid 725
                }
1957 cbradney 726
                nbl = nextItem;
727
                nextItem = nextItem->NextBox;
167 Franz 728
        }
1065 cbradney 729
        if (nbl->MaxChars < nbl->itemText.count())
125 Franz 730
                paraN++;
731
        else
732
                para++;
733
        if (Dat.isLetterOrNumber())
167 Franz 734
        {
1065 cbradney 735
                if (nbl->MaxChars < nbl->itemText.count())
125 Franz 736
                        wwN++;
737
                else
738
                        ww++;
167 Franz 739
        }
125 Franz 740
        *w = ww;
741
        *p = para;
742
        *c = cc;
743
        *wN = wwN;
744
        *pN = paraN;
745
        *cN = ccN;
5184 avox 746
#endif
125 Franz 747
}
203 Franz 748
 
690 cbradney 749
void ReOrderText(ScribusDoc *currentDoc, ScribusView *view)
203 Franz 750
{
4593 cbradney 751
        double savScale = view->scale();
2380 cbradney 752
        view->setScale(1.0);
690 cbradney 753
        currentDoc->RePos = true;
203 Franz 754
        QPixmap pgPix(10, 10);
755
        QRect rd = QRect(0,0,9,9);
756
        ScPainter *painter = new ScPainter(&pgPix, pgPix.width(), pgPix.height());
690 cbradney 757
        for (uint azz=0; azz<currentDoc->MasterItems.count(); ++azz)
203 Franz 758
        {
1957 cbradney 759
                PageItem *currItem = currentDoc->MasterItems.at(azz);
760
                if (currItem->itemType() == PageItem::PathText)
761
                        currItem->DrawObj(painter, rd);
203 Franz 762
        }
3727 cbradney 763
        for (uint azz=0; azz<currentDoc->Items->count(); ++azz)
203 Franz 764
        {
3727 cbradney 765
                PageItem *currItem = currentDoc->Items->at(azz);
1957 cbradney 766
                if ((currItem->itemType() == PageItem::TextFrame) || (currItem->itemType() == PageItem::PathText))
767
                        currItem->DrawObj(painter, rd);
203 Franz 768
        }
690 cbradney 769
        currentDoc->RePos = false;
2380 cbradney 770
        view->setScale(savScale);
203 Franz 771
        delete painter;
772
}
447 cbradney 773
 
4449 subik 774
/*! \brief Helper function for sorting in sortQStringList.
775
\author 10/06/2004 - pv
4645 subik 776
\param s1 first string
777
\param s2 second string
447 cbradney 778
\retval bool t/f related s1>s2
779
 */
780
bool compareQStrings(QString s1, QString s2)
781
{
782
        if (QString::localeAwareCompare(s1, s2) >= 0)
2680 cbradney 783
                return false;
784
        return true;
447 cbradney 785
}
786
 
787
QStringList sortQStringList(QStringList aList)
788
{
789
        std::vector<QString> sortList;
790
        QStringList retList;
791
        QStringList::Iterator it;
792
        for (it = aList.begin(); it != aList.end(); ++it)
793
                sortList.push_back(*it);
794
        std::sort(sortList.begin(), sortList.end(), compareQStrings);
456 fschmid 795
        for(uint i = 0; i < sortList.size(); i++)
447 cbradney 796
                retList.append(sortList[i]);
797
        return retList;
798
}
517 fschmid 799
 
1065 cbradney 800
void GetItemProps(bool newVersion, QDomElement *obj, struct CopyPasteBuffer *OB)
517 fschmid 801
{
802
        QString tmp;
803
        int x, y;
2282 fschmid 804
        double xf, yf, xf2;
4026 craig 805
        OB->PType = static_cast<PageItem::ItemType>(obj->attribute("PTYPE").toInt());
806
        OB->Width=obj->attribute("WIDTH").toDouble();
807
        OB->Height=obj->attribute("HEIGHT").toDouble();
808
        OB->RadRect = obj->attribute("RADRECT", "0").toDouble();
809
        OB->ClipEdited = obj->attribute("CLIPEDIT", "0").toInt();
810
        OB->FrameType = obj->attribute("FRTYPE", "0").toInt();
811
        OB->Pwidth=obj->attribute("PWIDTH").toDouble();
1394 cbradney 812
        OB->Pcolor = obj->attribute("PCOLOR");
517 fschmid 813
        if ((!newVersion) && (OB->PType == 4))
814
        {
815
                OB->TxtFill = obj->attribute("PCOLOR2");
4546 subik 816
                OB->Pcolor2 = CommonStrings::None;
517 fschmid 817
        }
818
        else
819
        {
820
                OB->Pcolor2 = obj->attribute("PCOLOR2");
821
                OB->TxtFill = obj->attribute("TXTFILL", "Black");
822
        }
4026 craig 823
        OB->Shade = obj->attribute("SHADE").toInt();
824
        OB->Shade2 = obj->attribute("SHADE2").toInt();
4546 subik 825
        OB->TxtStroke=obj->attribute("TXTSTROKE", CommonStrings::None);
4026 craig 826
        OB->ShTxtFill=obj->attribute("TXTFILLSH", "100").toInt();
827
        OB->ShTxtStroke=obj->attribute("TXTSTRSH", "100").toInt();
828
        OB->TxtScale=qRound(obj->attribute("TXTSCALE", "100").toDouble() * 10);
829
        OB->TxtScaleV=qRound(obj->attribute("TXTSCALEV", "100").toDouble() * 10);
830
        OB->TxTBase=qRound(obj->attribute("TXTBASE", "0").toDouble() * 10);
831
        OB->TxTStyle=obj->attribute("TXTSTYLE", "0").toInt();
832
        OB->TxtShadowX=qRound(obj->attribute("TXTSHX", "5").toDouble() * 10);
833
        OB->TxtShadowY=qRound(obj->attribute("TXTSHY", "-5").toDouble() * 10);
834
        OB->TxtOutline=qRound(obj->attribute("TXTOUT", "1").toDouble() * 10);
835
        OB->TxtUnderPos=qRound(obj->attribute("TXTULP", "-0.1").toDouble() * 10);
836
        OB->TxtUnderWidth=qRound(obj->attribute("TXTULW", "-0.1").toDouble() * 10);
837
        OB->TxtStrikePos=qRound(obj->attribute("TXTSTP", "-0.1").toDouble() * 10);
838
        OB->TxtStrikeWidth=qRound(obj->attribute("TXTSTW", "-0.1").toDouble() * 10);
839
        OB->Cols = obj->attribute("COLUMNS", "1").toInt();
840
        OB->ColGap = obj->attribute("COLGAP", "0.0").toDouble();
841
        OB->GrType = obj->attribute("GRTYP", "0").toInt();
517 fschmid 842
        OB->fill_gradient.clearStops();
843
        if (OB->GrType != 0)
844
        {
4026 craig 845
                OB->GrStartX = obj->attribute("GRSTARTX", "0.0").toDouble();
846
                OB->GrStartY = obj->attribute("GRSTARTY", "0.0").toDouble();
847
                OB->GrEndX = obj->attribute("GRENDX", "0.0").toDouble();
848
                OB->GrEndY = obj->attribute("GRENDY", "0.0").toDouble();
517 fschmid 849
                OB->GrColor = obj->attribute("GRCOLOR","");
2877 cbradney 850
                if (OB->GrColor.isEmpty())
2179 fschmid 851
                        OB->GrColor = "Black";
852
                OB->GrColor2 = obj->attribute("GRCOLOR2","Black");
2877 cbradney 853
                if (OB->GrColor2.isEmpty())
2179 fschmid 854
                        OB->GrColor2 = "Black";
4026 craig 855
                OB->GrShade = obj->attribute("GRSHADE", "100").toInt();
856
                OB->GrShade2 = obj->attribute("GRSHADE2", "100").toInt();
517 fschmid 857
        }
4026 craig 858
        OB->Rot=obj->attribute("ROT").toDouble();
859
        OB->PLineArt=Qt::PenStyle(obj->attribute("PLINEART").toInt());
860
        OB->PLineEnd=Qt::PenCapStyle(obj->attribute("PLINEEND", "0").toInt());
861
        OB->PLineJoin=Qt::PenJoinStyle(obj->attribute("PLINEJOIN", "0").toInt());
862
        OB->LineSp=obj->attribute("LINESP").toDouble();
863
        OB->LineSpMode = obj->attribute("LINESPMode", "0").toInt();
864
        OB->LocalScX=obj->attribute("LOCALSCX").toDouble();
865
        OB->LocalScY=obj->attribute("LOCALSCY").toDouble();
866
        OB->LocalX=obj->attribute("LOCALX").toDouble();
867
        OB->LocalY=obj->attribute("LOCALY").toDouble();
868
        OB->PicArt=obj->attribute("PICART").toInt();
869
        OB->flippedH = obj->attribute("FLIPPEDH").toInt() % 2;
870
        OB->flippedV = obj->attribute("FLIPPEDV").toInt() % 2;
4335 fschmid 871
/*      OB->BBoxX=obj->attribute("BBOXX").toDouble();
872
        OB->BBoxH=obj->attribute("BBOXH").toDouble(); */
4026 craig 873
        OB->ScaleType = obj->attribute("SCALETYPE", "1").toInt();
874
        OB->AspectRatio = obj->attribute("RATIO", "0").toInt();
875
        OB->isPrintable=obj->attribute("PRINTABLE").toInt();
4084 cbradney 876
        OB->m_isAnnotation=obj->attribute("ANNOTATION", "0").toInt();
877
        OB->m_annotation.setType(obj->attribute("ANTYPE", "0").toInt());
878
        OB->m_annotation.setAction(obj->attribute("ANACTION",""));
879
        OB->m_annotation.setE_act(obj->attribute("ANEACT",""));
880
        OB->m_annotation.setX_act(obj->attribute("ANXACT",""));
881
        OB->m_annotation.setD_act(obj->attribute("ANDACT",""));
882
        OB->m_annotation.setFo_act(obj->attribute("ANFOACT",""));
883
        OB->m_annotation.setBl_act(obj->attribute("ANBLACT",""));
884
        OB->m_annotation.setK_act(obj->attribute("ANKACT",""));
885
        OB->m_annotation.setF_act(obj->attribute("ANFACT",""));
886
        OB->m_annotation.setV_act(obj->attribute("ANVACT",""));
887
        OB->m_annotation.setC_act(obj->attribute("ANCACT",""));
888
        OB->m_annotation.setActionType(obj->attribute("ANACTYP", "0").toInt());
889
        OB->m_annotation.setExtern(obj->attribute("ANEXTERN",""));
890
        if ((!OB->m_annotation.Extern().isEmpty()) && (OB->m_annotation.ActionType() != 8))
517 fschmid 891
        {
4084 cbradney 892
                QFileInfo efp(OB->m_annotation.Extern());
893
                OB->m_annotation.setExtern(efp.absFilePath());
517 fschmid 894
        }
4084 cbradney 895
        OB->m_annotation.setZiel(obj->attribute("ANZIEL", "0").toInt());
896
        OB->AnName=obj->attribute("ANNAME","");
897
        OB->m_annotation.setToolTip(obj->attribute("ANTOOLTIP",""));
898
        OB->m_annotation.setRollOver(obj->attribute("ANROLL",""));
899
        OB->m_annotation.setDown(obj->attribute("ANDOWN",""));
900
        OB->m_annotation.setBwid(obj->attribute("ANBWID", "1").toInt());
901
        OB->m_annotation.setBsty(obj->attribute("ANBSTY", "0").toInt());
902
        OB->m_annotation.setFeed(obj->attribute("ANFEED", "1").toInt());
903
        OB->m_annotation.setFlag(obj->attribute("ANFLAG", "0").toInt());
904
        OB->m_annotation.setFont(obj->attribute("ANFONT", "4").toInt());
905
        OB->m_annotation.setFormat(obj->attribute("ANFORMAT", "0").toInt());
906
        OB->m_annotation.setVis(obj->attribute("ANVIS", "0").toInt());
907
        OB->m_annotation.setIsChk(static_cast<bool>(obj->attribute("ANCHK", "0").toInt()));
908
        OB->m_annotation.setAAact(static_cast<bool>(obj->attribute("ANAA", "0").toInt()));
909
        OB->m_annotation.setHTML(static_cast<bool>(obj->attribute("ANHTML", "0").toInt()));
910
        OB->m_annotation.setUseIcons(static_cast<bool>(obj->attribute("ANICON", "0").toInt()));
911
        OB->m_annotation.setChkStil(obj->attribute("ANCHKS", "0").toInt());
912
        OB->m_annotation.setMaxChar(obj->attribute("ANMC", "-1").toInt());
4546 subik 913
        OB->m_annotation.setBorderColor(obj->attribute("ANBCOL",CommonStrings::None));
4084 cbradney 914
        OB->m_annotation.setIPlace(obj->attribute("ANPLACE", "1").toInt());
915
        OB->m_annotation.setScaleW(obj->attribute("ANSCALE", "0").toInt());
4026 craig 916
        if (obj->attribute("TRANSPARENT", "0").toInt() == 1)
4546 subik 917
                OB->Pcolor = CommonStrings::None;
4026 craig 918
        OB->Textflow=obj->attribute("TEXTFLOW").toInt();
919
        OB->Textflow2 =obj->attribute("TEXTFLOW2", "0").toInt();
920
        OB->UseContour = obj->attribute("TEXTFLOW3", "0").toInt();
921
        OB->Extra=obj->attribute("EXTRA").toDouble();
922
        OB->TExtra=obj->attribute("TEXTRA", "1").toDouble();
923
        OB->BExtra=obj->attribute("BEXTRA", "1").toDouble();
924
        OB->RExtra=obj->attribute("REXTRA", "1").toDouble();
925
        OB->PoShow = obj->attribute("PLTSHOW", "0").toInt();
926
        OB->BaseOffs = obj->attribute("BASEOF", "0").toDouble();
927
        OB->ISize = qRound(obj->attribute("ISIZE", "12").toDouble() * 10);
2382 fschmid 928
        if (obj->hasAttribute("EXTRAV"))
4026 craig 929
                OB->ExtraV = qRound(obj->attribute("EXTRAV", "0").toDouble() / obj->attribute("ISIZE", "12").toDouble() * 1000.0);
2382 fschmid 930
        else
4026 craig 931
                OB->ExtraV = obj->attribute("TXTKERN").toInt();
517 fschmid 932
        OB->Pfile=obj->attribute("PFILE");
933
        OB->Pfile2=obj->attribute("PFILE2","");
934
        OB->Pfile3=obj->attribute("PFILE3","");
935
        OB->IProfile=obj->attribute("PRFILE","");
936
        OB->EmProfile=obj->attribute("EPROF","");
4026 craig 937
        OB->IRender = obj->attribute("IRENDER", "1").toInt();
938
        OB->UseEmbedded = obj->attribute("EMBEDDED", "1").toInt();
939
        OB->Locked = static_cast<bool>(obj->attribute("LOCK", "0").toInt());
940
        OB->LockRes = static_cast<bool>(obj->attribute("LOCKR", "0").toInt());
941
        OB->Reverse = static_cast<bool>(obj->attribute("REVERS", "0").toInt());
942
        OB->isTableItem = static_cast<bool>(obj->attribute("isTableItem", "0").toInt());
943
        OB->TopLine = static_cast<bool>(obj->attribute("TopLine", "0").toInt());
944
        OB->LeftLine = static_cast<bool>(obj->attribute("LeftLine", "0").toInt());
945
        OB->RightLine = static_cast<bool>(obj->attribute("RightLine", "0").toInt());
946
        OB->BottomLine = static_cast<bool>(obj->attribute("BottomLine", "0").toInt());
947
        OB->TopLinkID =  obj->attribute("TopLINK", "-1").toInt();
948
        OB->LeftLinkID =  obj->attribute("LeftLINK", "-1").toInt();
949
        OB->RightLinkID =  obj->attribute("RightLINK", "-1").toInt();
950
        OB->BottomLinkID =  obj->attribute("BottomLINK", "-1").toInt();
951
        OB->Transparency = obj->attribute("TransValue", "0.0").toDouble();
517 fschmid 952
        if (obj->hasAttribute("TransValueS"))
4026 craig 953
                OB->TranspStroke = obj->attribute("TransValueS", "0.0").toDouble();
517 fschmid 954
        else
955
                OB->TranspStroke = OB->Transparency;
956
        tmp = "";
957
        if (obj->hasAttribute("NUMCLIP"))
958
        {
959
                OB->Clip.resize(obj->attribute("NUMCLIP").toUInt());
960
                tmp = obj->attribute("CLIPCOOR");
961
                QTextStream fc(&tmp, IO_ReadOnly);
962
                for (uint c=0; c<obj->attribute("NUMCLIP").toUInt(); ++c)
963
                {
964
                        fc >> x;
965
                        fc >> y;
966
                        OB->Clip.setPoint(c, x, y);
967
                }
968
        }
969
        else
970
                OB->Clip.resize(0);
971
        tmp = "";
972
        if (obj->hasAttribute("NUMPO"))
973
        {
974
                OB->PoLine.resize(obj->attribute("NUMPO").toUInt());
975
                tmp = obj->attribute("POCOOR");
976
                QTextStream fp(&tmp, IO_ReadOnly);
977
                for (uint cx=0; cx<obj->attribute("NUMPO").toUInt(); ++cx)
978
                {
979
                        fp >> xf;
980
                        fp >> yf;
981
                        OB->PoLine.setPoint(cx, xf, yf);
982
                }
983
        }
984
        else
985
                OB->PoLine.resize(0);
986
        tmp = "";
987
        if (obj->hasAttribute("NUMCO"))
988
        {
989
                OB->ContourLine.resize(obj->attribute("NUMCO").toUInt());
990
                tmp = obj->attribute("COCOOR");
991
                QTextStream fp(&tmp, IO_ReadOnly);
992
                for (uint cx=0; cx<obj->attribute("NUMCO").toUInt(); ++cx)
993
                {
994
                        fp >> xf;
995
                        fp >> yf;
996
                        OB->ContourLine.setPoint(cx, xf, yf);
997
                }
998
        }
999
        else
1000
                OB->ContourLine.resize(0);
1001
        tmp = "";
4026 craig 1002
        if ((obj->hasAttribute("NUMTAB")) && (obj->attribute("NUMTAB", "0").toInt() != 0))
517 fschmid 1003
        {
5184 avox 1004
                ParagraphStyle::TabRecord tb;
517 fschmid 1005
                tmp = obj->attribute("TABS");
1006
                QTextStream tgv(&tmp, IO_ReadOnly);
1007
                OB->TabValues.clear();
4026 craig 1008
                for (int cxv = 0; cxv < obj->attribute("NUMTAB", "0").toInt(); cxv += 2)
517 fschmid 1009
                {
1010
                        tgv >> xf;
2282 fschmid 1011
                        tgv >> xf2;
1012
                        tb.tabPosition = xf2;
1013
                        tb.tabType = static_cast<int>(xf);
1014
                        tb.tabFillChar = QChar();
1015
                        OB->TabValues.append(tb);
517 fschmid 1016
                }
1017
                tmp = "";
1018
        }
1019
        else
1020
                OB->TabValues.clear();
4026 craig 1021
        if ((obj->hasAttribute("NUMDASH")) && (obj->attribute("NUMDASH", "0").toInt() != 0))
517 fschmid 1022
        {
1023
                tmp = obj->attribute("DASHS");
1024
                QTextStream dgv(&tmp, IO_ReadOnly);
1025
                OB->DashValues.clear();
4026 craig 1026
                for (int cxv = 0; cxv < obj->attribute("NUMDASH", "0").toInt(); ++cxv)
517 fschmid 1027
                {
1028
                        dgv >> xf;
1029
                        OB->DashValues.append(xf);
1030
                }
1031
                tmp = "";
1032
        }
1033
        else
1034
                OB->DashValues.clear();
4026 craig 1035
        OB->DashOffset = obj->attribute("DASHOFF", "0.0").toDouble();
517 fschmid 1036
}
1037
 
690 cbradney 1038
QColor SetColor(ScribusDoc *currentDoc, QString color, int shad)
517 fschmid 1039
{
1488 fschmid 1040
        return currentDoc->PageColors[color].getShadeColorProof(shad);
517 fschmid 1041
}
2529 craig 1042
 
2636 cbradney 1043
 
1044
/**
1045
 * QPixmaps are really slow with Qt/Mac 3.3.4. Really, *really*, slow.
1046
 * So we better cache them.
1047
 */
2907 subik 1048
QPixmap * getSmallPixmap(QColor rgb)
2636 cbradney 1049
{
1050
        static QMap<QRgb, QPixmap*> pxCache;
1051
 
3719 cbradney 1052
        QRgb index=rgb.rgb();
1053
        if (pxCache.contains(index))
1054
                return pxCache[index];
1055
 
1056
        QPixmap *pm = new QPixmap(15, 15);
1057
        pm->fill(rgb);
1058
        QPainter p;
1059
        p.begin(pm);
1060
        p.setBrush(Qt::NoBrush);
1061
        QPen b(Qt::black, 1);
1062
        p.setPen(b);
1063
        p.drawRect(0, 0, 15, 15);
1064
        p.end();
1065
        pxCache.insert(index, pm);
2636 cbradney 1066
        return pm;
1067
}
1068
 
2907 subik 1069
QPixmap * getWidePixmap(QColor rgb)
2636 cbradney 1070
{
1071
        static QMap<QRgb, QPixmap*> pxCache;
2907 subik 1072
 
3719 cbradney 1073
        QRgb index=rgb.rgb();
1074
        if (pxCache.contains(index))
1075
                return pxCache[index];
1076
 
1077
        QPixmap *pm = new QPixmap(30, 15);
1078
        pm->fill(rgb);
1079
        pxCache.insert(index, pm);
2636 cbradney 1080
        return pm;
1081
}
1082
 
3497 avox 1083
static Q_UINT64 code64(ScColor & col) {
1084
        int C, M, Y, K, R, G, B;
4505 cbradney 1085
        Q_UINT64 result=0;
3497 avox 1086
        col.getRGB( &R, &G, &B );
1087
        col.getCMYK( &C, &M, &Y, &K );
1088
        result |= col.getColorModel() == colorModelRGB ? 1 : 0;
1089
        result |= col.isOutOfGamut() ? 64 : 0;
1090
        result |= col.isSpotColor() ? 32 : 0;
1091
        result |= col.isRegistrationColor() ? 16 : 0;
1092
        result <<= 8;
1093
        result |= C;
1094
        result <<= 8;
1095
        result |= M;
1096
        result <<= 8;
1097
        result |= Y;
1098
        result <<= 8;
1099
        result |= K;
1100
        result <<= 8;
1101
        result |= R;
1102
        result <<= 8;
1103
        result |= G;
1104
        result <<= 8;
1105
        result |= B;
1106
        return result;
1107
}
1108
 
1109
QPixmap * getFancyPixmap(ScColor col) {
3717 cbradney 1110
        static QMap<Q_UINT64, QPixmap*> pxCache;
4546 subik 1111
 
3497 avox 1112
        static QPixmap alertIcon;
1113
        static QPixmap cmykIcon;
1114
        static QPixmap rgbIcon;
1115
        static QPixmap spotIcon;
1116
        static QPixmap regIcon;
1117
        static bool iconsInitialized = false;
4546 subik 1118
 
3497 avox 1119
        if ( !iconsInitialized ) {
1120
                alertIcon = loadIcon("alert.png");
1121
                cmykIcon = loadIcon("cmyk.png");
1122
                rgbIcon = loadIcon("rgb.png");
1123
                spotIcon = loadIcon("spot.png");
1124
                regIcon = loadIcon("register.png");
1125
                iconsInitialized = true;
1126
        }
4546 subik 1127
 
3717 cbradney 1128
        Q_UINT64 res=code64(col);
1129
        if (pxCache.contains(res))
1130
                return pxCache[res];
4546 subik 1131
 
3717 cbradney 1132
        QPixmap *pa=new QPixmap(60, 15);
1133
        QPixmap *pm=getSmallPixmap(col.getRawRGBColor());
1134
        pa->fill(Qt::white);
1135
        paintAlert(*pm, *pa, 0, 0);
1136
        col.checkGamut();
1137
        if (col.isOutOfGamut())
1138
                paintAlert(alertIcon, *pa, 15, 0);
1139
        if ((col.getColorModel() == colorModelCMYK) || (col.isSpotColor()))
1140
                paintAlert(cmykIcon, *pa, 30, 0);
1141
        else
1142
                paintAlert(rgbIcon, *pa, 30, 0);
1143
        if (col.isSpotColor())
1144
                paintAlert(spotIcon, *pa, 46, 2);
1145
        if (col.isRegistrationColor())
1146
                paintAlert(regIcon, *pa, 45, 0);
1147
        pxCache.insert(res, pa);
3497 avox 1148
        return pa;
1149
}
1150
 
1151
 
3046 fschmid 1152
void paintAlert(QPixmap &toPaint, QPixmap &target, int x, int y)
3041 fschmid 1153
{
4449 subik 1154
        // there is no alpha mask in the beginning
1155
        if (target.mask()==0)
1156
                target.setMask(QBitmap(target.width(), target.height(), true));
3041 fschmid 1157
        QPainter p;
4449 subik 1158
        QPainter alpha; // transparency handling
3041 fschmid 1159
        p.begin(&target);
4449 subik 1160
        alpha.begin(target.mask());
1161
        alpha.setBrush(Qt::color1);
1162
        alpha.setPen(Qt::color1);
3046 fschmid 1163
        p.drawPixmap(x, y, toPaint);
4449 subik 1164
        alpha.drawRect(x, y, 15, 15);
3041 fschmid 1165
        p.end();
4449 subik 1166
        alpha.end();
3041 fschmid 1167
}
1168
 
2529 craig 1169
FPoint getMaxClipF(FPointArray* Clip)
1170
{
1171
        FPoint np, rp;
1172
        double mx = 0;
1173
        double my = 0;
3719 cbradney 1174
        uint clipSize=Clip->size();
1175
        for (uint c = 0; c < clipSize; ++c)
2529 craig 1176
        {
1177
                np = Clip->point(c);
1178
                if (np.x() > 900000)
1179
                        continue;
1180
                if (np.x() > mx)
1181
                        mx = np.x();
1182
                if (np.y() > my)
1183
                        my = np.y();
1184
        }
1185
        rp.setXY(mx, my);
1186
        return rp;
1187
}
1188
 
1189
FPoint getMinClipF(FPointArray* Clip)
1190
{
1191
        FPoint np, rp;
1192
        double mx = 99999;
1193
        double my = 99999;
3719 cbradney 1194
        uint clipSize=Clip->size();
1195
        for (uint c = 0; c < clipSize; ++c)
2529 craig 1196
        {
1197
                np = Clip->point(c);
1198
                if (np.x() > 900000)
1199
                        continue;
1200
                if (np.x() < mx)
1201
                        mx = np.x();
1202
                if (np.y() < my)
1203
                        my = np.y();
1204
        }
1205
        rp.setXY(mx, my);
1206
        return rp;
1207
}
1208
 
2834 cbradney 1209
QString checkFileExtension(const QString &currName, const QString &extension)
1210
{
1211
        QString newName(currName);
1212
        //If filename ends with a period, just add the extension
1213
        if (newName.right(1)==".")
1214
        {
1215
                newName+=extension.lower();
1216
                return newName;
1217
        }
1218
        //If filename doesnt end with the period+extension, add it on
1219
        QString dotExt("." + extension.lower());
1220
        if (!newName.endsWith(dotExt,false))
1221
                newName+=dotExt;
1222
        return newName;
1223
}
2907 subik 1224
 
1225
QString getFileNameByPage(uint pageNo, QString extension)
1226
{
1227
        QString number;
4026 craig 1228
        number = number.setNum(pageNo + ScMW->doc->FirstPnum);
1229
        QString defaultName = ScMW->doc->DocName;
2907 subik 1230
        if (defaultName.isNull())
1231
                defaultName = "export";
1232
        else
1233
        {
1234
                QFileInfo fi(defaultName);
1235
                defaultName = fi.baseName(true);
1236
        }
2954 subik 1237
        return QString("%1-%2%3.%4").arg(defaultName).arg(QObject::tr("page", "page export")).arg(number).arg(extension);
2907 subik 1238
}
3689 cbradney 1239
 
1240
inline double square(double x)
1241
{
1242
        return x*x;
1243
}
1244
 
1245
inline double distance(double x, double y)
1246
{
1247
        return sqrt(x*x+y*y);
1248
}
1249
 
4754 cbradney 1250
double constrainAngle(double angle)
1251
{
1252
        double newAngle=angle;
1253
        double constrainTo=15.0;
1254
        if (newAngle<0.0)
1255
                newAngle+=360.0;
1256
        newAngle=qRound(angle/constrainTo)*constrainTo;
1257
        if (newAngle==360.0)
1258
                newAngle=0.0;
1259
        return newAngle;
1260
}
1261
 
3757 cbradney 1262
const QString getStringFromSequence(DocumentSectionType type, uint position)
1263
{
1264
        QString retVal("");
1265
        switch( type )
1266
        {
3778 cbradney 1267
                case Type_1_2_3:
1268
                        retVal=QString::number(position);
1269
                        break;
3757 cbradney 1270
                case Type_A_B_C:
3778 cbradney 1271
                        retVal=numberToLetterSequence(position).upper();
1272
                        break;
3757 cbradney 1273
                case Type_a_b_c:
3778 cbradney 1274
                        retVal=numberToLetterSequence(position);
3757 cbradney 1275
                        break;
1276
                case Type_I_II_III:
1277
                        retVal=arabicToRoman(position);
1278
                        break;
1279
                case Type_i_ii_iii:
1280
                        //well, for lower case people will want that, even if its "wrong"
1281
                        //ie, X=10, x=10000
1282
                        retVal=arabicToRoman(position).lower();
1283
                        break;
1284
                default:
1285
                        break;
1286
        }
1287
        return retVal;
1288
}
1289
 
1290
const QString numberToLetterSequence(uint i)
1291
{
1292
        QString retVal("");
1293
        unsigned digits = 1;
1294
        unsigned offset = 0;
1295
        uint column=i;
1296
        --column;
1297
 
1298
        if( column > 4058115285U ) return  QString("@");
1299
 
1300
        for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ )
1301
                offset += limit;
1302
 
1303
        for( unsigned c = column - offset; digits; --digits, c/=26 )
1304
                retVal.prepend( QChar( 'a' + (c%26) ) );
1305
        return retVal;
1306
}
1307
 
1308
const QString arabicToRoman(uint i)
1309
{
1310
        QString roman("");
1311
        int arabic = i;
1312
        while (arabic - 1000000 >= 0){
1313
        roman += "m";
1314
        arabic -= 1000000;
1315
        }
1316
        while (arabic - 900000 >= 0){
1317
        roman += "cm";
1318
        arabic -= 900000;
1319
        }
1320
        while (arabic - 500000 >= 0){
1321
        roman += "d";
1322
        arabic -= 500000;
1323
        }
1324
        while (arabic - 400000 >= 0){
1325
        roman += "cd";
1326
        arabic -= 400000;
1327
        }
1328
        while (arabic - 100000 >= 0){
1329
        roman += "c";
1330
        arabic -= 100000;
1331
        }
1332
        while (arabic - 90000 >= 0){
1333
        roman += "xc";
1334
        arabic -= 90000;
1335
        }
1336
        while (arabic - 50000 >= 0){
1337
        roman += "l";
1338
        arabic -= 50000;
1339
        }
1340
        while (arabic - 40000 >= 0){
1341
        roman += "xl";
1342
        arabic -= 40000;
1343
        }
1344
        while (arabic - 10000 >= 0){
1345
        roman += "x";
1346
        arabic -= 10000;
1347
        }
1348
        while (arabic - 9000 >= 0){
1349
        roman += "Mx";
1350
        arabic -= 9000;
1351
        }
1352
        while (arabic - 5000 >= 0){
1353
        roman += "v";
1354
        arabic -= 5000;
1355
        }
1356
        while (arabic - 4000 >= 0){
1357
        roman += "Mv";
1358
        arabic -= 4000;
1359
        }
1360
        while (arabic - 1000 >= 0){
1361
        roman += "M";
1362
        arabic -= 1000;
1363
        }
1364
        while (arabic - 900 >= 0){
1365
        roman += "CM";
1366
        arabic -= 900;
1367
        }
1368
        while (arabic - 500 >= 0){
1369
        roman += "D";
1370
        arabic -= 500;
1371
        }
1372
        while (arabic - 400 >= 0){
1373
        roman += "CD";
1374
        arabic -= 400;
1375
        }
1376
        while (arabic - 100 >= 0){
1377
        roman += "C";
1378
        arabic -= 100;
1379
        }
1380
        while (arabic - 90 >= 0){
1381
        roman += "XC";
1382
        arabic -= 90;
1383
        }
1384
        while (arabic - 50 >= 0){
1385
        roman += "L";
1386
        arabic -= 50;
1387
        }
1388
        while (arabic - 40 >= 0){
1389
        roman += "XL";
1390
        arabic -= 40;
1391
        }
1392
        while (arabic - 10 >= 0){
1393
        roman += "X";
1394
        arabic -= 10;
1395
        }
1396
        while (arabic - 9 >= 0){
1397
        roman += "IX";
1398
        arabic -= 9;
1399
        }
1400
        while (arabic - 5 >= 0){
1401
        roman += "V";
1402
        arabic -= 5;
1403
        }
1404
        while (arabic - 4 >= 0){
1405
        roman += "IV";
1406
        arabic -= 4;
1407
        }
1408
        while (arabic - 1 >= 0){
1409
        roman += "I";
1410
        arabic -= 1;
1411
        }
1412
        return roman;
3776 cbradney 1413
}
3784 cbradney 1414
 
1415
//CB Moved from scribus.cpp
1416
void parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount)
1417
{
1418
        QString tmp(pages);
1419
        QString token;
1420
        int from, to, pageNr;
1421
        do
1422
        {
1423
                if (tmp.find(",") == -1)
1424
                {
1425
                        token = tmp;
1426
                        tmp = "";
1427
                }
1428
                else
1429
                {
1430
                        token = tmp.left(tmp.find(","));
1431
                        tmp = tmp.right(tmp.length() - tmp.find(",") - 1);
1432
                }
1433
 
1434
                token = token.stripWhiteSpace();
1435
                if (token == "*") // Import all source doc pages
1436
                {
1437
                        for (int i = 1; i <= sourcePageCount; ++i)
1438
                                pageNs->push_back(i);
1439
                }
1440
                else if (token.find("-") != -1) // import a range of source doc pages
1441
                {
1442
                        from = QString(token.left(token.find("-"))).toInt();
1443
                        to = QString(token.right(token.length() - token.find("-") - 1)).toInt();
1444
                        if ((from != 0) && (to != 0))
1445
                        {
1446
                                if (from > sourcePageCount)
1447
                                        from = sourcePageCount;
1448
                                if (to > sourcePageCount)
1449
                                        to = sourcePageCount;
1450
                                if (from == to)
1451
                                        pageNs->push_back(to);
1452
                                else if (from < to)
1453
                                {
1454
                                        for (int i = from; i <= to; ++i)
1455
                                                pageNs->push_back(i);
1456
                                }
1457
                                else
1458
                                {
1459
                                        for (int i = from; i >= to; --i)
1460
                                                pageNs->push_back(i);
1461
                                }
1462
                        }
1463
                }
1464
                else // import single source doc page
1465
                {
1466
                        pageNr = token.toInt();
1467
                        if ((pageNr > 0) && (pageNr <= sourcePageCount))
1468
                                pageNs->push_back(pageNr);
1469
                }
1470
        } while (!tmp.isEmpty());
3793 cbradney 1471
}
5184 avox 1472
 
1473
 
1474
int findParagraphStyle(ScribusDoc* doc, const ParagraphStyle& parStyle)
1475
{
1476
        bool named = !parStyle.name().isEmpty();
1477
//qDebug(QString("looking up %1/ %2").arg(parStyle.name()).arg(parStyle.alignment())); 
1478
        if (named) {
1479
                for (uint i=0; i < doc->docParagraphStyles.size(); ++i)
1480
                {
1481
//qDebug(QString("%1 %2").arg(i).arg(doc->docParagraphStyles[i].name()));
1482
                        if (parStyle.name() == doc->docParagraphStyles[i].name()) {
1483
                                return i;
1484
                        }
1485
                }
1486
                assert(false);
1487
                return -1;
1488
        }
1489
        else {
1490
                return parStyle.alignment();
1491
        }
1492
}