~ubuntu-branches/ubuntu/breezy/koffice/breezy

« back to all changes in this revision

Viewing changes to lib/kformula/sequenceelement.cc

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include <math.h>
23
23
 
24
24
#include <qpainter.h>
 
25
#include <qpaintdevice.h>
 
26
#include <qvaluestack.h>
25
27
 
 
28
#include <kcommand.h>
26
29
#include <kdebug.h>
27
 
 
 
30
#include <klocale.h>
 
31
 
 
32
//#include <boost/spirit.hpp>
 
33
 
 
34
#include "MatrixDialog.h"
28
35
#include "bracketelement.h"
 
36
#include "creationstrategy.h"
29
37
#include "elementtype.h"
 
38
#include "elementvisitor.h"
30
39
#include "formulacursor.h"
31
40
#include "formulaelement.h"
32
41
#include "fractionelement.h"
33
42
#include "indexelement.h"
 
43
#include "kformulacommand.h"
 
44
#include "kformulacontainer.h"
 
45
#include "kformuladocument.h"
34
46
#include "matrixelement.h"
35
47
#include "rootelement.h"
36
48
#include "sequenceelement.h"
37
49
#include "sequenceparser.h"
 
50
#include "spaceelement.h"
38
51
#include "symbolelement.h"
 
52
#include "symboltable.h"
39
53
#include "textelement.h"
40
54
 
 
55
#include <assert.h>
41
56
 
42
57
KFORMULA_NAMESPACE_BEGIN
43
 
using namespace std;
 
58
//using namespace std;
 
59
 
 
60
ElementCreationStrategy* SequenceElement::creationStrategy = 0;
 
61
 
 
62
void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy )
 
63
{
 
64
    creationStrategy = strategy;
 
65
}
44
66
 
45
67
 
46
68
SequenceElement::SequenceElement(BasicElement* parent)
47
69
        : BasicElement(parent), parseTree(0), textSequence(true)
48
70
{
 
71
    assert( creationStrategy != 0 );
49
72
    children.setAutoDelete(true);
50
73
}
51
74
 
55
78
    delete parseTree;
56
79
}
57
80
 
 
81
SequenceElement::SequenceElement( const SequenceElement& other )
 
82
    : BasicElement( other )
 
83
{
 
84
    children.setAutoDelete(true);
 
85
    uint count = other.children.count();
 
86
    for (uint i = 0; i < count; i++) {
 
87
        BasicElement* child = children.at(i)->clone();
 
88
        child->setParent( this );
 
89
        children.append( child );
 
90
    }
 
91
}
 
92
 
 
93
 
 
94
bool SequenceElement::accept( ElementVisitor* visitor )
 
95
{
 
96
    return visitor->visit( this );
 
97
}
 
98
 
 
99
 
 
100
bool SequenceElement::readOnly( const FormulaCursor* ) const
 
101
{
 
102
    return getParent()->readOnly( this );
 
103
}
 
104
 
58
105
 
59
106
/**
60
107
 * Returns the element the point is in.
61
108
 */
62
 
BasicElement* SequenceElement::goToPos(FormulaCursor* cursor, bool& handled,
63
 
                                       const KoPoint& point, const KoPoint& parentOrigin)
 
