File indexing completed on 2024-04-28 15:22:55

0001 /**
0002  * This file is part of the DOM implementation for KDE.
0003  *
0004  * Copyright 1999 Lars Knoll (knoll@kde.org)
0005  * Copyright 2000 Gunnstein Lye (gunnstein@netcom.no)
0006  * Copyright 2000 Frederik Holljen (frederik.holljen@hig.no)
0007  * Copyright 2001 Peter Kelly (pmk@post.com)
0008  * Copyright 2003 Apple Computer, Inc.
0009  *
0010  * This library is free software; you can redistribute it and/or
0011  * modify it under the terms of the GNU Library General Public
0012  * License as published by the Free Software Foundation; either
0013  * version 2 of the License, or (at your option) any later version.
0014  *
0015  * This library is distributed in the hope that it will be useful,
0016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0018  * Library General Public License for more details.
0019  *
0020  * You should have received a copy of the GNU Library General Public License
0021  * along with this library; see the file COPYING.LIB.  If not, write to
0022  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0023  * Boston, MA 02110-1301, USA.
0024  *
0025  */
0026 #include "dom/dom_exception.h"
0027 #include "xml/dom_docimpl.h"
0028 #include "xml/dom2_rangeimpl.h"
0029 
0030 using namespace DOM;
0031 
0032 DOMString RangeException::codeAsString() const
0033 {
0034     return codeAsString(code);
0035 }
0036 
0037 bool RangeException::isRangeExceptionCode(int exceptioncode)
0038 {
0039     return exceptioncode >= _EXCEPTION_OFFSET && exceptioncode < _EXCEPTION_MAX;
0040 }
0041 
0042 DOMString RangeException::codeAsString(int code)
0043 {
0044     switch (code) {
0045     case BAD_BOUNDARYPOINTS_ERR:
0046         return DOMString("BAD_BOUNDARYPOINTS_ERR");
0047     case INVALID_NODE_TYPE_ERR:
0048         return DOMString("INVALID_NODE_TYPE_ERR");
0049     default:
0050         return DOMString("(unknown exception code)");
0051     }
0052 }
0053 
0054 Range::Range()
0055 {
0056     // a range can't exist by itself - it must be associated with a document
0057     impl = nullptr;
0058 }
0059 
0060 Range::Range(const Document rootContainer)
0061 {
0062     if (rootContainer.handle()) {
0063         impl = new RangeImpl(rootContainer.handle()->docPtr());
0064         impl->ref();
0065     } else {
0066         impl = nullptr;
0067     }
0068 }
0069 
0070 Range::Range(const Range &other)
0071 {
0072     impl = other.impl;
0073     if (impl) {
0074         impl->ref();
0075     }
0076 }
0077 
0078 Range::Range(const Node startContainer, const long startOffset, const Node endContainer, const long endOffset)
0079 {
0080     if (startContainer.isNull() || endContainer.isNull()) {
0081         throw DOMException(DOMException::NOT_FOUND_ERR);
0082     }
0083 
0084     if (!startContainer.handle()->document() ||
0085             startContainer.handle()->document() != endContainer.handle()->document()) {
0086         throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
0087     }
0088 
0089     impl = new RangeImpl(startContainer.handle()->docPtr(), startContainer.handle(), startOffset, endContainer.handle(), endOffset);
0090     impl->ref();
0091 }
0092 
0093 Range::Range(RangeImpl *i)
0094 {
0095     impl = i;
0096     if (impl) {
0097         impl->ref();
0098     }
0099 }
0100 
0101 Range &Range::operator = (const Range &other)
0102 {
0103     if (impl != other.impl) {
0104         if (impl) {
0105             impl->deref();
0106         }
0107         impl = other.impl;
0108         if (impl) {
0109             impl->ref();
0110         }
0111     }
0112     return *this;
0113 }
0114 
0115 Range::~Range()
0116 {
0117     if (impl) {
0118         impl->deref();
0119     }
0120 }
0121 
0122 Node Range::startContainer() const
0123 {
0124     if (!impl) {
0125         throw DOMException(DOMException::INVALID_STATE_ERR);
0126     }
0127 
0128     int exceptioncode = 0;
0129     NodeImpl *r = impl->startContainer(exceptioncode);
0130     throwException(exceptioncode);
0131     return r;
0132 }
0133 
0134 long Range::startOffset() const
0135 {
0136     if (!impl) {
0137         throw DOMException(DOMException::INVALID_STATE_ERR);
0138     }
0139 
0140     int exceptioncode = 0;
0141     long r = impl->startOffset(exceptioncode);
0142     throwException(exceptioncode);
0143     return r;
0144 
0145 }
0146 
0147 Node Range::endContainer() const
0148 {
0149     if (!impl) {
0150         throw DOMException(DOMException::INVALID_STATE_ERR);
0151     }
0152 
0153     int exceptioncode = 0;
0154     NodeImpl *r = impl->endContainer(exceptioncode);
0155     throwException(exceptioncode);
0156     return r;
0157 }
0158 
0159 long Range::endOffset() const
0160 {
0161     if (!impl) {
0162         throw DOMException(DOMException::INVALID_STATE_ERR);
0163     }
0164 
0165     int exceptioncode = 0;
0166     long r = impl->endOffset(exceptioncode);
0167     throwException(exceptioncode);
0168     return r;
0169 }
0170 
0171 bool Range::collapsed() const
0172 {
0173     if (!impl) {
0174         throw DOMException(DOMException::INVALID_STATE_ERR);
0175     }
0176 
0177     int exceptioncode = 0;
0178     bool r = impl->collapsed(exceptioncode);
0179     throwException(exceptioncode);
0180     return r;
0181 }
0182 
0183 Node Range::commonAncestorContainer()
0184 {
0185     if (!impl) {
0186         throw DOMException(DOMException::INVALID_STATE_ERR);
0187     }
0188 
0189     int exceptioncode = 0;
0190     NodeImpl *r = impl->commonAncestorContainer(exceptioncode);
0191     throwException(exceptioncode);
0192     return r;
0193 }
0194 
0195 void Range::setStart(const Node &refNode, long offset)
0196 {
0197     if (!impl) {
0198         throw DOMException(DOMException::INVALID_STATE_ERR);
0199     }
0200 
0201     int exceptioncode = 0;
0202     impl->setStart(refNode.handle(), offset, exceptioncode);
0203     throwException(exceptioncode);
0204 }
0205 
0206 void Range::setEnd(const Node &refNode, long offset)
0207 {
0208     if (!impl) {
0209         throw DOMException(DOMException::INVALID_STATE_ERR);
0210     }
0211 
0212     int exceptioncode = 0;
0213     impl->setEnd(refNode.handle(), offset, exceptioncode);
0214     throwException(exceptioncode);
0215 }
0216 
0217 void Range::setStartBefore(const Node &refNode)
0218 {
0219     if (!impl) {
0220         throw DOMException(DOMException::INVALID_STATE_ERR);
0221     }
0222 
0223     int exceptioncode = 0;
0224     impl->setStartBefore(refNode.handle(), exceptioncode);
0225     throwException(exceptioncode);
0226 }
0227 
0228 void Range::setStartAfter(const Node &refNode)
0229 {
0230     if (!impl) {
0231         throw DOMException(DOMException::INVALID_STATE_ERR);
0232     }
0233 
0234     int exceptioncode = 0;
0235     impl->setStartAfter(refNode.handle(), exceptioncode);
0236     throwException(exceptioncode);
0237 }
0238 
0239 void Range::setEndBefore(const Node &refNode)
0240 {
0241     if (!impl) {
0242         throw DOMException(DOMException::INVALID_STATE_ERR);
0243     }
0244 
0245     int exceptioncode = 0;
0246     impl->setEndBefore(refNode.handle(), exceptioncode);
0247     throwException(exceptioncode);
0248 }
0249 
0250 void Range::setEndAfter(const Node &refNode)
0251 {
0252     if (!impl) {
0253         throw DOMException(DOMException::INVALID_STATE_ERR);
0254     }
0255 
0256     int exceptioncode = 0;
0257     impl->setEndAfter(refNode.handle(), exceptioncode);
0258     throwException(exceptioncode);
0259 }
0260 
0261 void Range::collapse(bool toStart)
0262 {
0263     if (!impl) {
0264         throw DOMException(DOMException::INVALID_STATE_ERR);
0265     }
0266 
0267     int exceptioncode = 0;
0268     impl->collapse(toStart, exceptioncode);
0269     throwException(exceptioncode);
0270 }
0271 
0272 void Range::selectNode(const Node &refNode)
0273 {
0274     if (!impl) {
0275         throw DOMException(DOMException::INVALID_STATE_ERR);
0276     }
0277 
0278     int exceptioncode = 0;
0279     impl->selectNode(refNode.handle(), exceptioncode);
0280     throwException(exceptioncode);
0281 }
0282 
0283 void Range::selectNodeContents(const Node &refNode)
0284 {
0285     if (!impl) {
0286         throw DOMException(DOMException::INVALID_STATE_ERR);
0287     }
0288 
0289     int exceptioncode = 0;
0290     impl->selectNodeContents(refNode.handle(), exceptioncode);
0291     throwException(exceptioncode);
0292 }
0293 
0294 short Range::compareBoundaryPoints(CompareHow how, const Range &sourceRange)
0295 {
0296     if (!impl) {
0297         throw DOMException(DOMException::INVALID_STATE_ERR);
0298     }
0299 
0300     int exceptioncode = 0;
0301     short r = impl->compareBoundaryPoints(how, sourceRange.handle(), exceptioncode);
0302     throwException(exceptioncode);
0303     return r;
0304 }
0305 
0306 bool Range::boundaryPointsValid()
0307 {
0308     if (!impl) {
0309         throw DOMException(DOMException::INVALID_STATE_ERR);
0310     }
0311 
0312     return impl->boundaryPointsValid();
0313 }
0314 
0315 void Range::deleteContents()
0316 {
0317     if (!impl) {
0318         throw DOMException(DOMException::INVALID_STATE_ERR);
0319     }
0320 
0321     int exceptioncode = 0;
0322     impl->deleteContents(exceptioncode);
0323     throwException(exceptioncode);
0324 }
0325 
0326 DocumentFragment Range::extractContents()
0327 {
0328     if (!impl) {
0329         throw DOMException(DOMException::INVALID_STATE_ERR);
0330     }
0331 
0332     int exceptioncode = 0;
0333     DocumentFragmentImpl *r = impl->extractContents(exceptioncode);
0334     throwException(exceptioncode);
0335     return r;
0336 }
0337 
0338 DocumentFragment Range::cloneContents()
0339 {
0340     if (!impl) {
0341         throw DOMException(DOMException::INVALID_STATE_ERR);
0342     }
0343 
0344     int exceptioncode = 0;
0345     DocumentFragmentImpl *r = impl->cloneContents(exceptioncode);
0346     throwException(exceptioncode);
0347     return r;
0348 }
0349 
0350 void Range::insertNode(const Node &newNode)
0351 {
0352     if (!impl) {
0353         throw DOMException(DOMException::INVALID_STATE_ERR);
0354     }
0355 
0356     int exceptioncode = 0;
0357     impl->insertNode(newNode.handle(), exceptioncode);
0358     throwException(exceptioncode);
0359 }
0360 
0361 void Range::surroundContents(const Node &newParent)
0362 {
0363     if (!impl) {
0364         throw DOMException(DOMException::INVALID_STATE_ERR);
0365     }
0366 
0367     int exceptioncode = 0;
0368     impl->surroundContents(newParent.handle(), exceptioncode);
0369     throwException(exceptioncode);
0370 }
0371 
0372 Range Range::cloneRange()
0373 {
0374     if (!impl) {
0375         throw DOMException(DOMException::INVALID_STATE_ERR);
0376     }
0377 
0378     int exceptioncode = 0;
0379     RangeImpl *r = impl->cloneRange(exceptioncode);
0380     throwException(exceptioncode);
0381     return r;
0382 }
0383 
0384 DOMString Range::toString()
0385 {
0386     if (!impl) {
0387         throw DOMException(DOMException::INVALID_STATE_ERR);
0388     }
0389 
0390     int exceptioncode = 0;
0391     DOMString r = impl->toString(exceptioncode);
0392     throwException(exceptioncode);
0393     return r;
0394 
0395 }
0396 
0397 DOMString Range::toHTML()
0398 {
0399     if (!impl) {
0400         throw DOMException(DOMException::INVALID_STATE_ERR);
0401     }
0402     int exceptioncode = 0;
0403     DOMString r = impl->toHTML(exceptioncode);
0404     throwException(exceptioncode);
0405     return r;
0406 }
0407 
0408 DocumentFragment Range::createContextualFragment(const DOMString &html)
0409 {
0410     if (!impl) {
0411         throw DOMException(DOMException::INVALID_STATE_ERR);
0412     }
0413 
0414     int exceptioncode = 0;
0415     DocumentFragment r = impl->createContextualFragment(html, exceptioncode);
0416     throwException(exceptioncode);
0417     return r;
0418 }
0419 
0420 void Range::detach()
0421 {
0422     if (!impl) {
0423         throw DOMException(DOMException::INVALID_STATE_ERR);
0424     }
0425 
0426     int exceptioncode = 0;
0427     impl->detach(exceptioncode);
0428     throwException(exceptioncode);
0429 }
0430 
0431 bool Range::isDetached() const
0432 {
0433     if (!impl) {
0434         throw DOMException(DOMException::INVALID_STATE_ERR);
0435     }
0436 
0437     return impl->isDetached();
0438 }
0439 
0440 RangeImpl *Range::handle() const
0441 {
0442     return impl;
0443 }
0444 
0445 bool Range::isNull() const
0446 {
0447     return (impl == nullptr);
0448 }
0449 
0450 void Range::throwException(int exceptioncode) const
0451 {
0452     if (!exceptioncode) {
0453         return;
0454     }
0455 
0456     // ### also check for CSS & other exceptions?
0457     if (exceptioncode >= RangeException::_EXCEPTION_OFFSET && exceptioncode <= RangeException::_EXCEPTION_MAX) {
0458         throw RangeException(static_cast<RangeException::RangeExceptionCode>(exceptioncode - RangeException::_EXCEPTION_OFFSET));
0459     } else {
0460         throw DOMException(exceptioncode);
0461     }
0462 }
0463