Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
4777 avox 1
//FIXME: this include must go to sctextstruct.h !
2
#include <qvaluelist.h>
5105 mrdocs 3
#include <cassert>  //added to make Fedora-5 happy
4669 avox 4
#include "fpoint.h"
5
#include "sctextstruct.h"
6
#include "storytext.h"
7
#include "scribus.h"
8
#include "scfonts.h"
5184 avox 9
#include "util.h"
4669 avox 10
 
11
 
12
QChar SpecialChars::OBJECT     = QChar(25);
13
QChar SpecialChars::TAB        = QChar(9);
14
QChar SpecialChars::PARSEP     = QChar(13);
15
QChar SpecialChars::LINEBREAK  = QChar(28);
16
QChar SpecialChars::COLBREAK   = QChar(26);
17
QChar SpecialChars::FRAMEBREAK = QChar(27);
18
QChar SpecialChars::SHYPHEN;
19
QChar SpecialChars::NBHYPHEN   = QChar(24);
20
QChar SpecialChars::NBSPACE    = QChar(29);
21
QChar SpecialChars::ZWNBSPACE;
22
QChar SpecialChars::ZWSPACE;
23
//QChar SpecialChars::SPACE      = QChar(32);
24
 
5753 jghali 25
class ScText_Shared : public QPtrList<ScText>
26
{
27
public:
5721 avox 28
        ParagraphStyle defaultStyle;
29
        uint refs;
5722 avox 30
        uint len;
31
        ScText_Shared() : QPtrList<ScText>(), defaultStyle(), refs(1), len(0)
5721 avox 32
        {
33
                setAutoDelete(true);
34
        }
35
};
4669 avox 36
 
37
 
38
StoryText::StoryText(ScribusDoc * doc_) : doc(doc_)
39
{
5721 avox 40
        d = new ScText_Shared();
4669 avox 41
        clear();
42
}
43
 
5721 avox 44
StoryText::StoryText(const StoryText & other) : doc(other.doc)
4669 avox 45
{
5721 avox 46
        d = other.d;
47
        d->refs++;
48
 
4706 avox 49
        selFirst = 0;
50
        selLast = -1;
51
 
52
        firstFrameItem = 0;
53
        lastFrameItem = -1;
5721 avox 54
 
4669 avox 55
        invalidateLayout();
56
}
57
 
58
StoryText::~StoryText()
59
{
5721 avox 60
        d->refs--;
61
        if (d->refs == 0) {
5773 avox 62
                for (ScText *it = d->first(); it != 0; it = d->next())
63
                {
64
                        if ((it->ch[0] == SpecialChars::OBJECT) && (it->cembedded != 0)) {
65
                                doc->FrameItems.remove(it->cembedded);
66
                                delete it->cembedded;
67
                                it->cembedded = 0;
68
                        }
69
                        else if ((it->ch[0] == SpecialChars::PARSEP)) {
70
                                delete it->parstyle;
71
                                it->parstyle = 0;
72
                        }
73
                }
74
 
75
                d->clear();
76
                d->len = 0;
5721 avox 77
                delete d;
78
        }      
4669 avox 79
}
80
 
81
StoryText& StoryText::operator= (const StoryText & other)
82
{
5721 avox 83
        d->refs--;
84
        if (d->refs == 0) {
85
                clear();
86
                delete d;
87
        }
88
 
89
        doc = other.doc;
90
        d = other.d;
91
        d->refs++;
92
 
4706 avox 93
        selFirst = 0;
94
        selLast = -1;
95
 
96
        firstFrameItem = 0;
97
        lastFrameItem = -1;
98
 
4669 avox 99
        invalidateLayout();
100
        return *this;
101
}
102
 
103
 
