src/qt3support/text/q3richtext_p.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/qt3support/text/q3richtext_p.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,636 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3Support module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3richtext_p.h"
+
+#ifndef QT_NO_RICHTEXT
+
+QT_BEGIN_NAMESPACE
+
+Q3TextCommand::~Q3TextCommand() {}
+Q3TextCommand::Commands Q3TextCommand::type() const { return Invalid; }
+
+
+#ifndef QT_NO_TEXTCUSTOMITEM
+Q3TextCustomItem::~Q3TextCustomItem() {}
+void Q3TextCustomItem::adjustToPainter(QPainter* p){ if (p) width = 0; }
+Q3TextCustomItem::Placement Q3TextCustomItem::placement() const { return PlaceInline; }
+
+bool Q3TextCustomItem::ownLine() const { return false; }
+void Q3TextCustomItem::resize(int nwidth){ width = nwidth; }
+void Q3TextCustomItem::invalidate() {}
+
+bool Q3TextCustomItem::isNested() const { return false; }
+int Q3TextCustomItem::minimumWidth() const { return 0; }
+
+QString Q3TextCustomItem::richText() const { return QString(); }
+
+bool Q3TextCustomItem::enter(Q3TextCursor *, Q3TextDocument*&, Q3TextParagraph *&, int &, int &, int &, bool)
+{
+    return true;
+}
+bool Q3TextCustomItem::enterAt(Q3TextCursor *, Q3TextDocument *&, Q3TextParagraph *&, int &, int &, int &, const QPoint &)
+{
+    return true;
+}
+bool Q3TextCustomItem::next(Q3TextCursor *, Q3TextDocument *&, Q3TextParagraph *&, int &, int &, int &)
+{
+    return true;
+}
+bool Q3TextCustomItem::prev(Q3TextCursor *, Q3TextDocument *&, Q3TextParagraph *&, int &, int &, int &)
+{
+    return true;
+}
+bool Q3TextCustomItem::down(Q3TextCursor *, Q3TextDocument *&, Q3TextParagraph *&, int &, int &, int &)
+{
+    return true;
+}
+bool Q3TextCustomItem::up(Q3TextCursor *, Q3TextDocument *&, Q3TextParagraph *&, int &, int &, int &)
+{
+    return true;
+}
+#endif // QT_NO_TEXTCUSTOMITEM
+
+void Q3TextFlow::setPageSize(int ps) { pagesize = ps; }
+#ifndef QT_NO_TEXTCUSTOMITEM
+bool Q3TextFlow::isEmpty() { return leftItems.isEmpty() && rightItems.isEmpty(); }
+#else
+bool Q3TextFlow::isEmpty() { return true; }
+#endif
+
+#ifndef QT_NO_TEXTCUSTOMITEM
+void Q3TextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; }
+
+void Q3TextTable::invalidate() { cachewidth = -1; }
+#endif
+
+Q3TextParagraphData::~Q3TextParagraphData() {}
+void Q3TextParagraphData::join(Q3TextParagraphData *) {}
+
+Q3TextFormatter::~Q3TextFormatter() {}
+void Q3TextFormatter::setWrapEnabled(bool b) { wrapEnabled = b; }
+void Q3TextFormatter::setWrapAtColumn(int c) { wrapColumn = c; }
+
+
+
+int Q3TextCursor::x() const
+{
+    if (idx >= para->length())
+        return 0;
+    Q3TextStringChar *c = para->at(idx);
+    int curx = c->x;
+    if (!c->rightToLeft &&
+         c->c.isSpace() &&
+         idx > 0 &&
+         para->at(idx - 1)->c != QLatin1Char('\t') &&
+         !c->lineStart &&
+         (para->alignment() & Qt::AlignJustify) == Qt::AlignJustify)
+        curx = para->at(idx - 1)->x + para->string()->width(idx - 1);
+    if (c->rightToLeft)
+        curx += para->string()->width(idx);
+    return curx;
+}
+
+int Q3TextCursor::y() const
+{
+    int dummy, line;
+    para->lineStartOfChar(idx, &dummy, &line);
+    return para->lineY(line);
+}
+
+int Q3TextCursor::globalX() const { return totalOffsetX() + para->rect().x() + x(); }
+int Q3TextCursor::globalY() const { return totalOffsetY() + para->rect().y() + y(); }
+
+Q3TextDocument *Q3TextCursor::document() const
+{
+    return para ? para->document() : 0;
+}
+
+void Q3TextCursor::gotoPosition(Q3TextParagraph* p, int index)
+{
+    if (para && p != para) {
+        while (!indices.isEmpty() && para->document() != p->document())
+            pop();
+        Q_ASSERT(indices.isEmpty() || para->document() == p->document());
+    }
+    para = p;
+    if (index < 0 || index >= para->length()) {
+        qWarning("Q3TextCursor::gotoParagraph Index: %d out of range", index);
+        if (index < 0 || para->length() == 0)
+            index = 0;
+        else
+            index = para->length() - 1;
+    }
+
+    tmpX = -1;
+    idx = index;
+    fixCursorPosition();
+}
+
+bool Q3TextDocument::hasSelection(int id, bool visible) const
+{
+    return (selections.find(id) != selections.end() &&
+             (!visible ||
+               ((Q3TextDocument*)this)->selectionStartCursor(id) !=
+               ((Q3TextDocument*)this)->selectionEndCursor(id)));
+}
+
+void Q3TextDocument::setSelectionStart(int id, const Q3TextCursor &cursor)
+{
+    Q3TextDocumentSelection sel;
+    sel.startCursor = cursor;
+    sel.endCursor = cursor;
+    sel.swapped = false;
+    selections[id] = sel;
+}
+
+Q3TextParagraph *Q3TextDocument::paragAt(int i) const
+{
+    Q3TextParagraph* p = curParag;
+    if (!p || p->paragId() > i)
+        p = fParag;
+    while (p && p->paragId() != i)
+        p = p->next();
+    ((Q3TextDocument*)this)->curParag = p;
+    return p;
+}
+
+
+Q3TextFormat::~Q3TextFormat()
+{
+}
+
+Q3TextFormat::Q3TextFormat()
+    : fm(QFontMetrics(fn)), linkColor(true), logicalFontSize(3), stdSize(qApp->font().pointSize())
+{
+    ref = 0;
+
+    usePixelSizes = false;
+    if (stdSize == -1) {
+        stdSize = qApp->font().pixelSize();
+        usePixelSizes = true;
+    }
+
+    missp = false;
+    ha = AlignNormal;
+    collection = 0;
+}
+
+Q3TextFormat::Q3TextFormat(const Q3StyleSheetItem *style)
+    : fm(QFontMetrics(fn)), linkColor(true), logicalFontSize(3), stdSize(qApp->font().pointSize())
+{
+    ref = 0;
+
+    usePixelSizes = false;
+    if (stdSize == -1) {
+        stdSize = qApp->font().pixelSize();
+        usePixelSizes = true;
+    }
+
+    missp = false;
+    ha = AlignNormal;
+    collection = 0;
+    fn = QFont(style->fontFamily(),
+                style->fontSize(),
+                style->fontWeight(),
+                style->fontItalic());
+    fn.setUnderline(style->fontUnderline());
+    fn.setStrikeOut(style->fontStrikeOut());
+    col = style->color();
+    fm = QFontMetrics(fn);
+    leftBearing = fm.minLeftBearing();
+    rightBearing = fm.minRightBearing();
+    hei = fm.lineSpacing();
+    asc = fm.ascent() + (fm.leading()+1)/2;
+    dsc = fm.descent();
+    missp = false;
+    ha = AlignNormal;
+    memset(widths, 0, 256);
+    generateKey();
+    addRef();
+}
+
+Q3TextFormat::Q3TextFormat(const QFont &f, const QColor &c, Q3TextFormatCollection *parent)
+    : fn(f), col(c), fm(QFontMetrics(f)), linkColor(true),
+      logicalFontSize(3), stdSize(f.pointSize())
+{
+    ref = 0;
+    usePixelSizes = false;
+    if (stdSize == -1) {
+        stdSize = f.pixelSize();
+        usePixelSizes = true;
+    }
+    collection = parent;
+    leftBearing = fm.minLeftBearing();
+    rightBearing = fm.minRightBearing();
+    hei = fm.lineSpacing();
+    asc = fm.ascent() + (fm.leading()+1)/2;
+    dsc = fm.descent();
+    missp = false;
+    ha = AlignNormal;
+    memset(widths, 0, 256);
+    generateKey();
+    addRef();
+}
+
+Q3TextFormat::Q3TextFormat(const Q3TextFormat &f)
+    : fm(f.fm)
+{
+    ref = 0;
+    collection = 0;
+    fn = f.fn;
+    col = f.col;
+    leftBearing = f.leftBearing;
+    rightBearing = f.rightBearing;
+    memset(widths, 0, 256);
+    hei = f.hei;
+    asc = f.asc;
+    dsc = f.dsc;
+    stdSize = f.stdSize;
+    usePixelSizes = f.usePixelSizes;
+    logicalFontSize = f.logicalFontSize;
+    missp = f.missp;
+    ha = f.ha;
+    k = f.k;
+    linkColor = f.linkColor;
+    addRef();
+}
+
+Q3TextFormat& Q3TextFormat::operator=(const Q3TextFormat &f)
+{
+    ref = 0;
+    collection = f.collection;
+    fn = f.fn;
+    col = f.col;
+    fm = f.fm;
+    leftBearing = f.leftBearing;
+    rightBearing = f.rightBearing;
+    memset(widths, 0, 256);
+    hei = f.hei;
+    asc = f.asc;
+    dsc = f.dsc;
+    stdSize = f.stdSize;
+    usePixelSizes = f.usePixelSizes;
+    logicalFontSize = f.logicalFontSize;
+    missp = f.missp;
+    ha = f.ha;
+    k = f.k;
+    linkColor = f.linkColor;
+    addRef();
+    return *this;
+}
+
+void Q3TextFormat::update()
+{
+    fm = QFontMetrics(fn);
+    leftBearing = fm.minLeftBearing();
+    rightBearing = fm.minRightBearing();
+    hei = fm.lineSpacing();
+    asc = fm.ascent() + (fm.leading()+1)/2;
+    dsc = fm.descent();
+    memset(widths, 0, 256);
+    generateKey();
+}
+
+
+QPainter* Q3TextFormat::pntr = 0;
+QFontMetrics* Q3TextFormat::pntr_fm = 0;
+int Q3TextFormat::pntr_ldg=-1;
+int Q3TextFormat::pntr_asc=-1;
+int Q3TextFormat::pntr_hei=-1;
+int Q3TextFormat::pntr_dsc=-1;
+
+void Q3TextFormat::setPainter(QPainter *p)
+{
+    pntr = p;
+}
+
+QPainter*  Q3TextFormat::painter()
+{
+    return pntr;
+}
+
+void Q3TextFormat::applyFont(const QFont &f)
+{
+    QFontMetrics fm(pntr->fontMetrics());
+    if (!pntr_fm || pntr->font() != f) {
+        pntr->setFont(f);
+        delete pntr_fm;
+        pntr_fm = new QFontMetrics(pntr->fontMetrics());
+        pntr_ldg = pntr_fm->leading();
+        pntr_asc = pntr_fm->ascent()+(pntr_ldg+1)/2;
+        pntr_hei = pntr_fm->lineSpacing();
+        pntr_dsc = -1;
+    }
+}
+
+int Q3TextFormat::minLeftBearing() const
+{
+    if (!pntr || !pntr->isActive())
+        return leftBearing;
+    applyFont(fn);
+    return pntr_fm->minLeftBearing();
+}
+
+int Q3TextFormat::minRightBearing() const
+{
+    if (!pntr || !pntr->isActive())
+        return rightBearing;
+    applyFont(fn);
+    return pntr_fm->minRightBearing();
+}
+
+int Q3TextFormat::height() const
+{
+    if (!pntr || !pntr->isActive())
+        return hei;
+    applyFont(fn);
+    return pntr_hei;
+}
+
+int Q3TextFormat::ascent() const
+{
+    if (!pntr || !pntr->isActive())
+        return asc;
+    applyFont(fn);
+    return pntr_asc;
+}
+
+int Q3TextFormat::descent() const
+{
+    if (!pntr || !pntr->isActive())
+        return dsc;
+    applyFont(fn);
+    if (pntr_dsc < 0)
+        pntr_dsc = pntr_fm->descent();
+    return pntr_dsc;
+}
+
+int Q3TextFormat::leading() const
+{
+    if (!pntr || !pntr->isActive())
+        return fm.leading();
+    applyFont(fn);
+    return pntr_ldg;
+}
+
+void Q3TextFormat::generateKey()
+{
+    k = getKey(fn, col, isMisspelled(), vAlign());
+}
+
+QString Q3TextFormat::getKey(const QFont &fn, const QColor &col, bool misspelled, VerticalAlignment a)
+{
+    QString k = fn.key();
+    k += QLatin1Char('/');
+    k += QString::number((uint)col.rgb());
+    k += QLatin1Char('/');
+    k += QString::number((int)misspelled);
+    k += QLatin1Char('/');
+    k += QString::number((int)a);
+    return k;
+}
+
+QString Q3TextString::toString(const QVector<Q3TextStringChar> &data)
+{
+    QString s;
+    int l = data.size();
+    s.setUnicode(0, l);
+    const Q3TextStringChar *c = data.data();
+    QChar *uc = (QChar *)s.unicode();
+    while (l--)
+        *(uc++) = (c++)->c;
+
+    return s;
+}
+
+void Q3TextParagraph::setSelection(int id, int start, int end)
+{
+    QMap<int, Q3TextParagraphSelection>::ConstIterator it = selections().constFind(id);
+    if (it != mSelections->constEnd()) {
+        if (start == (*it).start && end == (*it).end)
+            return;
+    }
+
+    Q3TextParagraphSelection sel;
+    sel.start = start;
+    sel.end = end;
+    (*mSelections)[id] = sel;
+    setChanged(true, true);
+}
+
+void Q3TextParagraph::removeSelection(int id)
+{
+    if (!hasSelection(id))
+        return;
+    if (mSelections)
+        mSelections->remove(id);
+    setChanged(true, true);
+}
+
+int Q3TextParagraph::selectionStart(int id) const
+{
+    if (!mSelections)
+        return -1;
+    QMap<int, Q3TextParagraphSelection>::ConstIterator it = mSelections->constFind(id);
+    if (it == mSelections->constEnd())
+        return -1;
+    return (*it).start;
+}
+
+int Q3TextParagraph::selectionEnd(int id) const
+{
+    if (!mSelections)
+        return -1;
+    QMap<int, Q3TextParagraphSelection>::ConstIterator it = mSelections->constFind(id);
+    if (it == mSelections->constEnd())
+        return -1;
+    return (*it).end;
+}
+
+bool Q3TextParagraph::hasSelection(int id) const
+{
+    return mSelections ? mSelections->contains(id) : false;
+}
+
+bool Q3TextParagraph::fullSelected(int id) const
+{
+    if (!mSelections)
+        return false;
+    QMap<int, Q3TextParagraphSelection>::ConstIterator it = mSelections->constFind(id);
+    if (it == mSelections->constEnd())
+        return false;
+    return (*it).start == 0 && (*it).end == str->length() - 1;
+}
+
+int Q3TextParagraph::lineY(int l) const
+{
+    if (l > (int)lineStarts.count() - 1) {
+        qWarning("Q3TextParagraph::lineY: line %d out of range!", l);
+        return 0;
+    }
+
+    if (!isValid())
+        ((Q3TextParagraph*)this)->format();
+
+    QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
+    while (l-- > 0)
+        ++it;
+    return (*it)->y;
+}
+
+int Q3TextParagraph::lineBaseLine(int l) const
+{
+    if (l > (int)lineStarts.count() - 1) {
+        qWarning("Q3TextParagraph::lineBaseLine: line %d out of range!", l);
+        return 10;
+    }
+
+    if (!isValid())
+        ((Q3TextParagraph*)this)->format();
+
+    QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
+    while (l-- > 0)
+        ++it;
+    return (*it)->baseLine;
+}
+
+int Q3TextParagraph::lineHeight(int l) const
+{
+    if (l > (int)lineStarts.count() - 1) {
+        qWarning("Q3TextParagraph::lineHeight: line %d out of range!", l);
+        return 15;
+    }
+
+    if (!isValid())
+        ((Q3TextParagraph*)this)->format();
+
+    QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
+    while (l-- > 0)
+        ++it;
+    return (*it)->h;
+}
+
+void Q3TextParagraph::lineInfo(int l, int &y, int &h, int &bl) const
+{
+    if (l > (int)lineStarts.count() - 1) {
+        qWarning("Q3TextParagraph::lineInfo: line %d out of range!", l);
+        qDebug("%d %d", (int)lineStarts.count() - 1, l);
+        y = 0;
+        h = 15;
+        bl = 10;
+        return;
+    }
+
+    if (!isValid())
+        ((Q3TextParagraph*)this)->format();
+
+    QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
+    while (l-- > 0)
+        ++it;
+    y = (*it)->y;
+    h = (*it)->h;
+    bl = (*it)->baseLine;
+}
+
+
+void Q3TextParagraph::setAlignment(int a)
+{
+    if (a == (int)align)
+        return;
+    align = a;
+    invalidate(0);
+}
+
+Q3TextFormatter *Q3TextParagraph::formatter() const
+{
+    if (hasdoc)
+        return document()->formatter();
+    if (pseudoDocument()->pFormatter)
+        return pseudoDocument()->pFormatter;
+    return (((Q3TextParagraph*)this)->pseudoDocument()->pFormatter = new Q3TextFormatterBreakWords);
+}
+
+void Q3TextParagraph::setTabArray(int *a)
+{
+    delete [] tArray;
+    tArray = a;
+}
+
+void Q3TextParagraph::setTabStops(int tw)
+{
+    if (hasdoc)
+        document()->setTabStops(tw);
+    else
+        tabStopWidth = tw;
+}
+
+QMap<int, Q3TextParagraphSelection> &Q3TextParagraph::selections() const
+{
+    if (!mSelections)
+        ((Q3TextParagraph *)this)->mSelections = new QMap<int, Q3TextParagraphSelection>;
+    return *mSelections;
+}
+
+#ifndef QT_NO_TEXTCUSTOMITEM
+QList<Q3TextCustomItem *> &Q3TextParagraph::floatingItems() const
+{
+    if (!mFloatingItems)
+        ((Q3TextParagraph *)this)->mFloatingItems = new QList<Q3TextCustomItem *>;
+    return *mFloatingItems;
+}
+#endif
+
+Q3TextStringChar::~Q3TextStringChar()
+{
+    if (format())
+        format()->removeRef();
+    if (type) // not Regular
+        delete p.custom;
+}
+
+Q3TextParagraphPseudoDocument::Q3TextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0),collection(){}
+Q3TextParagraphPseudoDocument::~Q3TextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; }
+
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_RICHTEXT