Subversion Repositories Scribus

Rev

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