104
void StoryText::clear()
105
{
106
        selFirst = 0;
107
        selLast = -1;
108
 
109
        firstFrameItem = 0;
110
        lastFrameItem = -1;
111
 
5721 avox 112
        d->defaultStyle = ParagraphStyle();
113
        d->defaultStyle.setParent( & doc->docParagraphStyles[0]);
5777 avox 114
        d->defaultStyle.charStyle().setParent( & doc->docParagraphStyles[0].charStyle());
5569 avox 115
 
5721 avox 116
        for (ScText *it = d->first(); it != 0; it = d->next())
4749 avox 117
        {
5721 avox 118
                if ((it->ch[0] == SpecialChars::OBJECT) && (it->cembedded != 0)) {
4749 avox 119
                        doc->FrameItems.remove(it->cembedded);
5184 avox 120
                        delete it->cembedded;
4749 avox 121
                        it->cembedded = 0;
122
                }
5721 avox 123
                else if ((it->ch[0] == SpecialChars::PARSEP)) {
124
                        delete it->parstyle;
125
                        it->parstyle = 0;
126
                }
4749 avox 127
        }
128
 
5721 avox 129
        d->clear();
5722 avox 130
        d->len = 0;
4669 avox 131
        invalidateAll();
132
}
133
 
134
 
5732 avox 135
void StoryText::append(const StoryText& other)
136
{
137
        CharStyle cstyle(charStyle(length()));
138
        ParagraphStyle pstyle(paragraphStyle(length()));
139
        int cstyleStart = length();
140
        for (int i=0; i < other.length(); ++i) {
141
                if (other.charStyle(i) == cstyle)
142
                        continue;
143
                int pos = length();
144
                int len = i - cstyleStart;
145
                if (len > 0) {
146
                        insertChars(length(), other.text(cstyleStart, len));
147
                        applyCharStyle(pos, len, cstyle);
148
                }
149
                if (other.text(i) == SpecialChars::PARSEP) {
150
                        insertChars(pos+len, SpecialChars::PARSEP);
151
                        applyStyle(pos+len, other.paragraphStyle(i));
152
                        cstyleStart = i+1;
153
                }
154
                else {
155
                        cstyle = other.charStyle(i);
156
                        cstyleStart = i;
157
                }
158
        }
159
        int pos = length();
160
        int len = other.length() - cstyleStart;
161
        if (len > 0) {
162
                insertChars(length(), other.text(cstyleStart, len));
163
                applyCharStyle(pos, len, cstyle);
164
        }
165
        setDefaultStyle(other.defaultStyle());
166
}
167
 
168
 
169
 
5721 avox 170
/**
5778 avox 171
     A CharStyle's parent is usually the charstyle of default paragraphstyle,
172
     unless explicitly changed. This routines makes sure that all parent pointers
173
     to the default paragraphStyle's charstyle are up-to-date
5721 avox 174
 */
5776 avox 175
static void replaceParentStyle(StoryText* that, int pos, const CharStyle* oldP, const CharStyle* newP)
5721 avox 176
{
177
        for(int i = pos-1; i >= 0; ++i) {
178
                ScText* it = that->item(i);
179
                if (it->ch[0] == SpecialChars::PARSEP)
180
                        break;
181
                else if (it->parent() == NULL || it->parent() == oldP)
182
                        it->setParent(newP);
183
        }      
184
}
185
 
186
 
187
/**
188
    Make sure that the paragraph CharStyle's point to the new ParagraphStyle
189
 */
190
static void insertParSep(StoryText* that, int pos)
191
{
192
        ScText* it = that->item(pos);
5776 avox 193
        const ParagraphStyle& pstyle(that->paragraphStyle(pos));
5778 avox 194
        if(!it->parstyle)
195
                it->parstyle = new ParagraphStyle(pstyle);
5776 avox 196
        const CharStyle* oldP = & pstyle.charStyle();
197
        const CharStyle* newP = & it->parstyle->charStyle();
5721 avox 198
        replaceParentStyle(that, pos, oldP, newP);
199
}
200
/**
201
     need to remove the ParagraphStyle structure and replace all pointers
202
     to it...
203
 */
204
static void removeParSep(StoryText* that, int pos)
205
{
206
        ScText* it = that->item(pos);
207
        if (it->parstyle) {
5776 avox 208
                const CharStyle* oldP = & it->parstyle->charStyle();
209
                const CharStyle* newP = & that->paragraphStyle(pos+1).charStyle();
5721 avox 210
                replaceParentStyle(that, pos, oldP, newP);
5778 avox 211
                delete it->parstyle;
5721 avox 212
        }
213
}
214
 