109
BasicElement* SequenceElement::goToPos( FormulaCursor* cursor, bool& handled,
 
110
                                        const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
64
111
{
65
112
    BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
66
113
    if (e != 0) {
67
 
        KoPoint myPos(parentOrigin.x() + getX(),
68
 
                     parentOrigin.y() + getY());
 
114
        LuPixelPoint myPos(parentOrigin.x() + getX(),
 
115
                           parentOrigin.y() + getY());
69
116
 
70
117
        uint count = children.count();
71
118
        for (uint i = 0; i < count; i++) {
74
121
            if (e != 0) {
75
122
                if (!handled) {
76
123
                    handled = true;
77
 
                    if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()/2)) {
 
124
                    if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) {
78
125
                        cursor->setTo(this, children.find(e));
79
126
                    }
80
127
                    else {
85
132
            }
86
133
        }
87
134
 
88
 
        double dx = point.x() - myPos.x();
 
135
        luPixel dx = point.x() - myPos.x();
89
136
        //int dy = point.y() - myPos.y();
90
137
 
91
138
        for (uint i = 0; i < count; i++) {
92
139
            BasicElement* child = children.at(i);
93
140
            if (dx < child->getX()) {
94
 
                if (i > 0) {
95
 
                    cursor->setTo(this, i-1);
96
 
                    handled = true;
97
 
                    return children.at(i-1);
98
 
                }
99
 
                else {
100
 
                    break;
101
 
                }
 
141
                cursor->setTo( this, i );
 
142
                handled = true;
 
143
                return children.at( i );
102
144
            }
103
145
        }
104
146
 
127
169
 * Calculates our width and height and
128
170
 * our children's parentPosition.
129
171
 */
130
 
void SequenceElement::calcSizes(const ContextStyle& context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle)
 
172
void SequenceElement::calcSizes(const ContextStyle& style,
 
173
                                ContextStyle::TextStyle tstyle,
 
174
                                ContextStyle::IndexStyle istyle)
131
175
{
132
176
    if (!isEmpty()) {
133
 
        double mySize = context.getAdjustedSize( tstyle );
134
 
        double width = 0;
135
 
        double toBaseline = 0;
136
 
        double fromBaseline = 0;
137
 
 
138
 
        QFont font = context.getDefaultFont();
139
 
        font.setPointSizeFloat(mySize);
140
 
        QFontMetrics fm(font);
141
 
        double fromMidline = fm.strikeOutPos();
142
 
 
143
 
        //uint count = children.count();
 
177
        luPixel width = 0;
 
178
        luPixel toBaseline = 0;
 
179
        luPixel fromBaseline = 0;
144
180
 
145
181
        // Let's do all normal elements that have a base line.
146
 
        QListIterator<BasicElement> it( children );
 
182
        QPtrListIterator<BasicElement> it( children );
147
183
        for ( ; it.current(); ++it ) {
148
184
            BasicElement* child = it.current();
149
185
 
150
 
            double spaceBefore = 0;
 
186
            luPixel spaceBefore = 0;
151
187
            if ( isFirstOfToken( child ) ) {
152
 
                spaceBefore = child->getElementType()->getSpaceBefore( context, tstyle );
 
188
                spaceBefore =
 
189
                    style.ptToPixelX( child->getElementType()->getSpaceBefore( style,
 
190
                                                                               tstyle ) );
153
191
            }
154
192
 
155
193
            if ( !child->isInvisible() ) {
156
 
                child->calcSizes( context, tstyle, istyle );
 
194
                child->calcSizes( style, tstyle, istyle );
157
195
                child->setX( width + spaceBefore );
158
196
                width += child->getWidth() + spaceBefore;
159
197
 
160
 
                if ( child->getBaseline() > -1 ) {
161
 
                    toBaseline = QMAX( toBaseline, child->getBaseline() );
162
 
                    fromBaseline = QMAX( fromBaseline, child->getHeight()-child->getBaseline() );
 
198
                luPixel childBaseline = child->getBaseline();
 
199
                if ( childBaseline > -1 ) {
 
200
                    toBaseline = QMAX( toBaseline, childBaseline );
 
201
                    fromBaseline = QMAX( fromBaseline,
 
202
                                         child->getHeight() - childBaseline );
 
203
                }
 
204
                else {
 
205
                    luPixel bl = child->getHeight()/2 + style.axisHeight( tstyle );
 
206
                    toBaseline = QMAX( toBaseline, bl );
 
207
                    fromBaseline = QMAX( fromBaseline, child->getHeight() - bl );
163
208
                }
164
209
            }
165
210
            else {
168
213
            }
169
214
        }
170
215
 
171
 
        bool noBaseline = toBaseline == 0;
172
 
 
173
 
        // Now all normal elements without a base line.
174
 
        it.toFirst();
175
 
        for ( ; it.current(); ++it ) {
176
 
            BasicElement* child = it.current();
177
 
            if (!child->isInvisible()) {
178
 
                if (child->getBaseline() == -1) {
179
 
                    toBaseline = QMAX(toBaseline, child->getMidline()+fromMidline);
180
 
                    fromBaseline = QMAX(fromBaseline, child->getHeight()-(child->getMidline()+fromMidline));
181
 
                }
182
 
            }
183
 
        }
184
 
 
185
216
        setWidth(width);
186
217
        setHeight(toBaseline+fromBaseline);
187
 
        setBaseline(noBaseline ? -1 : toBaseline);
188
 
        setMidline(toBaseline-fromMidline);
 
218
        setBaseline(toBaseline);
189
219
 
190
220
        setChildrenPositions();
191
221
    }
192
222
    else {
193
 
        double w = context.getEmptyRectWidth();
194
 
        double h = context.getEmptyRectHeight();
 
223
        luPixel w = style.getEmptyRectWidth();
 
224
        luPixel h = style.getEmptyRectHeight();
195
225
        setWidth( w );
196
226
        setHeight( h );
197
227
        setBaseline( h );
198
 
        setMidline( h*.5 );
 
228
        //setMidline( h*.5 );
199
229
    }
200
230
}
201
231
 
202
232
 
203
233
void SequenceElement::setChildrenPositions()
204
234
{
205
 
    QListIterator<BasicElement> it( children );
 
235
    QPtrListIterator<BasicElement> it( children );
206
236
    for ( ; it.current(); ++it ) {
207
237
        BasicElement* child = it.current();
208
 
        if (child->getBaseline() > -1) {
209
 
            child->setY(getBaseline() - child->getBaseline());
210
 
        }
211
 
        else {
212
 
            child->setY(getMidline() - child->getMidline());
213
 
        }
 
238
        child->setY(getBaseline() - child->getBaseline());
214
239
    }
215
240
}
216
241
 
220
245
 * The `parentOrigin' is the point this element's parent starts.
221
246
 * We can use our parentPosition to get our own origin then.
222
247
 */
223
 
void SequenceElement::draw(QPainter& painter, const QRect& r,
224
 
                           const ContextStyle& context,
225
 
                           ContextStyle::TextStyle tstyle,
226
 
                           ContextStyle::IndexStyle istyle,
227
 
                           const KoPoint& parentOrigin)
 
248
void SequenceElement::draw( QPainter& painter, const LuPixelRect& r,
 
249
                            const ContextStyle& context,
 
250
                            ContextStyle::TextStyle tstyle,
 
251
                            ContextStyle::IndexStyle istyle,
 
252
                            const LuPixelPoint& parentOrigin )
228
253
{
229
 
    KoPoint myPos(parentOrigin.x() + getX(),
230
 
                 parentOrigin.y() + getY());
231
 
    if (!QRect(myPos.x(), myPos.y(), getWidth(), getHeight()).intersects(r))
232
 
        return;
 
254
    LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
 
255
    // There might be zero sized elements that still want to be drawn at least
 
256
    // in edit mode. (EmptyElement)
 
257
    //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
 
258
    //    return;
233
259
 
234
260
    if (!isEmpty()) {
235
 
        QListIterator<BasicElement> it( children );
236
 
        for ( ; it.current(); ++it ) {
 
261
        QPtrListIterator<BasicElement> it( children );
 
262
        for ( ; it.current(); ) {
237
263
            BasicElement* child = it.current();
238
 
            if (!child->isInvisible()) {
 
264
            if (!child->isInvisible()) {
239
265
                child->draw(painter, r, context, tstyle, istyle, myPos);
240
 
            }
241
 
            // Debug
242
 
            //painter.setPen(Qt::green);
243
 
            //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(),
244
 
            //                 getWidth(), getHeight());
 
266
 
 
267
                // Each starting element draws the whole token
 
268
                // This only concerns TextElements.
 
269
                ElementType* token = child->getElementType();
 
270
                if ( token != 0 ) {
 
271
                    it += token->end() - token->start();
 
272
                }
 
273
                else {
 
274
                    ++it;
 
275
                }
 
276
            }
 
277
            else {
 
278
                ++it;
 
279
            }
245
280
        }
246
281
    }
247
 
    else if ( painter.device()->devType() != QInternal::Printer ) {
 
282
    else {
 
283
        drawEmptyRect( painter, context, myPos );
 
284
    }
 
285
    // Debug
 
286
    //painter.setPen(Qt::green);
 
287
    //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(),
 
288
    //                 getWidth(), getHeight());
 
289
//     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
 
290
//                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ),
 
291
//                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
 
292
//                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ) );
 
293
//     painter.setPen(Qt::red);
 
294
//     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
 
295
//                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ),
 
296
//                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
 
297
//                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ) );
 
298
}
 
299
 
 
300
 
 
301
void SequenceElement::dispatchFontCommand( FontCommand* cmd )
 
302
{
 
303
    QPtrListIterator<BasicElement> it( children );
 
304
    for ( ; it.current(); ++it ) {
 
305
        BasicElement* child = it.current();
 
306
        child->dispatchFontCommand( cmd );
 
307
    }
 
308
}
 
309
 
 
310
 
 
311
void SequenceElement::drawEmptyRect( QPainter& painter, const ContextStyle& context,
 
312
                                     const LuPixelPoint& upperLeft )
 
313
{
 
314
    if ( context.edit() ) {
248
315
        painter.setBrush(Qt::NoBrush);
249
 
        painter.setPen(QPen(context.getEmptyColor(), context.getLineWidth()));
250
 
        painter.drawRect(myPos.x(), myPos.y(), getWidth(), getHeight());
251
 
//         kdDebug( 40000 ) << "SequenceElement::calcCursorSize: "
252
 
//                   << myPos.x() << " " << myPos.y() << " "
253
 
//                   << getWidth() << " " << getHeight()
254
 
//                   << endl;
 
316
        painter.setPen( QPen( context.getEmptyColor(),
 
317
                              context.layoutUnitToPixelX( context.getLineWidth() ) ) );
 
318
        painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ),
 
319
                          context.layoutUnitToPixelY( upperLeft.y() ),
 
320
                          context.layoutUnitToPixelX( getWidth() ),
 
321
                          context.layoutUnitToPixelY( getHeight() ) );
255
322
    }
256
323
}
257
324
 
258
 
 
259
 
void SequenceElement::calcCursorSize(FormulaCursor* cursor, bool smallCursor)
 
325
void SequenceElement::calcCursorSize( const ContextStyle& context,
 
326
                                      FormulaCursor* cursor, bool smallCursor )
260
327
{
261
 
    KoPoint point = widgetPos();
 
328
    LuPixelPoint point = widgetPos();
262
329
    uint pos = cursor->getPos();
263
330
 
264
 
    double posX = getChildPosition(pos);
265
 
    double height = getHeight();
 
331
    luPixel posX = getChildPosition( context, pos );
 
332
    luPixel height = getHeight();
 
333
 
 
334
    luPixel unitX = context.ptToLayoutUnitPixX( 1 );
 
335
    luPixel unitY = context.ptToLayoutUnitPixY( 1 );
266
336
 
267
337
    // Here are those evil constants that describe the cursor size.
268
338
 
269
 
    if (cursor->isSelection()) {
 
339
    if ( cursor->isSelection() ) {
270
340
        uint mark = cursor->getMark();
271
 
        double markX = getChildPosition(mark);
272
 
        double x = QMIN(posX, markX);
273
 
        double width = fabs(posX - markX);
 
341
        luPixel markX = getChildPosition( context, mark );
 
342
        luPixel x = QMIN(posX, markX);
 
343
        luPixel width = abs(posX - markX);
274
344
 
275
 
        if (smallCursor) {
276
 
            cursor->cursorSize.setRect(point.x()+x, point.y(), width, height);
 
345
        if ( smallCursor ) {
 
346
            cursor->cursorSize.setRect( point.x()+x, point.y(), width, height );
277
347
        }
278
348
        else {
279
 
            cursor->cursorSize.setRect(point.x()+x, point.y()-2, width+1, height+4);
 
349
            cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY,
 
350
                                        width + unitX, height + 4*unitY );
280
351
        }
281
352
    }
282
353
    else {
283
 
        if (smallCursor) {
284
 
            cursor->cursorSize.setRect(point.x()+posX, point.y(), 1, height);
 
354
        if ( smallCursor ) {
 
355
            cursor->cursorSize.setRect( point.x()+posX, point.y(),
 
356
                                        unitX, height );
285
357
        }
286
358
        else {
287
 
            cursor->cursorSize.setRect(point.x(), point.y()-2, getWidth()+2, height+6);
 
359
            cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY,
 
360
                                        getWidth() + unitX, height + 4*unitY );
288
361
        }
289
362
    }
290
363
 
291
 
    cursor->cursorPoint.setX(point.x()+posX);
292
 
    cursor->cursorPoint.setY(point.y()+getHeight()/2);
 
364
    cursor->cursorPoint.setX( point.x()+posX );
 
365
    cursor->cursorPoint.setY( point.y()+getHeight()/2 );
293
366
}
294
367
 
295
368
 
296
369
/**
297
370
 * If the cursor is inside a sequence it needs to be drawn.
298
371
 */
299
 
void SequenceElement::drawCursor(FormulaCursor* cursor, QPainter& painter, bool smallCursor)
 
372
void SequenceElement::drawCursor( QPainter& painter, const ContextStyle& context,
 
373
                                  FormulaCursor* cursor, bool smallCursor )
300
374
{
301
 
    painter.setRasterOp(Qt::XorROP);
302
 
    if (cursor->isSelection()) {
303
 
        const QRect& r = cursor->cursorSize;
304
 
        painter.fillRect(r.x(), r.y(), r.width(), r.height(), Qt::white);
 
375
    painter.setRasterOp( Qt::XorROP );
 
376
    if ( cursor->isSelection() ) {
 
377
        const LuPixelRect& r = cursor->cursorSize;
 
378
        painter.fillRect( context.layoutUnitToPixelX( r.x() ),
 
379
                          context.layoutUnitToPixelY( r.y() ),
 
380
                          context.layoutUnitToPixelX( r.width() ),
 
381
                          context.layoutUnitToPixelY( r.height() ),
 
382
                          Qt::white );
305
383
    }
306
384
    else {
307
 
        painter.setPen(Qt::white);
308
 
        const QPoint& point = cursor->cursorPoint;
309
 
        const QRect& size = cursor->cursorSize;
310
 
        if (smallCursor) {
311
 
            painter.drawLine(point.x(), size.top(),
312
 
                             point.x(), size.bottom());
 
385
        painter.setPen( QPen( Qt::white,
 
386
                              context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
 
387
        const LuPixelPoint& point = cursor->getCursorPoint();
 
388
        const LuPixelRect& size = cursor->getCursorSize();
 
389
        if ( smallCursor ) {
 
390
            painter.drawLine( context.layoutUnitToPixelX( point.x() ),
 
391
                              context.layoutUnitToPixelY( size.top() ),
 
392
                              context.layoutUnitToPixelX( point.x() ),
 
393
                              context.layoutUnitToPixelY( size.bottom() )-1 );
313
394
        }
314
395
        else {
315
 
            painter.drawLine(point.x(), size.top(),
316
 
                             point.x(), size.bottom()-1);
317
 
            painter.drawLine(size.left(), size.bottom(),
318
 
                             size.right(), size.bottom());
 
396
            painter.drawLine( context.layoutUnitToPixelX( point.x() ),
 
397
                              context.layoutUnitToPixelY( size.top() ),
 
398
                              context.layoutUnitToPixelX( point.x() ),
 
399
                              context.layoutUnitToPixelY( size.bottom() )-1 );
 
400
            painter.drawLine( context.layoutUnitToPixelX( size.left() ),
 
401
                              context.layoutUnitToPixelY( size.bottom() )-1,
 
402
                              context.layoutUnitToPixelX( size.right() )-1,
 
403
                              context.layoutUnitToPixelY( size.bottom() )-1 );
319
404
        }
320
405
    }
321
 
    painter.setRasterOp(Qt::CopyROP);
 
406
    // This might be wrong but probably isn't.
 
407
    painter.setRasterOp( Qt::CopyROP );
322
408
}
323
409
 
324
410
 
325
 
double SequenceElement::getChildPosition(uint child)
 
411
luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
326
412
{
327
413
    if (child < children.count()) {
328
414
        return children.at(child)->getX();
332
418
            return children.at(child-1)->getX() + children.at(child-1)->getWidth();
333
419
        }
334
420
        else {
335
 
            return 2;
 
421
            return context.ptToLayoutUnitPixX( 2 );
336
422
        }
337
423
    }
338
424
}
356
442
    // Our parent asks us for a cursor position. Found.
357
443
    if (from == getParent()) {
358
444
        cursor->setTo(this, children.count());
 
445
        from->entered( this );
359
446
    }
360
447
 
361
448
    // We already owned the cursor. Ask next child then.
378
465
            if (getParent() != 0) {
379
466
                getParent()->moveLeft(cursor, this);
380
467
            }
 
468
            else {
 
469
                formula()->moveOutLeft( cursor );
 
470
            }
381
471
        }
382
472
    }
383
473
 
394
484
        if (from->isInvisible()) {
395
485
            moveLeft(cursor, this);
396
486
        }
 
487
        formula()->tell( "" );
397
488
    }
398
489
}
399
490
 
407
498
    // Our parent asks us for a cursor position. Found.
408
499
    if (from == getParent()) {
409
500
        cursor->setTo(this, 0);
 
501
        from->entered( this );
410
502
    }
411
503
 
412
504
    // We already owned the cursor. Ask next child then.
430
522
            if (getParent() != 0) {
431
523
                getParent()->moveRight(cursor, this);
432
524
            }
 
525
            else {
 
526
                formula()->moveOutRight( cursor );
 
527
            }
433
528
        }
434
529
    }
435
530
 
446
541
        if (from->isInvisible()) {
447
542
            moveRight(cursor, this);
448
543
        }
 
544
        formula()->tell( "" );
449
545
    }
450
546
}
451
547
 
494
590
        if (getParent() != 0) {
495
591
            getParent()->moveUp(cursor, this);
496
592
        }
 
593
        else {
 
594
            formula()->moveOutAbove( cursor );
 
595
        }
497
596
    }
498
597
}
499
598
 
511
610
        if (getParent() != 0) {
512
611
            getParent()->moveDown(cursor, this);
513
612
        }
 
613
        else {
 
614
            formula()->moveOutBelow( cursor );
 
615
        }
514
616
    }
515
617
}
516
618
 
600
702
 * The list will be emptied but stays the property of the caller.
601
703
 */
602
704
void SequenceElement::insert(FormulaCursor* cursor,
603
 
                             QList<BasicElement>& newChildren,
 
705
                             QPtrList<BasicElement>& newChildren,
604
706
                             Direction direction)
605
707
{
606
708
    int pos = cursor->getPos();
616
718
    else {
617
719
        cursor->setTo(this, pos, pos+count);
618
720
    }
 
721
 
619
722
    formula()->changed();
620
723
    parse();
621
724
}
628
731
 * The ownership of the list is passed to the caller.
629
732
 */
630
733
void SequenceElement::remove(FormulaCursor* cursor,
631
 
                             QList<BasicElement>& removedChildren,
 
734
                             QPtrList<BasicElement>& removedChildren,
632
735
                             Direction direction)
633
736
{
634
737
    if (cursor->isSelection()) {
685
788
/**
686
789
 * Removes the children at pos and appends it to the list.
687
790
 */
688
 
void SequenceElement::removeChild(QList<BasicElement>& removedChildren, int pos)
 
791
void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
689
792
{
690
793
    BasicElement* child = children.at(pos);
691
794
    formula()->elementRemoval(child);
718
821
        }
719
822
    }
720
823
    else {
721
 
        if ( cursor->getPos() < static_cast<int>( children.count() ) ) {
 
824
        if ( cursor->getPos() < qRound( children.count() ) ) {
722
825
            return children.at( cursor->getPos() );
723
826
        }
724
827
    }
754
857
    }
755
858
}
756
859
 
757
 
QString SequenceElement::getCurrentName(FormulaCursor* cursor)
758
 
{
759
 
    uint pos = cursor->getPos();
760
 
    if (pos > 0) {
761
 
        ElementType* type = children.at(pos-1)->getElementType();
762
 
        if (type != 0) {
763
 
            QString name = type->getName();
764
 
            if (!name.isNull()) {
765
 
                cursor->setTo(this, type->start(), type->end());
766
 
                return name;
767
 
            }
768
 
        }
769
 
        if (pos == children.count()) {
770
 
            bool linear = cursor->getLinearMovement();
771
 
            cursor->setLinearMovement(false);
772
 
            cursor->moveRight();
773
 
            cursor->setLinearMovement(linear);
774
 
        }
775
 
    }
776
 
    return QString::null;
777
 
}
778
 
 
779
860
 
780
861
/**
781
862
 * Selects all children. The cursor is put behind, the mark before them.
785
866
    cursor->setTo(this, children.count(), 0);
786
867
}
787
868
 
 
869
bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
 
870
{
 
871
    if ( cursor->isSelection() ) {
 
872
        uint from = QMIN( cursor->getPos(), cursor->getMark() );
 
873
        uint to = QMAX( cursor->getPos(), cursor->getMark() );
 
874
        for ( uint i = from; i < to; i++ ) {
 
875
            BasicElement* element = getChild( i );
 
876
            if ( element->getCharacter() == QChar::null ) {
 
877
                return false;
 
878
            }
 
879
        }
 
880
    }
 
881
    return true;
 
882
}
 
883
 
 
884
 
 
885
KCommand* SequenceElement::buildCommand( Container* container, Request* request )
 
886
{
 
887
    FormulaCursor* cursor = container->activeCursor();
 
888
    if ( cursor->isReadOnly() ) {
 
889
        formula()->tell( i18n( "write protection" ) );
 
890
        return 0;
 
891
    }
 
892
 
 
893
    switch ( *request ) {
 
894
    case req_addText: {
 
895
        KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
 
896
        TextRequest* tr = static_cast<TextRequest*>( request );
 
897
        for ( uint i = 0; i < tr->text().length(); i++ ) {
 
898
            command->addElement( creationStrategy->createTextElement( tr->text()[i] ) );
 
899
        }
 
900
        return command;
 
901
    }
 
902
    case req_addTextChar: {
 
903
        KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
 
904
        TextCharRequest* tr = static_cast<TextCharRequest*>( request );
 
905
        TextElement* element = creationStrategy->createTextElement( tr->ch(), tr->isSymbol() );
 
906
        command->addElement( element );
 
907
        return command;
 
908
    }
 
909
    case req_addEmptyBox: {
 
910
        EmptyElement* element = creationStrategy->createEmptyElement();
 
911
        if ( element != 0 ) {
 
912
            KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
 
913
            command->addElement( element );
 
914
            return command;
 
915
        }
 
916
        break;
 
917
    }
 
918
    case req_addNameSequence:
 
919
        if ( onlyTextSelected( container->activeCursor() ) ) {
 
920
            NameSequence* nameSequence = creationStrategy->createNameSequence();
 
921
            if ( nameSequence != 0 ) {
 
922
                KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
 
923
                command->setElement( nameSequence );
 
924
                return command;
 
925
            }
 
926
        }
 
927
        break;
 
928
    case req_addBracket: {
 
929
        BracketRequest* br = static_cast<BracketRequest*>( request );
 
930
        BracketElement* bracketElement =
 
931
            creationStrategy->createBracketElement( br->left(), br->right() );
 
932
        if ( bracketElement != 0 ) {
 
933
            KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
 
934
            command->setElement( bracketElement );
 
935
            return command;
 
936
        }
 
937
        break;
 
938
    }
 
939
    case req_addOverline: {
 
940
        OverlineElement* overline = creationStrategy->createOverlineElement();
 
941
        if ( overline != 0 ) {
 
942
            KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
 
943
            command->setElement( overline );
 
944
            return command;
 
945
        }
 
946
        break;
 
947
    }
 
948
    case req_addUnderline: {
 
949
        UnderlineElement* underline = creationStrategy->createUnderlineElement();
 
950
        if ( underline != 0 ) {
 
951
            KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
 
952
            command->setElement( underline );
 
953
            return command;
 
954
        }
 
955
        break;
 
956
    }
 
957
    case req_addMultiline: {
 
958
        MultilineElement* multiline = creationStrategy->createMultilineElement();
 
959
        if ( multiline != 0 ) {
 
960
            KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
 
961
            command->setElement( multiline );
 
962
            return command;
 
963
        }
 
964
        break;
 
965
    }
 
966
    case req_addSpace: {
 
967
        SpaceRequest* sr = static_cast<SpaceRequest*>( request );
 
968
        SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
 
969
        if ( element != 0 ) {
 
970
            KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
 
971
            command->addElement( element );
 
972
            return command;
 
973
        }
 
974
        break;
 
975
    }
 
976
    case req_addFraction: {
 
977
        FractionElement* fraction = creationStrategy->createFractionElement();
 
978
        if ( fraction != 0 ) {
 
979
            KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
 
980
            command->setElement( fraction );
 
981
            return command;
 
982
        }
 
983
        break;
 
984
    }
 
985
    case req_addRoot: {
 
986
        RootElement* root = creationStrategy->createRootElement();
 
987
        if ( root != 0 ) {
 
988
            KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
 
989
            command->setElement( root );
 
990
            return command;
 
991
        }
 
992
        break;
 
993
    }
 
994
    case req_addSymbol: {
 
995
        SymbolRequest* sr = static_cast<SymbolRequest*>( request );
 
996
        SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
 
997
        if ( symbol != 0 ) {
 
998
            KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
 
999
            command->setElement( symbol );
 
1000
            return command;
 
1001
        }
 
1002
        break;
 
1003
    }
 
1004
    case req_addOneByTwoMatrix: {
 
1005
        FractionElement* element = creationStrategy->createFractionElement();
 
1006
        if ( element != 0 ) {
 
1007
            KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
 
1008
            element->showLine(false);
 
1009
            command->setElement(element);
 
1010
            return command;
 
1011
        }
 
1012
    }
 
1013
    case req_addMatrix: {
 
1014
        MatrixRequest* mr = static_cast<MatrixRequest*>( request );
 
1015
        uint rows = mr->rows(), cols = mr->columns();
 
1016
        if ( ( rows == 0 ) || ( cols == 0 ) ) {
 
1017
            MatrixDialog* dialog = new MatrixDialog( 0 );
 
1018
            if ( dialog->exec() ) {
 
1019
                rows = dialog->h;
 
1020
                cols = dialog->w;
 
1021
            }
 
1022
            delete dialog;
 
1023
        }
 
1024
 
 
1025
        if ( ( rows != 0 ) && ( cols != 0 ) ) {
 
1026
            KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
 
1027
            command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
 
1028
            return command;
 
1029
        }
 
1030
        else
 
1031
            return 0L;
 
1032
    }
 
1033
    case req_addIndex: {
 
1034
        if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
 
1035
            IndexElement* element =
 
1036
                dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
 
1037
            if ( element != 0 ) {
 
1038
                element->getMainChild()->goInside( cursor );
 
1039
                return element->getMainChild()->buildCommand( container, request );
 
1040
            }
 
1041
        }
 
1042
        IndexElement* element = creationStrategy->createIndexElement();
 
1043
        if ( element != 0 ) {
 
1044
            if ( !cursor->isSelection() ) {
 
1045
                cursor->moveLeft( SelectMovement | WordMovement );
 
1046
            }
 
1047
            IndexRequest* ir = static_cast<IndexRequest*>( request );
 
1048
            KFCAddIndex* command = new KFCAddIndex( container, element,
 
1049
                                                    element->getIndex( ir->index() ) );
 
1050
            return command;
 
1051
        }
 
1052
        break;
 
1053
    }
 
1054
    case req_removeEnclosing: {
 
1055
        if ( !cursor->isSelection() ) {
 
1056
            DirectedRemove* dr = static_cast<DirectedRemove*>( request );
 
1057
            KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
 
1058
            return command;
 
1059
        }
 
1060
    }
 
1061
    case req_remove: {
 
1062
        SequenceElement* sequence = cursor->normal();
 
1063
        if ( sequence &&
 
1064
             ( sequence == sequence->formula() ) &&
 
1065
             ( sequence->countChildren() == 0 ) ) {
 
1066
            sequence->formula()->removeFormula( cursor );
 
1067
            return 0;
 
1068
        }
 
1069
        else {
 
1070
            DirectedRemove* dr = static_cast<DirectedRemove*>( request );
 
1071
 
 
1072
            // empty removes are not legal!
 
1073
            if ( !cursor->isSelection() ) {
 
1074
                if ( countChildren() > 0 ) {
 
1075
                    if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
 
1076
                        return 0;
 
1077
                    }
 
1078
                    if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
 
1079
                        return 0;
 
1080
                    }
 
1081
                }
 
1082
                else if ( getParent() == 0 ) {
 
1083
                    return 0;
 
1084
                }
 
1085
            }
 
1086
 
 
1087
            KFCRemove* command = new KFCRemove( container, dr->direction() );
 
1088
            return command;
 
1089
        }
 
1090
    }
 
1091
    case req_compactExpression: {
 
1092
        cursor->moveEnd();
 
1093
        cursor->moveRight();
 
1094
        formula()->cursorHasMoved( cursor );
 
1095
        break;
 
1096
    }
 
1097
    case req_makeGreek: {
 
1098
        TextElement* element = cursor->getActiveTextElement();
 
1099
        if ((element != 0) && !element->isSymbol()) {
 
1100
            cursor->selectActiveElement();
 
1101
            const SymbolTable& table = container->document()->getSymbolTable();
 
1102
            if (table.greekLetters().find(element->getCharacter()) != -1) {
 
1103
                KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
 
1104
                TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
 
1105
                command->addElement( symbol );
 
1106
                return command;
 
1107
            }
 
1108
            cursor->setSelection( false );
 
1109
        }
 
1110
        break;
 
1111
    }
 
1112
    case req_paste:
 
1113
    case req_copy:
 
1114
    case req_cut:
 
1115
        break;
 
1116
    case req_formatBold:
 
1117
    case req_formatItalic: {
 
1118
        if ( cursor->isSelection() ) {
 
1119
            CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
 
1120
            CharStyle cs = normalChar;
 
1121
            if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
 
1122
            if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
 
1123
            CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
 
1124
            int end = cursor->getSelectionEnd();
 
1125
            for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
 
1126
                cmd->addElement( children.at( i ) );
 
1127
            }
 
1128
            return cmd;
 
1129
        }
 
1130
        break;
 
1131
    }
 
1132
    case req_formatFamily: {
 
1133
        if ( cursor->isSelection() ) {
 
1134
            CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
 
1135
            CharFamily cf = cfr->charFamily();
 
1136
            CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
 
1137
            int end = cursor->getSelectionEnd();
 
1138
            for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
 
1139
                cmd->addElement( children.at( i ) );
 
1140
            }
 
1141
            return cmd;
 
1142
        }
 
1143
        break;
 
1144
    }
 
1145
    default:
 
1146
        break;
 
1147
    }
 
1148
    return 0;
 
1149
}
 
1150
 
 
1151
 
 
1152
KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
 
1153
{
 
1154
    QChar ch = event->text().at( 0 );
 
1155
    if ( ch.isPrint() ) {
 
1156
        return input( container, ch );
 
1157
    }
 
1158
    else {
 
1159
        int action = event->key();
 
1160
        int state = event->state();
 
1161
        MoveFlag flag = movementFlag(state);
 
1162
 
 
1163
        switch ( action ) {
 
1164
        case Qt::Key_BackSpace: {
 
1165
            DirectedRemove r( req_remove, beforeCursor );
 
1166
            return buildCommand( container, &r );
 
1167
        }
 
1168
        case Qt::Key_Delete: {
 
1169
            DirectedRemove r( req_remove, afterCursor );
 
1170
            return buildCommand( container, &r );
 
1171
        }
 
1172
        case Qt::Key_Left: {
 
1173
            FormulaCursor* cursor = container->activeCursor();
 
1174
            cursor->moveLeft( flag );
 
1175
            formula()->cursorHasMoved( cursor );
 
1176
            break;
 
1177
        }
 
1178
        case Qt::Key_Right: {
 
1179
            FormulaCursor* cursor = container->activeCursor();
 
1180
            cursor->moveRight( flag );
 
1181
            formula()->cursorHasMoved( cursor );
 
1182
            break;
 
1183
        }
 
1184
        case Qt::Key_Up: {
 
1185
            FormulaCursor* cursor = container->activeCursor();
 
1186
            cursor->moveUp( flag );
 
1187
            formula()->cursorHasMoved( cursor );
 
1188
            break;
 
1189
        }
 
1190
        case Qt::Key_Down: {
 
1191
            FormulaCursor* cursor = container->activeCursor();
 
1192
            cursor->moveDown( flag );
 
1193
            formula()->cursorHasMoved( cursor );
 
1194
            break;
 
1195
        }
 
1196
        case Qt::Key_Home: {
 
1197
            FormulaCursor* cursor = container->activeCursor();
 
1198
            cursor->moveHome( flag );
 
1199
            formula()->cursorHasMoved( cursor );
 
1200
            break;
 
1201
        }
 
1202
        case Qt::Key_End: {
 
1203
            FormulaCursor* cursor = container->activeCursor();
 
1204
            cursor->moveEnd( flag );
 
1205
            formula()->cursorHasMoved( cursor );
 
1206
            break;
 
1207
        }
 
1208
        default:
 
1209
            if ( state & Qt::ControlButton ) {
 
1210
                switch ( event->key() ) {
 
1211
                case Qt::Key_AsciiCircum: {
 
1212
                    IndexRequest r( upperLeftPos );
 
1213
                    return buildCommand( container, &r );
 
1214
                }
 
1215
                case Qt::Key_Underscore: {
 
1216
                    IndexRequest r( lowerLeftPos );
 
1217
                    return buildCommand( container, &r );
 
1218
                }
 
1219
                default:
 
1220
                    break;
 
1221
                }
 
1222
            }
 
1223
        }
 
1224
    }
 
1225
    return 0;
 
1226
}
 
1227
 
 
1228
 
 
1229
KCommand* SequenceElement::input( Container* container, QChar ch )
 
1230
{
 
1231
    int unicode = ch.unicode();
 
1232
    switch (unicode) {
 
1233
    case '(': {
 
1234
        BracketRequest r( container->document()->leftBracketChar(),
 
1235
                          container->document()->rightBracketChar() );
 
1236
        return buildCommand( container, &r );
 
1237
    }
 
1238
    case '[': {
 
1239
        BracketRequest r( LeftSquareBracket, RightSquareBracket );
 
1240
        return buildCommand( container, &r );
 
1241
    }
 
1242
    case '{': {
 
1243
        BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
 
1244
        return buildCommand( container, &r );
 
1245
    }
 
1246
    case '|': {
 
1247
        BracketRequest r( LeftLineBracket, RightLineBracket );
 
1248
        return buildCommand( container, &r );
 
1249
    }
 
1250
    case '^': {
 
1251
        IndexRequest r( upperRightPos );
 
1252
        return buildCommand( container, &r );
 
1253
    }
 
1254
    case '_': {
 
1255
        IndexRequest r( lowerRightPos );
 
1256
        return buildCommand( container, &r );
 
1257
    }
 
1258
    case ' ': {
 
1259
        Request r( req_compactExpression );
 
1260
        return buildCommand( container, &r );
 
1261
    }
 
1262
    case '}': {
 
1263
        Request r( req_addEmptyBox );
 
1264
        return buildCommand( container, &r );
 
1265
    }
 
1266
    case ']':
 
1267
    case ')':
 
1268
        break;
 
1269
    case '\\': {
 
1270
        Request r( req_addNameSequence );
 
1271
        return buildCommand( container, &r );
 
1272
    }
 
1273
    default: {
 
1274
        TextCharRequest r( ch );
 
1275
        return buildCommand( container, &r );
 
1276
    }
 
1277
    }
 
1278
    return 0;
 
1279
}
788
1280
 
789
1281
/**
790
1282
 * Stores the given childrens dom in the element.
791
1283
 */
792
 
void SequenceElement::getChildrenDom(QDomDocument& doc, QDomElement& elem,
 
1284
void SequenceElement::getChildrenDom(QDomDocument doc, QDomElement elem,
793
1285
                                     uint from, uint to)
794
1286
{
795
1287
    for (uint i = from; i < to; i++) {
804
1296
 * puts them into the list.
805
1297
 * Returns false if an error occures.
806
1298
 */
807
 
bool SequenceElement::buildChildrenFromDom(QList<BasicElement>& list, QDomNode n)
 
1299
bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
808
1300
{
809
1301
    while (!n.isNull()) {
810
1302
        if (n.isElement()) {
834
1326
}
835
1327
 
836
1328
 
837
 
BasicElement* SequenceElement::createElement(QString type)
 
1329
BasicElement* SequenceElement::createElement( QString type )
838
1330
{
839
 
    if      (type == "TEXT")       return new TextElement();
840
 
    else if (type == "ROOT")       return new RootElement();
841
 
    else if (type == "BRACKET")    return new BracketElement();
842
 
    else if (type == "MATRIX")     return new MatrixElement();
843
 
    else if (type == "INDEX")      return new IndexElement();
844
 
    else if (type == "FRACTION")   return new FractionElement();
845
 
    else if (type == "SYMBOL")     return new SymbolElement();
846
 
    else if (type == "SEQUENCE") {
847
 
        cerr << "malformed data: sequence inside sequence.\n";
848
 
        return 0;
849
 
    }
850
 
    return 0;
 
1331
    return creationStrategy->createElement( type );
851
1332
}
852
1333
 
853
1334
/**
854
1335
 * Appends our attributes to the dom element.
855
1336
 */
856
 
void SequenceElement::writeDom(QDomElement& element)
 
1337
void SequenceElement::writeDom(QDomElement element)
857
1338
{
858
1339
    BasicElement::writeDom(element);
859
1340
 
866
1347
 * Reads our attributes from the element.
867
1348
 * Returns false if it failed.
868
1349
 */
869
 
bool SequenceElement::readAttributesFromDom(QDomElement& element)
 
1350
bool SequenceElement::readAttributesFromDom(QDomElement element)
870
1351
{
871
1352
    if (!BasicElement::readAttributesFromDom(element)) {
872
1353
        return false;
902
1383
        // be used.
903
1384
        element->setElementType(0);
904
1385
 
905
 
        if (element->getCharacter() == QChar::null) {
 
1386
        if (element->getCharacter().isNull()) {
906
1387
            textSequence = false;
907
1388
        }
908
1389
    }
911
1392
    SequenceParser parser(symbols);
912
1393
    parseTree = parser.parse(children);
913
1394
 
 
1395
    // With the IndexElement dynamically changing its text/non-text
 
1396
    // behaviour we need to reparse your parent, too. Hacky!
 
1397
    BasicElement* p = getParent();
 
1398
    if ( p != 0 ) {
 
1399
        SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
 
1400
        if ( seq != 0 ) {
 
1401
            seq->parse();
 
1402
        }
 
1403
    }
914
1404
    // debug
915
1405
    //parseTree->output();
916
1406
}
938
1428
    return content;
939
1429
}
940
1430
 
 
1431
 
 
1432
QString SequenceElement::formulaString()
 
1433
{
 
1434
    QString content;
 
1435
    uint count = children.count();
 
1436
    for ( uint i = 0; i < count; i++ ) {
 
1437
        BasicElement* child = children.at( i );
 
1438
        //if ( isFirstOfToken( child ) ) {
 
1439
        //    content += " ";
 
1440
        //}
 
1441
        content += child->formulaString();
 
1442
    }
 
1443
    return content;
 
1444
}
 
1445
 
 
1446
 
 
1447
void SequenceElement::writeMathML( QDomDocument doc, QDomNode parent )
 
1448
{
 
1449
    QDomElement de = doc.createElement( "mrow" );
 
1450
 
 
1451
    BasicElement* last = children.last();
 
1452
    if ( last != 0 ) {
 
1453
        // Create a list (right order!)
 
1454
        QPtrList<ElementType> tokenList;
 
1455
        ElementType* token = last->getElementType();
 
1456
        while ( token != 0 ) {
 
1457
            // Add to the list.
 
1458
            tokenList.prepend( token );
 
1459
            token = token->getPrev();
 
1460
        }
 
1461
 
 
1462
        if ( tokenList.count() == 1 ) {
 
1463
            tokenList.first()->saveMathML( this, doc, parent.toElement() );
 
1464
            return;
 
1465
        }
 
1466
 
 
1467
        for ( uint i = 0; i < tokenList.count(); ++i ) {
 
1468
            tokenList.at( i )->saveMathML( this, doc, de );
 
1469
        }
 
1470
    }
 
1471
    parent.appendChild( de );
 
1472
}
 
1473
 
 
1474
 
 
1475
int SequenceElement::childPos( const BasicElement* child ) const
 
1476
{
 
1477
    QPtrListIterator<BasicElement> it( children );
 
1478
    uint count = it.count();
 
1479
    for ( uint i=0; i<count; ++i, ++it ) {
 
1480
        if ( it.current() == child ) {
 
1481
            return i;
 
1482
        }
 
1483
    }
 
1484
    return -1;
 
1485
}
 
1486
 
 
1487
 
 
1488
NameSequence::NameSequence( BasicElement* parent )
 
1489
    : SequenceElement( parent )
 
1490
{
 
1491
}
 
1492
 
 
1493
 
 
1494
bool NameSequence::accept( ElementVisitor* visitor )
 
1495
{
 
1496
    return visitor->visit( this );
 
1497
}
 
1498
 
 
1499
 
 
1500
void NameSequence::calcCursorSize( const ContextStyle& context,
 
1501
                                   FormulaCursor* cursor, bool smallCursor )
 
1502
{
 
1503
    inherited::calcCursorSize( context, cursor, smallCursor );
 
1504
    LuPixelPoint point = widgetPos();
 
1505
    luPixel unitX = context.ptToLayoutUnitPixX( 1 );
 
1506
    luPixel unitY = context.ptToLayoutUnitPixY( 1 );
 
1507
    cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
 
1508
                                        getWidth()+2*unitX, getHeight()+2*unitY ) );
 
1509
}
 
1510
 
 
1511
void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
 
1512
                               FormulaCursor* cursor, bool smallCursor )
 
1513
{
 
1514
    LuPixelPoint point = widgetPos();
 
1515
    painter.setPen( QPen( context.getEmptyColor(),
 
1516
                          context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
 
1517
    luPixel unitX = context.ptToLayoutUnitPixX( 1 );
 
1518
    luPixel unitY = context.ptToLayoutUnitPixY( 1 );
 
1519
    painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
 
1520
                      context.layoutUnitToPixelY( point.y()-unitY ),
 
1521
                      context.layoutUnitToPixelX( getWidth()+2*unitX ),
 
1522
                      context.layoutUnitToPixelY( getHeight()+2*unitY ) );
 
1523
 
 
1524
    inherited::drawCursor( painter, context, cursor, smallCursor );
 
1525
}
 
1526
 
 
1527
void NameSequence::moveWordLeft( FormulaCursor* cursor )
 
1528
{
 
1529
    uint pos = cursor->getPos();
 
1530
    if ( pos > 0 ) {
 
1531
        cursor->setTo( this, 0 );
 
1532
    }
 
1533
    else {
 
1534
        moveLeft( cursor, this );
 
1535
    }
 
1536
}
 
1537
 
 
1538
void NameSequence::moveWordRight( FormulaCursor* cursor )
 
1539
{
 
1540
    int pos = cursor->getPos();
 
1541
    if ( pos < countChildren() ) {
 
1542
        cursor->setTo( this, countChildren() );
 
1543
    }
 
1544
    else {
 
1545
        moveRight( cursor, this );
 
1546
    }
 
1547
}
 
1548
 
 
1549
 
 
1550
KCommand* NameSequence::compactExpressionCmd( Container* container )
 
1551
{
 
1552
    BasicElement* element = replaceElement( container->document()->getSymbolTable() );
 
1553
    if ( element != 0 ) {
 
1554
        getParent()->selectChild( container->activeCursor(), this );
 
1555
 
 
1556
        KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
 
1557
        command->addElement( element );
 
1558
        return command;
 
1559
    }
 
1560
    return 0;
 
1561
}
 
1562
 
 
1563
KCommand* NameSequence::buildCommand( Container* container, Request* request )
 
1564
{
 
1565
    switch ( *request ) {
 
1566
    case req_compactExpression:
 
1567
        return compactExpressionCmd( container );
 
1568
    case req_addSpace:
 
1569
    case req_addIndex:
 
1570
    case req_addMatrix:
 
1571
    case req_addOneByTwoMatrix:
 
1572
    case req_addSymbol:
 
1573
    case req_addRoot:
 
1574
    case req_addFraction:
 
1575
    case req_addBracket:
 
1576
    case req_addNameSequence:
 
1577
        return 0;
 
1578
    default:
 
1579
        break;
 
1580
    }
 
1581
    return inherited::buildCommand( container, request );
 
1582
}
 
1583
 
 
1584
 
 
1585
KCommand* NameSequence::input( Container* container, QChar ch )
 
1586
{
 
1587
    int unicode = ch.unicode();
 
1588
    switch (unicode) {
 
1589
    case '(':
 
1590
    case '[':
 
1591
    case '|':
 
1592
    case '^':
 
1593
    case '_':
 
1594
    case '}':
 
1595
    case ']':
 
1596
    case ')':
 
1597
    case '\\': {
 
1598
//         KCommand* compact = compactExpressionCmd( container );
 
1599
//         KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch );
 
1600
//         if ( compact != 0 ) {
 
1601
//             KMacroCommand* macro = new KMacroCommand( cmd->name() );
 
1602
//             macro->addCommand( compact );
 
1603
//             macro->addCommand( cmd );
 
1604
//             return macro;
 
1605
//         }
 
1606
//         else {
 
1607
//             return cmd;
 
1608
//         }
 
1609
        break;
 
1610
    }
 
1611
    case '{':
 
1612
    case ' ': {
 
1613
        Request r( req_compactExpression );
 
1614
        return buildCommand( container, &r );
 
1615
    }
 
1616
    default: {
 
1617
        TextCharRequest r( ch );
 
1618
        return buildCommand( container, &r );
 
1619
    }
 
1620
    }
 
1621
    return 0;
 
1622
}
 
1623
 
 
1624
void NameSequence::setElementType( ElementType* t )
 
1625
{
 
1626
    inherited::setElementType( t );
 
1627
    parse();
 
1628
}
 
1629
 
 
1630
BasicElement* NameSequence::replaceElement( const SymbolTable& table )
 
1631
{
 
1632
    QString name = buildName();
 
1633
    QChar ch = table.unicode( name );
 
1634
    if ( !ch.isNull() ) {
 
1635
        return new TextElement( ch, true );
 
1636
    }
 
1637
    else {
 
1638
        ch = table.unicode( i18n( name.latin1() ) );
 
1639
        if ( !ch.isNull() ) {
 
1640
            return new TextElement( ch, true );
 
1641
        }
 
1642
    }
 
1643
 
 
1644
    if ( name == "!" )    return new SpaceElement( NEGTHIN );
 
1645
    if ( name == "," )    return new SpaceElement( THIN );
 
1646
    if ( name == ">" )    return new SpaceElement( MEDIUM );
 
1647
    if ( name == ";" )    return new SpaceElement( THICK );
 
1648
    if ( name == "quad" ) return new SpaceElement( QUAD );
 
1649
 
 
1650
    if ( name == "frac" ) return new FractionElement();
 
1651
    if ( name == "atop" ) {
 
1652
        FractionElement* frac = new FractionElement();
 
1653
        frac->showLine( false );
 
1654
        return frac;
 
1655
    }
 
1656
    if ( name == "sqrt" ) return new RootElement();
 
1657
 
 
1658
    return 0;
 
1659
}
 
1660
 
 
1661
BasicElement* NameSequence::createElement( QString type )
 
1662
{
 
1663
    if      ( type == "TEXT" )         return new TextElement();
 
1664
    return 0;
 
1665
}
 
1666
 
 
1667
// void NameSequence::parse()
 
1668
// {
 
1669
//     // A name sequence is known as name and so are its children.
 
1670
//     // Caution: this is fake!
 
1671
//     for ( int i = 0; i < countChildren(); i++ ) {
 
1672
//         getChild( i )->setElementType( getElementType() );
 
1673
//     }
 
1674
// }
 
1675
 
 
1676
QString NameSequence::buildName()
 
1677
{
 
1678
    QString name;
 
1679
    for ( int i = 0; i < countChildren(); i++ ) {
 
1680
        name += getChild( i )->getCharacter();
 
1681
    }
 
1682
    return name;
 
1683
}
 
1684
 
 
1685
bool NameSequence::isValidSelection( FormulaCursor* cursor )
 
1686
{
 
1687
    SequenceElement* sequence = cursor->normal();
 
1688
    if ( sequence == 0 ) {
 
1689
        return false;
 
1690
    }
 
1691
    return sequence->onlyTextSelected( cursor );
 
1692
}
 
1693
 
 
1694
void NameSequence::writeMathML( QDomDocument doc, QDomNode parent )
 
1695
{
 
1696
    QDomElement de = doc.createElement( "mi" );
 
1697
    QString value;
 
1698
    for ( int i = 0; i < countChildren(); ++i ) {
 
1699
        // these are supposed to by TextElements
 
1700
        value += getChild( i )->getCharacter();
 
1701
    }
 
1702
    de.appendChild( doc.createTextNode( value ) );
 
1703
    parent.appendChild( de );
 
1704
}
 
1705
 
941
1706
KFORMULA_NAMESPACE_END