4669 avox 215
void StoryText::removeChars(int pos, uint len)
216
{
217
        if (pos < 0)
218
                pos += length();
219
 
220
        assert( len > 0 );
221
        assert( pos >= 0 );
222
        assert( pos + static_cast<int>(len) <= length() );
4749 avox 223
 
5751 avox 224
        for ( int i=pos + static_cast<int>(len) - 1; i >= pos; --i )
4749 avox 225
        {
5721 avox 226
                ScText *it = d->at(i);
227
                if ((it->ch[0] == SpecialChars::OBJECT) && (it->cembedded != 0)) {
4749 avox 228
                        doc->FrameItems.remove(it->cembedded);
229
                        it->cembedded = 0;
230
                }
5721 avox 231
                else if ((it->ch[0] == SpecialChars::PARSEP)) {
232
                        removeParSep(this, i);
233
                }
5751 avox 234
//              qDebug("remove char %d at %d", it->ch[0].unicode(), i);
5721 avox 235
                d->take(i);
5722 avox 236
                d->len--;
4749 avox 237
                delete it;
238
        }
5722 avox 239
 
240
        d->len = d->count();
4749 avox 241
        invalidate(pos, -1);
4669 avox 242
}
243
 
4749 avox 244
void StoryText::insertChars(int pos, QString txt) //, const CharStyle&
4669 avox 245
{
246
        if (pos < 0)
247
                pos += length();
248
 
249
        assert(pos >= 0);
250
        assert(pos <= length());
4749 avox 251
 
5365 avox 252
        if (txt.length() == 0)
253
                return;
254
 
5569 avox 255
        const CharStyle style = pos == 0 ? defaultStyle().charStyle() : charStyle(pos - 1);
5691 avox 256
        assert(style.font() != NULL);
5291 avox 257
 
5721 avox 258
//      const int paraStyle = pos == 0 ? 0 : at(pos - 1)->cab;
4749 avox 259
 
4752 avox 260
        for (uint i = 0; i < txt.length(); ++i) {
4749 avox 261
                ScText * item = new ScText();
262
                item->ch= txt.mid(i, 1);
263
                *static_cast<CharStyle *>(item) = style;
5721 avox 264
                d->insert(pos + i, item);
5722 avox 265
                d->len++;
5721 avox 266
                if (item->ch[0] == SpecialChars::PARSEP) {
267
//                      qDebug(QString("new PARSEP %2 at %1").arg(pos).arg(paragraphStyle(pos).name()));
268
                        insertParSep(this, pos + i);
269
                }
4749 avox 270
        }
271
 
5722 avox 272
        d->len = d->count();
4669 avox 273
        invalidate(pos, pos + txt.length());
274
}
275
 
276
void StoryText::replaceChar(int pos, QChar ch)
277
{
278
        if (pos < 0)
279
                pos += length();
280
 
281
        assert(pos >= 0);
282
        assert(pos < length());
283
 
5721 avox 284
        ScText* item = d->at(pos);
285
        if (item->ch[0] == ch)
286
                return;
287
 
288
        if (d->at(pos)->ch[0] == SpecialChars::PARSEP) {
289
                removeParSep(this, pos);
290
        }
291
        item->ch = ch;
292
        if (d->at(pos)->ch[0] == SpecialChars::PARSEP) {
293
                insertParSep(this, pos);
294
        }
295
 
4669 avox 296
        invalidate(pos, pos + 1);
297
}
298
 
5559 avox 299
void StoryText::hyphenateWord(int pos, uint len, char* hyphens)
300
{
301
        assert(pos >= 0);
5691 avox 302
        assert(pos + signed(len) <= length());
5559 avox 303
 
5691 avox 304
        for (int i=pos; i < pos+signed(len); ++i)
5569 avox 305
                if(hyphens && hyphens[i] & 1)
5721 avox 306
                        d->at(i)->setEffects(d->at(i)->effects() | ScStyle_HyphenationPossible);
5559 avox 307
                else
5721 avox 308
                        d->at(i)->setEffects(d->at(i)->effects() & ~ScStyle_HyphenationPossible);
5559 avox 309
 
310
        invalidate(pos, pos + len);
311
}
312
 
4669 avox 313
void StoryText::insertObject(int pos, PageItem* ob)
314
{
315
        if (pos < 0)
316
                pos += length();
317
 
318
        insertChars(pos, SpecialChars::OBJECT);
5721 avox 319
        const_cast<StoryText *>(this)->d->at(pos)->cembedded = ob;
4669 avox 320
}
321
 
322
 
323
int StoryText::length() const
324
{
5722 avox 325
        return d->len;
4669 avox 326
}
327
 
328
QChar StoryText::text(int pos) const
329
{
330
        if (pos < 0)
331
                pos += length();
332
 
333
        assert(pos >= 0);
334
        assert(pos < length());
335
 
5721 avox 336
        return const_cast<StoryText *>(this)->d->at(pos)->ch[0];
4669 avox 337
}
338
 
339
QString StoryText::text(int pos, uint len) const
340
{
341
        if (pos < 0)
342
                pos += length();
343
 
344
        assert(len > 0);
345
        assert(pos >= 0);
346
        assert(pos + signed(len) <= length());
347
 
348
        QString result;
5721 avox 349
        StoryText* that(const_cast<StoryText*>(this));
350
        that->d->at(pos);
351
        for (int i = pos; i < pos+signed(len); ++i) {
352
                result += that->d->current()->ch;
353
                that->d->next();
354
        }
4669 avox 355
 
356
        return result;
357
}
358
 
359
PageItem* StoryText::object(int pos) const
360
{
361
        if (pos < 0)
362
                pos += length();
363
 
364
        assert(pos >= 0);
365
        assert(pos < length());
366
 
367
        StoryText* that = const_cast<StoryText *>(this);       
5721 avox 368
        if (that->d->at(pos)->cembedded != NULL)
369
                return that->d->at(pos)->cembedded;
4669 avox 370
        else
371
                return NULL;
372
}
373
 
374
 
375
const CharStyle & StoryText::charStyle(int pos) const
376
{
377
        if (pos < 0)
378
                pos += length();
379
 
380
        assert(pos >= 0);
5732 avox 381
        assert(pos <= length());
4669 avox 382
 
5732 avox 383
        if (length() == 0)
384
                return defaultStyle().charStyle();
385
        else if (pos == length())
386
                --pos;
387
 
4669 avox 388
        StoryText* that = const_cast<StoryText *>(this);
5721 avox 389
        return dynamic_cast<const CharStyle &> (*that->d->at(pos));
4669 avox 390
}
391
 
392
const ParagraphStyle & StoryText::paragraphStyle(int pos) const
393
{
394
        if (pos < 0)
395
                pos += length();
396
 
397
        assert(pos >= 0);
5721 avox 398
        assert(pos <= length());
4669 avox 399
 
5192 avox 400
        StoryText * that = const_cast<StoryText *> (this);
5721 avox 401
//      assert( that->at(pos)->cab >= 0 );
402
//      assert( that->at(pos)->cab < doc->docParagraphStyles.count() );
403
//      return doc->docParagraphStyles[that->at(pos)->cab];
404
 
405
        that->d->at(pos);
406
        while (pos < length() && that->d->current()->ch[0] != SpecialChars::PARSEP) {
407
                ++pos;
408
                that->d->next();
409
        }
5778 avox 410
        if (pos == length()) {
411
//              qDebug(QString("using default parstyle at end (%1)").arg(pos));
412
                return that->d->defaultStyle;
413
        }
5721 avox 414
        else if ( !that->d->current()->parstyle ) {
5778 avox 415
                qDebug(QString("inserting default parstyle at %1").arg(pos));
5721 avox 416
                that->d->current()->parstyle = new ParagraphStyle(defaultStyle());
417
        }
5778 avox 418
        else {
419
//              qDebug(QString("using parstyle at %1").arg(pos));
420
        }
5721 avox 421
        return *that->d->current()->parstyle;
4669 avox 422
}
423
 
5559 avox 424
const ParagraphStyle& StoryText::defaultStyle() const
425
{
5721 avox 426
        return d->defaultStyle;
5559 avox 427
}
428
 
5569 avox 429
 
430
void StoryText::setDefaultStyle(const ParagraphStyle& style)
431
{
5721 avox 432
        d->defaultStyle = style;
433
        if (!d->defaultStyle.parent())
434
                d->defaultStyle.setParent( & doc->docParagraphStyles[0] );
5777 avox 435
        if (!d->defaultStyle.charStyle().parent())
436
                d->defaultStyle.charStyle().setParent( & doc->docParagraphStyles[0].charStyle() );
5569 avox 437
}
438
 
439
 
440
 
5721 avox 441
void StoryText::applyCharStyle(int pos, uint len, const CharStyle& style )
4669 avox 442
{
443
        if (pos < 0)
444
                pos += length();
445
 
446
        assert(pos >= 0);
447
        assert(pos + signed(len) <= length());
448
 
449
        if (len == 0)
450
                return;
451
 
5721 avox 452
        d->at(pos);
453
        for (uint i=pos; i < pos+len; ++i) {
454
                d->current()->applyCharStyle(style);
455
                d->next();
456
        }
4669 avox 457
 
458
        invalidate(pos, pos + len);
459
}
460
 
5773 avox 461
 
462
 
463
void StoryText::eraseCharStyle(int pos, uint len, const CharStyle& style )
464
{
465
        if (pos < 0)
466
                pos += length();
467
 
468
        assert(pos >= 0);
469
        assert(pos + signed(len) <= length());
470
 
471
        if (len == 0)
472
                return;
473
 
474
        d->at(pos);
475
        for (uint i=pos; i < pos+len; ++i) {
476
                d->current()->eraseCharStyle(style);
477
                d->next();
478
        }
479
 
480
        invalidate(pos, pos + len);
481
}
482
 
483
 
4669 avox 484
void StoryText::applyStyle(int pos, const ParagraphStyle& style)
485
{
486
        if (pos < 0)
487
                pos += length();
488
 
489
        assert(pos >= 0);
5721 avox 490
        assert(pos <= length());
4669 avox 491
 
5721 avox 492
/*      int paraStyle = QMAX(0, findParagraphStyle(doc, style)); //FIXME:NLS
5184 avox 493
        int i = pos - 1;
5721 avox 494
        if (length() > 0) {
495
                // find start of para
496
                while (i >= 0 && at(i)->ch[0] != SpecialChars::PARSEP) {
497
                        --i;
498
                }
499
                // set 'cab' field
500
                do {
501
                        ++i;
502
                        at(i)->cab = paraStyle;
503
                }
504
                while (i+1 < length() && d->at(i)->ch[0] != SpecialChars::PARSEP);
505
        }
506
        ++i; */
507
 
508
        int i = pos;
509
        while (i < length() && d->at(i)->ch[0] != SpecialChars::PARSEP) {
5184 avox 510
                ++i;
511
        }
5721 avox 512
        if (i < length()) {
513
                if (!d->at(i)->parstyle) {
514
                        qDebug(QString("PARSEP without style at pos %1").arg(i));
515
                        d->at(i)->parstyle = new ParagraphStyle(defaultStyle());
516
                }
517
//              qDebug(QString("applying parstyle %2 at %1 for %3").arg(i).arg(paragraphStyle(pos).name()).arg(pos));
518
                d->at(i)->parstyle->applyStyle(style);
519
                if (!d->at(i)->parstyle->parent()) {
520
                        d->at(i)->parstyle->setParent( & d->defaultStyle );
521
                }
5777 avox 522
                if (!d->at(i)->parstyle->charStyle().parent()) {
523
                        d->at(i)->parstyle->charStyle().setParent( & d->defaultStyle.charStyle() );
524
                }
5721 avox 525
        }
526
        else {
527
                // not happy about this but inserting a new PARSEP makes more trouble
528
//              qDebug(QString("applying parstyle %1 as defaultstyle for %2").arg(paragraphStyle(pos).name()).arg(pos));
529
                d->defaultStyle.applyStyle(style);
530
        }
4669 avox 531
}
532
 
5773 avox 533
void StoryText::eraseStyle(int pos, const ParagraphStyle& style)
534
{
535
        if (pos < 0)
536
                pos += length();
537
 
538
        assert(pos >= 0);
539
        assert(pos <= length());
540
 
541
        int i = pos;
542
        while (i < length() && d->at(i)->ch[0] != SpecialChars::PARSEP) {
543
                ++i;
544
        }
545
        if (i < length()) {
546
                if (!d->at(i)->parstyle) {
547
                        qDebug(QString("PARSEP without style at pos %1").arg(i));
548
                        d->at(i)->parstyle = new ParagraphStyle(defaultStyle());
549
                }
550
                //              qDebug(QString("applying parstyle %2 at %1 for %3").arg(i).arg(paragraphStyle(pos).name()).arg(pos));
551
                d->at(i)->parstyle->eraseStyle(style);
552
                if (!d->at(i)->parstyle->parent()) {
553
                        d->at(i)->parstyle->setParent( & d->defaultStyle );
554
                }
5777 avox 555
                if (!d->at(i)->parstyle->charStyle().parent()) {
556
                        d->at(i)->parstyle->charStyle().setParent( & d->defaultStyle.charStyle() );
557
                }
5773 avox 558
        }
559
        else {
560
                // not happy about this but inserting a new PARSEP makes more trouble
561
                //              qDebug(QString("applying parstyle %1 as defaultstyle for %2").arg(paragraphStyle(pos).name()).arg(pos));
562
                d->defaultStyle.eraseStyle(style);
563
        }
564
}
565
 
566
 
4669 avox 567
uint StoryText::nrOfParagraphs() const
568
{
569
        uint result = 0;
5721 avox 570
        StoryText* that = const_cast<StoryText *>(this);
571
        that->d->at(0);
572
        for (int i=0; i < length(); ++i) {
573
                if (that->d->current()->ch[0] == SpecialChars::PARSEP)
4669 avox 574
                        ++result;
5721 avox 575
                that->d->next();
576
        }
4669 avox 577
        return result;
578
}
579
 
580
int StoryText::startOfParagraph(uint index) const
581
{
582
        if (index == 0)
583
                return 0;
584
 
5184 avox 585
        StoryText* that = const_cast<StoryText *>(this);
5721 avox 586
        that->d->at(0);
587
        for (int i=0; i < length(); ++i) {
588
                if (that->d->current()->ch[0] == SpecialChars::PARSEP && ! --index)
4669 avox 589
                        return i + 1;
5721 avox 590
                that->d->next();
591
        }
4669 avox 592
        return -1;
593
}
594
 
595
int StoryText::endOfParagraph(uint index) const
596
{
597
        ++index;
5184 avox 598
        StoryText* that = const_cast<StoryText *>(this);
5721 avox 599
        that->d->at(0);
600
        for (int i=0; i < length(); ++i) {
601
                if (that->d->current()->ch[0] == SpecialChars::PARSEP && ! --index)
602
                        return i;
603
                that->d->next();
604
        }
4669 avox 605
        return length();
606
}
607
 
608
uint StoryText::nrOfRuns() const
609
{
5464 avox 610
        return length();
4669 avox 611
}
612
 
613
int StoryText::startOfRun(uint index) const
614
{
5464 avox 615
        return index;
4669 avox 616
}
617
 
618
int StoryText::endOfRun(uint index) const
619
{
5464 avox 620
        return index + 1;
4669 avox 621
}
622
 
623
 
624
// selection
625
 
626
int StoryText::startOfSelection() const
627
{
628
        return selFirst <= selLast? selFirst : 0;
629
}
630
 
631
int StoryText::endOfSelection() const
632
{
633
        return selFirst <= selLast? selLast + 1 : -1;
634
}
635
 
636
int StoryText::lengthOfSelection() const
637
{
638
        return selFirst <= selLast? selLast - selFirst + 1 : 0;
639
}
640
 
641
 
642
bool StoryText::selected(int pos) const
643
{
4749 avox 644
        return (selFirst <= pos && pos <= selLast)
5721 avox 645
//             || (pos >= 0 && pos < length() && const_cast<StoryText*>(this)->d->at(pos)->cselect)
646
        ;
4669 avox 647
}
648
 
649
void StoryText::select(int pos, uint len, bool on)
650
{
651
        if (pos < 0)
652
                pos += length();
653
 
654
        assert( pos >= 0 );
655
        assert( pos + signed(len) <= length() );
656
 
5751 avox 657
//      qDebug("old selection: %d - %d", selFirst, selLast);
658
 
5721 avox 659
//      StoryText* that = const_cast<StoryText *>(this);
660
//      for (int i=pos; i < pos+signed(len); ++i)
661
//              that->at(i)->cselect = on;
4669 avox 662
 
663
        if (on) {
664
                // extend if possible
665
                if (selected(pos - 1))
666
                        selLast = QMAX(selLast, pos + static_cast<int>(len) - 1);
667
                else if (selected(pos + len))
668
                        selFirst = QMIN(selFirst, pos);
669
                else {
670
                        selFirst = pos;
671
                        selLast = pos + len - 1;
672
                }
673
        }
674
        else {
675
                if (pos <= selFirst && selLast < pos + signed(len))
676
                        deselectAll();
677
                // shrink
678
                else if (!selected(pos - 1) && selected(pos + len - 1))
679
                        selFirst = pos + len;
680
                else if (selected(pos) && !selected(pos + len))
681
                        selLast = pos - 1;
682
                else if (selected(pos) || selected(pos + len - 1))
683
                        // Grr, deselection splits selection
684
                        selLast = pos - 1;
685
        }
5751 avox 686
 
687
//      qDebug("new selection: %d - %d", selFirst, selLast);
4669 avox 688
}
689
 
690
void StoryText::selectAll()
691
{
5721 avox 692
/*      StoryText* that = const_cast<StoryText *>(this);
693
        that->at(0);
694
        for (int i=0; i < length(); ++i) {
695
                that->current()->cselect = true;
696
                that->next();
697
        }
698
*/
4669 avox 699
        selFirst = 0;
700
        selLast = length() - 1;
701
}
702
 
703
void StoryText::deselectAll()
704
{
5721 avox 705
/*      StoryText* that = const_cast<StoryText *>(this);
706
        that->at(0);
707
        for (int i=0; i < length(); ++i) {
708
                that->current()->cselect = false;
709
                that->next();
710
        }
711
*/     
4669 avox 712
        selFirst = 0;
713
        selLast = -1;
714
}
715
 
716
void StoryText::removeSelection()
717
{
5751 avox 718
//      qDebug("removeSelection: %d - %d", selFirst, selLast);
4669 avox 719
        if (selFirst > selLast)
720
                return;
721
 
722
        assert( selFirst >= 0 );
723
        assert( selLast < length() );
724
 
725
        removeChars(selFirst, selLast - selFirst+1);
726
        deselectAll();
727
}
728
 
729
 
730
 
731
void StoryText::invalidateObject(const PageItem * embedded)
732
{
733
}
734
 
735
void StoryText::invalidateLayout()
736
{
737
}
738
 
739
void StoryText::invalidateAll()
740
{
741
}
742
 
4749 avox 743
void StoryText::invalidate(int firstitem, int lastitem)
4669 avox 744
{
745
}
746
 
747
 
748
// physical view
749
 
750
/*
751
void StoryText::validate()
752
{
753
        static bool withinValidate = false;
754
 
755
        assert( !withinValidate );
756
        withinValidate = true;
757
 
758
        withinValidate = false;
759
}
760
*/
761
 
762
int StoryText::screenToPosition(FPoint coord) const
763
{
764
//FIXME:NLS     
765
        //FIXME: should be end of lastFrameItem
766
        return length();
767
}
768
 
769
 
770
FPoint StoryText::boundingBox(int pos, uint len) const
771
{
772
        return FPoint(); //FIXME
773
}
774
 
775
 
776
int StoryText::layout(int startItem)
777
{
778
        //FIXME:NLS
779
        return -1;
780
}
781
 
782
 
783
uint StoryText::nrOfItems() const
784
{
785
        return length();
786
}
787
 
788
 
789
ScText*  StoryText::item(uint itm)
790
{
791
        assert( static_cast<int>(itm) < length() );
5721 avox 792
        return const_cast<StoryText *>(this)->d->at(itm);
4669 avox 793
}
794
 
795
const QString StoryText::itemText(uint itm) const
796
{
797
 
798
        assert( static_cast<int>(itm) < length() );
799
 
800
        return text(itm, 1);
801
}
802
 
803
 
804
const CharStyle StoryText::itemStyle(uint itm) const
805
{
806
        assert( static_cast<int>(itm) < length() );
807
 
808
        return charStyle(itm);
809
}
810
 
811
 
812
int StoryText::startOfItem(uint itm) const
813
{
814
        assert( static_cast<int>(itm) < length() );
815
 
816
        return itm;
817
}
818
 
819
int StoryText::endOfItem(uint itm) const
820
{
821
        assert( static_cast<int>(itm) < length() );
822
 
823
        return itm + 1;
824
}
825