1# -*- coding: utf-8 -*- 2 3''' 4This file is part of the LibreOffice project. 5 6This Source Code Form is subject to the terms of the Mozilla Public 7License, v. 2.0. If a copy of the MPL was not distributed with this 8file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10This file incorporates work covered by the following license notice: 11 12 Licensed to the Apache Software Foundation (ASF) under one or more 13 contributor license agreements. See the NOTICE file distributed 14 with this work for additional information regarding copyright 15 ownership. The ASF licenses this file to you under the Apache 16 License, Version 2.0 (the "License"); you may not use this file 17 except in compliance with the License. You may obtain a copy of 18 the License at http://www.apache.org/licenses/LICENSE-2.0 . 19''' 20import uno 21import unittest 22import os.path 23from org.libreoffice.unotest import UnoInProcess, mkPropertyValue 24from tempfile import TemporaryDirectory 25from com.sun.star.uno import RuntimeException 26from com.sun.star.lang import IllegalArgumentException, NoSupportException 27from com.sun.star.beans import PropertyValue, StringPair 28from com.sun.star.rdf.URIs import ODF_PREFIX, ODF_SUFFIX 29from com.sun.star.i18n.NumberFormatIndex import NUMBER_INT 30from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK, HARD_HYPHEN 31from com.sun.star.text.TextContentAnchorType import ( 32 AT_CHARACTER, AS_CHARACTER, AT_PARAGRAPH, AT_PAGE, AT_FRAME) 33 34 35class TreeNode(): 36 '''base class for tree nodes. only instance: root of tree.''' 37 38 def __init__(self, content=None): 39 self.content = content 40 self._children = [] 41 self.nodetype = "__ROOT__" 42 self.isnesting = False 43 44 def __str__(self): 45 return "<{}>".format(self.nodetype) 46 47 def __eq__(self, other): 48 return type(self) == type(other) 49 50 def __ne__(self, other): 51 return not self == other 52 53 def _dup(self, nodetype, *args): 54 try: 55 return nodetype(*args) 56 except Exception as e: 57 raise RuntimeError("TreeNode.dup") from e 58 59 def createenumeration(self): 60 return iter(self._children) 61 62 def appendchild(self, child): 63 self._children.append(child) 64 return self 65 66 67class ContentNode(TreeNode): 68 69 def __init__(self, content): 70 super().__init__(content) 71 72 def __str__(self): 73 return "{}\tcontent: {}".format(super().__str__(), self.content) 74 75 def __eq__(self, other): 76 try: 77 return other.content == self.content and super().__eq__(other) 78 except AttributeError: 79 return False 80 81 def appendchild(self, child): 82 try: 83 self._children.append(child) 84 return self 85 except Exception as e: 86 raise RuntimeError("ContentNode.appendchild") from e 87 88 89class TextNode(ContentNode): 90 91 def __init__(self, content): 92 super().__init__(content) 93 self.nodetype = "Text" 94 95 def dup(self): 96 return self._dup(TextNode, self.content) 97 98 99class TextFieldNode(ContentNode): 100 101 def __init__(self, content): 102 super().__init__(content) 103 self.nodetype = "TextField" 104 105 def dup(self): 106 return self._dup(TextFieldNode, self.content) 107 108 109class ControlCharacterNode(TreeNode): 110 def __init__(self, char): 111 super().__init__() 112 self.char = char 113 self.nodetype = "ControlCharacter" 114 115 def __str__(self): 116 return "{}\tcontent: {}".format(super().__str__(), self.char) 117 118 def __eq__(self, other): 119 try: 120 return other.char == self.char and super().__eq__(other) 121 except AttributeError: 122 return False 123 124 def dup(self): 125 return self._dup(ControlCharacterNode, self.char) 126 127 128class FootnoteNode(TreeNode): 129 130 def __init__(self, label): 131 super().__init__() 132 self.label = label 133 self.nodetype = "Footnote" 134 135 def __str__(self): 136 return "{}\tlabel: {}".format(super().__str__(), self.label) 137 138 def __eq__(self, other): 139 try: 140 return other.label == self.label and super().__eq__(other) 141 except AttributeError: 142 return False 143 144 def dup(self): 145 return self._dup(FootnoteNode, self.label) 146 147 148class FrameNode(TreeNode): 149 def __init__(self, name, anchor): 150 super().__init__() 151 self.name = name 152 self.anchor = anchor 153 self.nodetype = "Frame" 154 155 def __str__(self): 156 return "{}\tname: {}\tanchor: {}".format( 157 super().__str__(),self.name, self.str_anchor(self.anchor)) 158 159 def __eq__(self, other): 160 try: 161 return (other.name == self.name and 162 other.anchor == self.anchor and 163 super().__eq__(other)) 164 except AttributeError: 165 return False 166 167 def dup(self): 168 return self._dup(FrameNode, self.name, self.anchor) 169 170 def str_anchor(self, anchor): 171 anchors = {str(AS_CHARACTER): "AS_CHARACTER", 172 str(AT_CHARACTER): "AT_CHARACTER", 173 str(AT_PARAGRAPH): "AT_PARAGRAPH", 174 str(AT_PAGE): "AT_PAGE", 175 str(AT_FRAME): "AT_FRAME"} 176 try: 177 return anchors[str(anchor)] 178 except KeyError: 179 raise RuntimeError("unknown anchor") 180 181 182class MetaNode(TreeNode): 183 def __init__(self, xmlid): 184 super().__init__() 185 self.xmlid = xmlid 186 self.nodetype = "InContentMetadata" 187 self.isnesting = True 188 189 def __str__(self): 190 return "{}\txmlid: {}#{}".format( 191 super().__str__(), self.xmlid.First, self.xmlid.Second) 192 193 def __eq__(self, other): 194 try: 195 return (type(other) == type(self) and 196 MetaNode.eq(other.xmlid, self.xmlid)) 197 except AttributeError: 198 return False 199 200 @classmethod 201 def eq(cls, left, right): 202 return left.First == right.First and left.Second == right.Second 203 204 def dup(self): 205 return self._dup(MetaNode, self.xmlid) 206 207 208class MarkNode(TreeNode): 209 def __init__(self, name, ispoint=True): 210 super().__init__() 211 self.name = name 212 self.ispoint = ispoint 213 self.isstart = False 214 215 def __str__(self): 216 return "{}\tisPoint: {}\tisStart: {}".format( 217 super().__str__(), self.ispoint, self.isstart) 218 219 def __eq__(self, other): 220 try: 221 return (other.name == self.name and 222 other.ispoint == self.ispoint and 223 other.isstart == self.isstart) 224 except AttributeError: 225 return False 226 227 228class BookmarkNode(MarkNode): 229 def __init__(self, name, xmlid=StringPair()): 230 super().__init__(name) 231 self.xmlid = xmlid 232 self.nodetype = "Bookmark" 233 234 def __str__(self): 235 return "{}\txmlid: {}#{}".format( 236 super().__str__(), self.xmlid.First, self.xmlid.Second) 237 238 def __eq__(self, other): 239 try: 240 return (type(other) == type(self) and 241 super().__eq__(other) and 242 MetaNode.eq(other.xmlid, self.xmlid)) 243 except AttributeError: 244 return False 245 246 def dup(self): 247 return self._dup(BookmarkNode, self.name, self.xmlid) 248 249 250class BookmarkStartNode(BookmarkNode): 251 252 def __init__(self, name, xmlid=StringPair()): 253 super().__init__(name, xmlid) 254 self.ispoint = False 255 self.isstart = True 256 257 def dup(self): 258 return self._dup(BookmarkStartNode, self.name) 259 260 261class BookmarkEndNode(BookmarkNode): 262 263 def __init__(self, name, xmlid=StringPair()): 264 super().__init__(name, xmlid) 265 self.ispoint = False 266 self.isstart = False 267 268 def dup(self): 269 return self._dup(BookmarkEndNode, self.name) 270 271 272class ReferenceMarkNode(MarkNode): 273 def __init__(self, name): 274 super().__init__(name) 275 self.nodetype = "ReferenceMark" 276 277 def __eq__(self, other): 278 return (type(other) == type(self) and super().__eq__(other)) 279 280 def dup(self): 281 return self._dup(ReferenceMarkNode, self.name) 282 283 284class ReferenceMarkStartNode(ReferenceMarkNode): 285 def __init__(self, name): 286 super().__init__(name) 287 self.ispoint = False 288 self.isstart = True 289 290 def dup(self): 291 return self._dup(ReferenceMarkStartNode, self.name) 292 293 294class ReferenceMarkEndNode(ReferenceMarkNode): 295 def __init__(self, name): 296 super().__init__(name) 297 self.ispoint = False 298 self.isstart = False 299 300 def dup(self): 301 return self._dup(ReferenceMarkEndNode, self.name) 302 303 304class DocumentIndexMarkNode(MarkNode): 305 def __init__(self, name): 306 super().__init__(name) 307 self.nodetype = "DocumentIndexMark" 308 309 def __eq__(self, other): 310 return (type(other) == type(self) and super().__eq__(other)) 311 312 def dup(self): 313 return self._dup(DocumentIndexMarkNode, self.name) 314 315 316class DocumentIndexMarkStartNode(DocumentIndexMarkNode): 317 def __init__(self, name): 318 super().__init__(name) 319 self.ispoint = False 320 self.isstart = True 321 322 def dup(self): 323 return self._dup(DocumentIndexMarkStartNode, self.name) 324 325 326class DocumentIndexMarkEndNode(DocumentIndexMarkNode): 327 def __init__(self, name): 328 super().__init__(name) 329 self.ispoint = False 330 self.isstart = False 331 332 def dup(self): 333 return self._dup(DocumentIndexMarkEndNode, self.name) 334 335 336class HyperlinkNode(TreeNode): 337 def __init__(self, url): 338 super().__init__() 339 self.nodetype = "Hyperlink" 340 self.isnesting = True 341 if url: 342 self.url = url 343 else: 344 raise RuntimeError("HyperlinkNode") 345 346 def __str__(self): 347 return "{}\turl: {}".format(super().__str__(), self.url) 348 349 def __eq__(self, other): 350 try: 351 return other.url == self.url and super().__eq__(other) 352 except AttributeError: 353 return False 354 355 def dup(self): 356 return self._dup(HyperlinkNode, self.url) 357 358 359class RubyNode(TreeNode): 360 def __init__(self, ruby): 361 super().__init__() 362 self.nodetype = "Ruby" 363 self.isnesting = True 364 if ruby: 365 self.ruby = ruby 366 else: 367 raise RuntimeError("RubyNode") 368 369 def __str__(self): 370 return "{}\trubytext: {}".format(super().__str__(), self.ruby) 371 372 def __eq__(self, other): 373 try: 374 return other.ruby == self.ruby and super().__eq__(other) 375 except AttributeError: 376 return False 377 378 def dup(self): 379 return self._dup(RubyNode, self.ruby) 380 381 382class MetaFieldNode(MetaNode): 383 def __init__(self, xmlid): 384 super().__init__(xmlid) 385 self.nodetype = "MetadataField" 386 387 def dup(self): 388 return self._dup(MetaFieldNode, self.xmlid) 389 390 391class Range(): 392 def __init__(self, start, end, node): 393 self.start = start 394 self.end = end 395 self.node = node 396 self.extent = end - start 397 398 399class Inserter(): 400 401 def __init__(self, xDoc): 402 self.xDoc = xDoc 403 self.xText = xDoc.getText() 404 self.xCursor = self.xText.createTextCursor() 405 406 def initparagraph(self): 407 ## we split the first (empty) paragraph, and then insert into the 408 ## second (empty) paragraph; this ensures first is always empty! 409 self.xCursor.gotoStartOfParagraph(False) 410 self.xText.insertControlCharacter(self.xCursor, PARAGRAPH_BREAK, False) 411 412 def inserttext(self, xCursor, text): 413 xCursor.setString(text) 414 415 def inserttextfield(self, xCursor, content): 416 xContent = self.maketextfield(content) 417 xContent.attach(xCursor) 418 419 def maketextfield(self, content): 420 xField = self.xDoc.createInstance("com.sun.star.text.textfield.Author") 421 xField.IsFixed = True 422 xField.FullName = False 423 xField.Content = content 424 return xField 425 426 def insertcontrolcharacter(self, xCursor, cchar): 427 self.xText.insertControlCharacter(xCursor, cchar, False) 428 429 def insertframe(self, xCursor, name, anchor): 430 xContent = self.makeframe(name, anchor) 431 xContent.attach(xCursor) 432 433 def makeframe(self, name, anchor): 434 xFrame = self.xDoc.createInstance("com.sun.star.text.TextFrame") 435 xFrame.AnchorType = anchor 436 xFrame.setName(name) 437 return xFrame 438 439 def insertfootnote(self, xCursor, label): 440 xContent = self.makefootnote(label) 441 xContent.attach(xCursor) 442 443 def makefootnote(self, label): 444 xFootNote = self.xDoc.createInstance("com.sun.star.text.Footnote") 445 xFootNote.setLabel(label) 446 return xFootNote 447 448 def insertbookmark(self, xCursor, name, xmlid): 449 xContent = self.makebookmark(name) 450 xContent.attach(xCursor) 451 if xmlid.First != "": 452 xContent.MetadataReference = xmlid 453 454 def makebookmark(self, name): 455 xBookmark = self.xDoc.createInstance("com.sun.star.text.Bookmark") 456 xBookmark.setName(name) 457 return xBookmark 458 459 def insertreferencemark(self, xCursor, name): 460 xContent = self.makereferencemark(name) 461 xContent.attach(xCursor) 462 463 def makereferencemark(self, name): 464 xMark = self.xDoc.createInstance("com.sun.star.text.ReferenceMark") 465 xMark.setName(name) 466 return xMark 467 468 def insertdocumentindexmark(self, xCursor, key): 469 xContent = self.makedocumentindexmark(key) 470 xContent.attach(xCursor) 471 472 def makedocumentindexmark(self, key): 473 xMark = self.xDoc.createInstance("com.sun.star.text.DocumentIndexMark") 474 xMark.PrimaryKey = key 475 return xMark 476 477 def inserthyperlink(self, xCursor, url): 478 xCursor.HyperLinkURL = url 479 480 def insertruby(self, xCursor, rubytext): 481 xCursor.RubyText = rubytext 482 483 def insertmeta(self, xCursor, xmlid): 484 xContent = self.makemeta() 485 xContent.attach(xCursor) 486 xContent.MetadataReference = xmlid 487 return xContent 488 489 def makemeta(self): 490 xMeta = self.xDoc.createInstance("com.sun.star.text.InContentMetadata") 491 return xMeta 492 493 def insertmetafield(self, xCursor, xmlid): 494 xContent = self.makemetafield() 495 xContent.attach(xCursor) 496 xContent.MetadataReference = xmlid 497 return xContent 498 499 def makemetafield(self): 500 xMeta = self.xDoc.createInstance( 501 "com.sun.star.text.textfield.MetadataField") 502 return xMeta 503 504 505class TreeInserter(Inserter): 506 507 def __init__(self, xDoc): 508 super().__init__(xDoc) 509 self._bookmarkstarts = {} 510 self._referencemarkstarts = {} 511 self._documentindexmarkstarts = {} 512 self._framehints = [] 513 514 def inserttree(self, tree): 515 if tree.nodetype != "__ROOT__": 516 raise RuntimeError("insertTree: test error: no root") 517 self.initparagraph() 518 self.insertchildren(tree.createenumeration()) 519 for p in self._framehints: 520 self.insertframe(p[0], p[1].name, p[1].anchor) 521 522 def insertchildren(self, children): 523 xCursor = self.xCursor 524 for node in children: 525 xCursor.gotoEndOfParagraph(False) 526 type_ = node.nodetype 527 if type_ == "Text": 528 self.inserttext(xCursor, node.content) 529 elif type_ == "TextField": 530 self.inserttextfield(xCursor, node.content) 531 elif type_ == "ControlCharacter": 532 self.insertcontrolcharacter(xCursor, node.char) 533 elif type_ == "Footnote": 534 self.insertfootnote(xCursor, node.label) 535 elif type_ == "Frame": 536 if node.anchor == AT_CHARACTER: 537 self._framehints.append((xCursor.getStart(), node)) 538 else: 539 self.insertframe(xCursor, node.name, node.anchor) 540 elif type_ == "Bookmark": 541 name = node.name 542 id_ = node.xmlid 543 if node.ispoint: 544 self.insertbookmark(xCursor, name, id_) 545 elif node.isstart: 546 self._bookmarkstarts[name] = xCursor.getStart() 547 else: 548 xRange = self._bookmarkstarts[name] 549 xParaCursor = self.mkcursor(xRange) 550 self.insertbookmark(xParaCursor, name, id_) 551 elif type_ == "ReferenceMark": 552 name = node.name 553 if node.ispoint: 554 self.insertreferencemark(xCursor, name) 555 elif node.isstart: 556 self._referencemarkstarts[name] = xCursor.getStart() 557 else: 558 xRange = self._referencemarkstarts[name] 559 xParaCursor = self.mkcursor(xRange) 560 self.insertreferencemark(xParaCursor, name) 561 elif type_ == "DocumentIndexMark": 562 name = node.name 563 if node.ispoint: 564 self.insertdocumentindexmark(xCursor, name) 565 elif node.isstart: 566 self._documentindexmarkstarts[name] = xCursor.getStart() 567 else: 568 xRange = self._documentindexmarkstarts[name] 569 xParaCursor = self.mkcursor(xRange) 570 self.insertdocumentindexmark(xParaCursor, name) 571 elif type_ == "Hyperlink": 572 xRange = xCursor.getStart() 573 self.insertchildren(node.createenumeration()) 574 xParaCursor = self.mkcursor(xRange) 575 self.inserthyperlink(xParaCursor, node.url) 576 elif type_ == "Ruby": 577 xRange = xCursor.getStart() 578 self.insertchildren(node.createenumeration()) 579 xParaCursor = self.mkcursor(xRange) 580 self.insertruby(xParaCursor, node.ruby) 581 elif type_ == "InContentMetadata": 582 xRange = xCursor.getStart() 583 self.insertchildren(node.createenumeration()) 584 xParaCursor = self.mkcursor(xRange) 585 self.insertmeta(xParaCursor, node.xmlid) 586 elif type_ == "MetadataField": 587 xRange = xCursor.getStart() 588 self.insertchildren(node.createenumeration()) 589 xParaCursor = self.mkcursor(xRange) 590 self.insertmetafield(xParaCursor, node.xmlid) 591 elif type_ == "SoftPageBreak": 592 raise RuntimeError("sorry, cannot test SoftPageBreak") 593 else: 594 raise RuntimeError("unexpected type: {}".format(type_)) 595 596 def mkcursor(self, xRange): 597 xCursor = self.xText.createTextCursorByRange(xRange) 598 xCursor.gotoEndOfParagraph(True) 599 return xCursor 600 601 602# FIXME: this does not account for inserted dummy characters! 603class RangeInserter(Inserter): 604 def __init__(self, xDoc): 605 super().__init__(xDoc) 606 self.initparagraph() 607 608 # def inserttext(self, pos, text): 609 # self.xCursor.gotoStartOfParagraph(False) 610 # self.xCursor.goRight(pos, False) 611 # self.inserttext(self.xCursor, text) 612 613 def insertrange(self, range): 614 self.xCursor.gotoStartOfParagraph(False) 615 self.xCursor.goRight(range.start, False) 616 self.xCursor.goRight(range.extent, True) 617 return self.insertnode(self.xCursor, range.node) 618 619 def insertnode(self, xParaCursor, node): 620 nodetype = node.nodetype 621 if nodetype == "Text": 622 text = node 623 self.inserttext(xParaCursor, text.content) 624 elif nodetype == "Hyperlink": 625 href = node 626 self.inserthyperlink(xParaCursor, href.url) 627 elif nodetype == "Ruby": 628 ruby = node 629 self.insertruby(xParaCursor, ruby.ruby) 630 elif nodetype == "InContentMetadata": 631 meta = node 632 return self.insertmeta(xParaCursor, meta.xmlid) 633 elif nodetype == "MetadataField": 634 meta = node 635 return self.insertmetafield(xParaCursor, meta.xmlid) 636 elif nodetype == "Bookmark": 637 bkmk = node 638 if bkmk.ispoint: 639 raise RuntimeError("range only") 640 self.insertbookmark(xParaCursor, bkmk.name, bkmk.xmlid) 641 elif nodetype == "ReferenceMark": 642 mark = node 643 if mark.ispoint: 644 raise RuntimeError("range only") 645 self.insertreferencemark(xParaCursor, mark.name) 646 elif nodetype == "DocumentIndexMark": 647 mark = node 648 if mark.ispoint: 649 raise RuntimeError("range only") 650 self.insertdocumentindexmark(xParaCursor, mark.name) 651 elif nodetype == "TextField": 652 field = node 653 self.inserttextfield(self.xCursor, field.content) 654 elif nodetype == "Footnote": 655 note = node 656 self.insertfootnote(self.xCursor, note.label) 657 elif nodetype == "Frame": 658 frame = node 659 self.insertframe(xParaCursor, frame.name, frame.anchor) 660 elif nodetype == "ControlCharacter": 661 cchar = node 662 self.insertcontrolcharacter(self.xCursor, cchar.char) 663 elif nodetype == "SoftPageBreak": 664 raise RuntimeError("sorry, cannot test SoftPageBreak") 665 else: 666 raise RuntimeError("unexpected nodetype: {}".format(nodetype)) 667 return None 668 669 670class EnumConverter(): 671 672 def __init__(self): 673 self._stack = [] 674 675 def convert(self, xEnum): 676 root = TreeNode() 677 self._stack.append(root) 678 ret = self.convertchildren(xEnum) 679 assert (len(self._stack)==0), "EnumConverter.convert: stack is not empty" 680 return ret 681 682 def convertchildren(self, xEnum): 683 for xPortion in xEnum: 684 type_ = xPortion.TextPortionType 685 if type_ == "Text": 686 text = xPortion.getString() 687 node = TextNode(text) 688 url = xPortion.HyperLinkURL 689 if len(url) > 0: 690 temp = node 691 node = HyperlinkNode(url) 692 node.appendchild(temp) 693 elif type_ == "TextField": 694 xField = xPortion.TextField 695 if xField.supportsService("com.sun.star.text.textfield.MetadataField"): 696 xmlid = xField.MetadataReference 697 node = MetaFieldNode(xmlid) 698 self._stack.append(node) 699 xEnumChildren = xField.createEnumeration() 700 node2 = self.convertchildren(xEnumChildren) 701 print(node) 702 print(node2) 703 assert (node2 is node), "stack error: meta-field" 704 else: 705 content = xField.Content 706 isFixed = xField.IsFixed 707 assert isFixed, "field not fixed?" 708 node = TextFieldNode(content) 709 elif type_ == "ControlCharacter": 710 c = xPortion.ControlCharacter 711 node = ControlCharacterNode(c) 712 elif type_ == "Footnote": 713 xFootnote = xPortion.Footnote 714 label = xFootnote.getLabel() 715 node = FootnoteNode(label) 716 elif type_ == "Frame": 717 xCEA = xPortion.createContentEnumeration('') 718 while xCEA.hasMoreElements(): 719 xFrame = xCEA.nextElement() 720 anchor = xFrame.AnchorType 721 name = xFrame.getName() 722 node = FrameNode(name, anchor) 723 self._stack[-1].appendchild(node) 724 continue 725 elif type_ == "Bookmark": 726 xMark = xPortion.Bookmark 727 name = xMark.getName() 728 xmlid = xMark.MetadataReference 729 isCollapsed = xPortion.IsCollapsed 730 if isCollapsed: 731 node = BookmarkNode(name, xmlid) 732 else: 733 isStart = xPortion.IsStart 734 if isStart: 735 node = BookmarkStartNode(name, xmlid) 736 else: 737 node = BookmarkEndNode(name, xmlid) 738 elif type_ == "ReferenceMark": 739 xMark = xPortion.ReferenceMark 740 name = xMark.getName() 741 isCollapsed = xPortion.IsCollapsed 742 if isCollapsed: 743 node = ReferenceMarkNode(name) 744 else: 745 isStart = xPortion.IsStart 746 if isStart: 747 node = ReferenceMarkStartNode(name) 748 else: 749 node = ReferenceMarkEndNode(name) 750 elif type_ == "DocumentIndexMark": 751 xMark = xPortion.DocumentIndexMark 752 name = xMark.PrimaryKey 753 isCollapsed = xPortion.IsCollapsed 754 if isCollapsed: 755 node = DocumentIndexMarkNode(name) 756 else: 757 isStart = xPortion.IsStart 758 if isStart: 759 node = DocumentIndexMarkStartNode(name) 760 else: 761 node = DocumentIndexMarkEndNode(name) 762 elif type_ == "Ruby": 763 isStart = xPortion.IsStart 764 if isStart: 765 # ARRGH!!! stupid api... 766 # the text is ONLY at the start! 767 ruby = xPortion.RubyText 768 node = RubyNode(ruby) 769 self._stack.append(node) 770 continue 771 else: 772 node = self._stack.pop() 773 assert (isinstance(node, RubyNode)), "stack error: Ruby expected; is: {}".format(str(node)) 774 elif type_ == "InContentMetadata": 775 xMeta = xPortion.InContentMetadata 776 xmlid = xMeta.MetadataReference 777 node = MetaNode(xmlid) 778 self._stack.append(node) 779 xEnumChildren = xMeta.createEnumeration() 780 node2 = self.convertchildren(xEnumChildren) 781 assert (node2 is node), "stack error: meta" 782 elif type_ == "SoftPageBreak": 783 node = SoftPageBreakNode() 784 else: 785 raise RuntimeError("unexpected type: {}".format(type_)) 786 self._stack[-1].appendchild(node) 787 ret = self._stack.pop() 788 return ret 789 790 791class FuzzyTester(): 792 '''this is where we nail the pudding to the wall''' 793 def __init__(self): 794 self.diffcontent = 0 795 self.diffmissing = 0 796 self.diffnesting = 0 797 self.diffspuriousemptytext = 0 798 self.diffsequence = 0 # ignored? 799 self.stackexpected = [] 800 self.stackactual = [] 801 self.bufferexpected = [] 802 self.bufferactual = [] 803 804 def dotest(self, expected, actual): 805 '''idea: traverse both trees, enumerate nodes, stopping at content nodes. 806 then compare buffers.''' 807 assert "__ROOT__" == expected.nodetype 808 assert "__ROOT__" == actual.nodetype 809 self.stackexpected.append((expected, expected.createenumeration())) 810 self.stackactual.append((actual, actual.createenumeration())) 811 while self.stackexpected or self.stackactual: 812 self.traverse(self.stackexpected, self.bufferexpected) 813 self.traverse(self.stackactual, self.bufferactual) 814 self.testbuffer() 815 if self.diffsequence: 816 print("warning: {} differences in sequence".format( 817 self.diffsequence)) 818 if self.diffspuriousemptytext: 819 print("warning: {} spurious empty text nodes".format( 820 self.diffspuriousemptytext)) 821 if self.diffnesting: 822 print("WARNING: {} differences in nesting".format( 823 self.diffnesting)) 824 assert self.diffcontent == 0 825 assert self.diffmissing == 0 826 827 def traverse(self, stack, buffer): 828 while stack: 829 topenum = stack[-1][1] 830 try: 831 node = next(topenum) 832 buffer.append(node) 833 if node._children: 834 node_enum = node.createenumeration() 835 stack.append((node, node_enum)) 836 if node.content: 837 if not (isinstance(node, TextNode) and # spurious empty text? 838 len(node.content) == 0): 839 return # break here 840 except StopIteration: 841 buffer.append(stack[-1][0]) 842 stack.pop() 843 844 def testterminatingnode(self): 845 lenexpected = len(self.bufferexpected) 846 lenactual = len(self.bufferactual) 847 if lenexpected == 0 or lenactual == 0: 848 return 849 expected = self.bufferexpected[-1] 850 actual = self.bufferactual[-1] 851 eroot = expected.nodetype == "__ROOT__" 852 aroot = actual.nodetype == "__ROOT__" 853 if eroot or aroot: 854 if not (eroot and aroot): 855 if aroot: 856 self.printmissing(expected) 857 else: 858 self.printunexpected(actual) 859 self.diffmissing += 1 860 return 861 self.testcontentnode(expected, actual) 862 self.bufferexpected[-1] = None 863 self.bufferactual[-1] = None 864 865 def testcontentnode(self, expected, actual): 866 contentexpected = expected.content 867 contentactual = actual.content 868 if expected != actual: 869 self.printdiff("text content differs", contentexpected, contentactual) 870 self.diffcontent += 1 871 872 def testbuffer(self): 873 lenactual = len(self.bufferactual) 874 tmp_bufferactual = self.bufferactual[:] 875 for i, node in enumerate(self.bufferexpected): 876 try: 877 j = tmp_bufferactual.index(node) 878 if j != i: 879 # FIXME how bad is this? 880 self.printdiff("position differs", i, j) 881 # a hacky hack 882 min_ = min(i,j) 883 max_ = max(min(lenactual-1, i),j) 884 for k in range(min_, max_): 885 tmp = tmp_bufferactual[k] 886 if tmp and tmp.isnesting: 887 self.printnesting(node, tmp) 888 self.diffnesting += 1 889 self.diffsequence += 1 890 tmp_bufferactual[j] = None 891 except ValueError: 892 print('perdrix') 893 self.printmissing(node) 894 self.diffmissing += 1 895 for j, node in enumerate(tmp_bufferactual): 896 if node: 897 self.printunexpected(node) 898 if isinstance(node, TextNode) and len(node.content) == 0: 899 self.diffspuriousemptytext += 1 900 else: 901 print('renard') 902 self.diffmissing += 1 903 self.testterminatingnode() 904 self.bufferexpected[:] = [] 905 self.bufferactual[:] = [] 906 907 def printdiff(self, prefix, expected, actual): 908 print("{}:\texpected: {}\tactual: {}".format(prefix, expected, actual)) 909 910 def printnesting(self, node, nesting): 911 print("node: {} possibly moved across nesting {}".format( 912 str(node), str(nesting))) 913 914 def printmissing(self, node): 915 print(" missing node: {}".format(str(node))) 916 917 def printunexpected(self, node): 918 print("unexpected node: {}".format(str(node))) 919 920 921class TextPortionEnumerationTest(unittest.TestCase): 922 923 xMSF = None 924 xContext = None 925 tempdir = None 926 927 @classmethod 928 def setUpClass(cls): 929 cls._uno = UnoInProcess() 930 cls._uno.setUp() 931 cls.xDoc = cls._uno.openEmptyWriterDoc() 932 cls.count = 0 933 934 @classmethod 935 def tearDownClass(cls): 936 cls.xDoc.close(True) 937 cls._uno.tearDown() 938 # HACK in case cls.xDoc holds a UNO proxy to an SwXTextDocument (whose dtor calls 939 # Application::GetSolarMutex via sw::UnoImplPtrDeleter), which would potentially only be 940 # garbage-collected after VCL has already been deinitialized: 941 cls.xDoc = None 942 943 def test_text(self): 944 root = TreeNode() 945 text = TextNode("abc") 946 root.appendchild(text) 947 self.dotest(root) 948 949 def test_text_field(self): 950 self.mkname("ruby") 951 root = TreeNode() 952 txtf = TextFieldNode("abc") 953 root.appendchild(txtf) 954 self.dotest(root) 955 956 @unittest.skip("FIXME this is converted to a text portion: ControlCharacter is obsolete") 957 def test_control_char(self): 958 root = TreeNode() 959 cchr = ControlCharacterNode(HARD_HYPHEN) 960 root.appendchild(cchr) 961 self.dotest(root) 962 963 @unittest.skip("FIXME: insert a soft page break: not done") 964 def test_soft_page_break(self): 965 root = TreeNode() 966 spbk =SoftPageBreakNode() 967 text = TextNode("abc") 968 root.appendchild(spbk) 969 root.appendchild(text) 970 self.dotest(root) 971 972 def test_footnote(self): 973 name = self.mkname("ftn") 974 root = TreeNode() 975 ftnd = FootnoteNode(name) 976 root.appendchild(ftnd) 977 self.dotest(root) 978 979 def test_frame_as(self): 980 name = self.mkname("frame") 981 root = TreeNode() 982 fram = FrameNode(name, AS_CHARACTER) 983 root.appendchild(fram) 984 self.dotest(root) 985 986 def test_frame_at(self): 987 name = self.mkname("frame") 988 root = TreeNode() 989 fram = FrameNode(name, AT_CHARACTER) 990 root.appendchild(fram) 991 self.dotest(root) 992 993 def test_bookmark_point(self): 994 name = self.mkname("mark") 995 root = TreeNode() 996 bkmk = BookmarkNode(name) 997 text = TextNode("abc") 998 root.appendchild(bkmk) 999 root.appendchild(text) 1000 self.dotest(root) 1001 1002 def test_bookmark(self): 1003 name = self.mkname("mark") 1004 root = TreeNode() 1005 bkm1 = BookmarkStartNode(name) 1006 text = TextNode("abc") 1007 bkm2 = BookmarkEndNode(name) 1008 root.appendchild(bkm1) 1009 root.appendchild(text) 1010 root.appendchild(bkm2) 1011 self.dotest(root) 1012 1013 def test_bookmark_point_xmlid(self): 1014 name = self.mkname("mark") 1015 id = self.mkid("id") 1016 root = TreeNode() 1017 bkmk = BookmarkNode(name, id) 1018 text = TextNode("abc") 1019 root.appendchild(bkmk) 1020 root.appendchild(text) 1021 self.dotest(root) 1022 1023 def test_bookmark_xmlid(self): 1024 name = self.mkname("mark") 1025 id = self.mkid("id") 1026 root = TreeNode() 1027 bkm1 = BookmarkStartNode(name, id) 1028 text = TextNode("abc") 1029 bkm2 = BookmarkEndNode(name, id) 1030 root.appendchild(bkm1) 1031 root.appendchild(text) 1032 root.appendchild(bkm2) 1033 self.dotest(root) 1034 1035 def test_refmark_point(self): 1036 name = self.mkname("refmark") 1037 root = TreeNode() 1038 rfmk = ReferenceMarkNode(name) 1039 text = TextNode("abc") 1040 root.appendchild(rfmk) 1041 root.appendchild(text) 1042 self.dotest(root) 1043 1044 def test_refmark(self): 1045 name = self.mkname("refmark") 1046 root = TreeNode() 1047 rfm1 = ReferenceMarkStartNode(name) 1048 text = TextNode("abc") 1049 rfm2 = ReferenceMarkEndNode(name) 1050 root.appendchild(rfm1) 1051 root.appendchild(text) 1052 root.appendchild(rfm2) 1053 self.dotest(root) 1054 1055 def test_toxmark_point(self): 1056 name = self.mkname("toxmark") 1057 root = TreeNode() 1058 txmk = DocumentIndexMarkNode(name) 1059 text = TextNode("abc") 1060 root.appendchild(txmk) 1061 root.appendchild(text) 1062 self.dotest(root) 1063 1064 def test_toxmark(self): 1065 name = self.mkname("toxmark") 1066 root = TreeNode() 1067 txm1 = DocumentIndexMarkStartNode(name) 1068 text = TextNode("abc") 1069 txm2 = DocumentIndexMarkEndNode(name) 1070 root.appendchild(txm1) 1071 root.appendchild(text) 1072 root.appendchild(txm2) 1073 self.dotest(root) 1074 1075 def test_hyperlink(self): 1076 name = self.mkname("url") 1077 root = TreeNode() 1078 href = HyperlinkNode(name) 1079 text = TextNode("abc") 1080 href.appendchild(text) 1081 root.appendchild(href) 1082 self.dotest(root) 1083 1084 def test_hyperlink_empty(self): 1085 name = self.mkname("url") 1086 root = TreeNode() 1087 href = HyperlinkNode(name) 1088 text = TextNode("") 1089 href.appendchild(text) 1090 root.appendchild(href) 1091 self.dotest(root) 1092 1093 def test_ruby(self): 1094 name = self.mkname("ruby") 1095 root = TreeNode() 1096 ruby = RubyNode(name) 1097 text = TextNode("abc") 1098 ruby.appendchild(text) 1099 root.appendchild(ruby) 1100 self.dotest(root) 1101 1102 def test_ruby_empty(self): 1103 # BUG: #i91534# 1104 name = self.mkname("ruby") 1105 root = TreeNode() 1106 ruby = RubyNode(name) 1107 root.appendchild(ruby) 1108 self.dotest(root) 1109 1110 def test_meta(self): 1111 id = StringPair("content.xml", self.mkname("id")) 1112 root = TreeNode() 1113 meta = MetaNode(id) 1114 text = TextNode("abc") 1115 root.appendchild(TextNode("123")) 1116 meta.appendchild(text) 1117 root.appendchild(meta) 1118 self.dotest(root) 1119 1120 def test_meta_empty(self): 1121 id = StringPair("content.xml", self.mkname("id")) 1122 root = TreeNode() 1123 meta = MetaNode(id) 1124 root.appendchild(meta) 1125 self.dotest(root) 1126 1127 def test_meta_field(self): 1128 id = StringPair("content.xml", self.mkname("id")) 1129 root = TreeNode() 1130 meta = MetaFieldNode(id) 1131 text = TextNode("abc") 1132 root.appendchild(TextNode("123")) 1133 meta.appendchild(text) 1134 root.appendchild(meta) 1135 self.dotest(root) 1136 1137 def test_meta_field_empty(self): 1138 id = StringPair("content.xml", self.mkname("id")) 1139 root = TreeNode() 1140 meta = MetaFieldNode(id) 1141 root.appendchild(meta) 1142 self.dotest(root) 1143 1144 def test_bookmark1(self): 1145 name1 = self.mkname("mark") 1146 name2 = self.mkname("mark") 1147 name3 = self.mkname("mark") 1148 root = TreeNode() 1149 root.appendchild(BookmarkStartNode(name1)) 1150 root.appendchild(BookmarkNode(name2)) 1151 root.appendchild(BookmarkStartNode(name3)) 1152 root.appendchild(TextNode("abc")) 1153 root.appendchild(BookmarkEndNode(name1)) 1154 root.appendchild(TextNode("de")) 1155 root.appendchild(BookmarkEndNode(name3)) 1156 self.dotest(root) 1157 1158 def test_bookmark2(self): 1159 name1 = self.mkname("mark") 1160 name2 = self.mkname("mark") 1161 name3 = self.mkname("mark") 1162 root = TreeNode() 1163 root.appendchild(BookmarkStartNode(name1)) 1164 root.appendchild(TextNode("abc")) 1165 root.appendchild(BookmarkNode(name2)) 1166 root.appendchild(BookmarkStartNode(name3)) 1167 root.appendchild(BookmarkEndNode(name1)) 1168 root.appendchild(TextNode("de")) 1169 root.appendchild(BookmarkEndNode(name3)) 1170 self.dotest(root) 1171 1172 def test_refmark2(self): 1173 name1 = self.mkname("refmark") 1174 root = TreeNode() 1175 root.appendchild(ReferenceMarkStartNode(name1)) 1176 root.appendchild(TextNode("abc")) 1177 # BUG: #i102541# (this is actually not unoportenum's fault) 1178 root.appendchild(ReferenceMarkEndNode(name1)) 1179 root.appendchild(TextNode("de")) 1180 self.dotest(root) 1181 1182 def test_refmark3(self): 1183 # BUG: #i107672# (non-deterministic; depends on pointer ordering) 1184 name1 = self.mkname("refmark") 1185 name2 = self.mkname("refmark") 1186 name3 = self.mkname("refmark") 1187 name4 = self.mkname("refmark") 1188 name5 = self.mkname("refmark") 1189 name6 = self.mkname("refmark") 1190 name7 = self.mkname("refmark") 1191 root = TreeNode() 1192 root.appendchild(ReferenceMarkStartNode(name1)) 1193 root.appendchild(ReferenceMarkStartNode(name2)) 1194 root.appendchild(ReferenceMarkStartNode(name3)) 1195 root.appendchild(ReferenceMarkStartNode(name4)) 1196 root.appendchild(ReferenceMarkStartNode(name5)) 1197 root.appendchild(ReferenceMarkStartNode(name6)) 1198 root.appendchild(ReferenceMarkStartNode(name7)) 1199 root.appendchild(TextNode("abc")) 1200 root.appendchild(ReferenceMarkEndNode(name7)) 1201 root.appendchild(ReferenceMarkEndNode(name6)) 1202 root.appendchild(ReferenceMarkEndNode(name5)) 1203 root.appendchild(ReferenceMarkEndNode(name4)) 1204 root.appendchild(ReferenceMarkEndNode(name3)) 1205 root.appendchild(ReferenceMarkEndNode(name2)) 1206 root.appendchild(ReferenceMarkEndNode(name1)) 1207 root.appendchild(TextNode("de")) 1208 self.dotest(root) 1209 1210 def test_toxmark2(self): 1211 name1 = self.mkname("toxmark") 1212 root = TreeNode() 1213 root.appendchild(DocumentIndexMarkStartNode(name1)) 1214 root.appendchild(TextNode("abc")) 1215 root.appendchild(DocumentIndexMarkEndNode(name1)) 1216 root.appendchild(TextNode("de")) 1217 self.dotest(root) 1218 1219 def test_toxmark3(self): 1220 # BUG: #i107672# (non-deterministic; depends on pointer ordering) 1221 name1 = self.mkname("toxmark") 1222 name2 = self.mkname("toxmark") 1223 name3 = self.mkname("toxmark") 1224 name4 = self.mkname("toxmark") 1225 name5 = self.mkname("toxmark") 1226 name6 = self.mkname("toxmark") 1227 name7 = self.mkname("toxmark") 1228 root = TreeNode() 1229 root.appendchild(DocumentIndexMarkStartNode(name1)) 1230 root.appendchild(DocumentIndexMarkStartNode(name2)) 1231 root.appendchild(DocumentIndexMarkStartNode(name3)) 1232 root.appendchild(DocumentIndexMarkStartNode(name4)) 1233 root.appendchild(DocumentIndexMarkStartNode(name5)) 1234 root.appendchild(DocumentIndexMarkStartNode(name6)) 1235 root.appendchild(DocumentIndexMarkStartNode(name7)) 1236 root.appendchild(TextNode("abc")) 1237 root.appendchild(DocumentIndexMarkEndNode(name7)) 1238 root.appendchild(DocumentIndexMarkEndNode(name6)) 1239 root.appendchild(DocumentIndexMarkEndNode(name5)) 1240 root.appendchild(DocumentIndexMarkEndNode(name4)) 1241 root.appendchild(DocumentIndexMarkEndNode(name3)) 1242 root.appendchild(DocumentIndexMarkEndNode(name2)) 1243 root.appendchild(DocumentIndexMarkEndNode(name1)) 1244 root.appendchild(TextNode("de")) 1245 self.dotest(root) 1246 1247 def test_marks1(self): 1248 name1 = self.mkname("bookmark") 1249 name2 = self.mkname("toxmark") 1250 name3 = self.mkname("refmark") 1251 name4 = self.mkname("toxmark") 1252 root = TreeNode() 1253 root.appendchild(BookmarkStartNode(name1)) 1254 root.appendchild(DocumentIndexMarkNode(name2)) 1255 root.appendchild(ReferenceMarkStartNode(name3)) 1256 root.appendchild(TextNode("abc")) 1257 root.appendchild(BookmarkEndNode(name1)) 1258 root.appendchild(DocumentIndexMarkStartNode(name4)) 1259 root.appendchild(TextNode("de")) 1260 root.appendchild(DocumentIndexMarkEndNode(name4)) 1261 root.appendchild(ReferenceMarkEndNode(name3)) 1262 self.dotest(root) 1263 1264 def test_marks2(self): 1265 name1 = self.mkname("bookmark") 1266 name2 = self.mkname("refmark") 1267 name3 = self.mkname("refmark") 1268 name4 = self.mkname("toxmark") 1269 name5 = self.mkname("refmark") 1270 root = TreeNode() 1271 root.appendchild(BookmarkStartNode(name1)) 1272 root.appendchild(ReferenceMarkNode(name2)) 1273 root.appendchild(ReferenceMarkStartNode(name3)) 1274 root.appendchild(TextNode("abc")) 1275 root.appendchild(DocumentIndexMarkStartNode(name4)) 1276 root.appendchild(ReferenceMarkStartNode(name5)) 1277 # BUG: #i102541# (this is actually not unoportenum's fault) 1278 root.appendchild(ReferenceMarkEndNode(name3)) 1279 root.appendchild(TextNode("de")) 1280 root.appendchild(DocumentIndexMarkEndNode(name4)) 1281 root.appendchild(BookmarkEndNode(name1)) 1282 root.appendchild(ReferenceMarkEndNode(name5)) 1283 self.dotest(root) 1284 1285 def test_marks3(self): 1286 name1 = self.mkname("bookmark") 1287 name2 = self.mkname("refmark") 1288 name3 = self.mkname("refmark") 1289 name4 = self.mkname("toxmark") 1290 name5 = self.mkname("refmark") 1291 root = TreeNode() 1292 root.appendchild(BookmarkStartNode(name1)) 1293 root.appendchild(DocumentIndexMarkNode(name2)) 1294 root.appendchild(DocumentIndexMarkStartNode(name3)) 1295 root.appendchild(TextNode("abc")) 1296 root.appendchild(ReferenceMarkStartNode(name4)) 1297 root.appendchild(DocumentIndexMarkStartNode(name5)) 1298 root.appendchild(DocumentIndexMarkEndNode(name3)) 1299 root.appendchild(TextNode("de")) 1300 root.appendchild(ReferenceMarkEndNode(name4)) 1301 root.appendchild(BookmarkEndNode(name1)) 1302 root.appendchild(DocumentIndexMarkEndNode(name5)) 1303 self.dotest(root) 1304 1305 def test_frame_mark1(self): 1306 name1 = self.mkname("bookmark") 1307 name2 = self.mkname("frame") 1308 root = TreeNode() 1309 root.appendchild(TextNode("abc")) 1310 root.appendchild(BookmarkNode(name1)) 1311 root.appendchild(TextNode("de")) 1312 root.appendchild(FrameNode(name2, AS_CHARACTER)) 1313 self.dotest(root) 1314 1315 def test_frame_mark2(self): 1316 # BUG: #i98530# 1317 name1 = self.mkname("bookmark") 1318 name2 = self.mkname("frame") 1319 root = TreeNode() 1320 root.appendchild(TextNode("abc")) 1321 root.appendchild(BookmarkNode(name1)) 1322 root.appendchild(TextNode("de")) 1323 root.appendchild(FrameNode(name2, AT_CHARACTER)) 1324 self.dotest(root) 1325 1326 def test_frame_mark3(self): 1327 name1 = self.mkname("frame") 1328 name2 = self.mkname("bookmark") 1329 root = TreeNode() 1330 root.appendchild(TextNode("abc")) 1331 root.appendchild(FrameNode(name1, AS_CHARACTER)) 1332 root.appendchild(TextNode("de")) 1333 root.appendchild(BookmarkNode(name2)) 1334 self.dotest(root) 1335 1336 def test_frame_mark4(self): 1337 name1 = self.mkname("frame") 1338 name2 = self.mkname("bookmark") 1339 root = TreeNode() 1340 root.appendchild(TextNode("abc")) 1341 root.appendchild(FrameNode(name1, AT_CHARACTER)) 1342 root.appendchild(TextNode("de")) 1343 root.appendchild(BookmarkNode(name2)) 1344 self.dotest(root) 1345 1346 def test_frames1(self): 1347 name1 = self.mkname("frame") 1348 name2 = self.mkname("frame") 1349 name3 = self.mkname("frame") 1350 root = TreeNode() 1351 root.appendchild(FrameNode(name1, AT_CHARACTER)) 1352 root.appendchild(FrameNode(name2, AT_CHARACTER)) 1353 root.appendchild(FrameNode(name3, AT_CHARACTER)) 1354 self.dotest(root) 1355 1356 def test_frames2(self): 1357 name1 = self.mkname("frame") 1358 name2 = self.mkname("frame") 1359 name3 = self.mkname("frame") 1360 root = TreeNode() 1361 root.appendchild(FrameNode(name1, AS_CHARACTER)) 1362 root.appendchild(FrameNode(name2, AS_CHARACTER)) 1363 root.appendchild(FrameNode(name3, AS_CHARACTER)) 1364 self.dotest(root) 1365 1366 def test_frames3(self): 1367 name1 = self.mkname("frame") 1368 name2 = self.mkname("frame") 1369 name3 = self.mkname("frame") 1370 root = TreeNode() 1371 root.appendchild(FrameNode(name1, AT_CHARACTER)) 1372 root.appendchild(FrameNode(name2, AS_CHARACTER)) 1373 root.appendchild(FrameNode(name3, AT_CHARACTER)) 1374 self.dotest(root) 1375 1376 def test_frames4(self): 1377 name1 = self.mkname("frame") 1378 name2 = self.mkname("frame") 1379 name3 = self.mkname("frame") 1380 root = TreeNode() 1381 root.appendchild(FrameNode(name1, AT_CHARACTER)) 1382 root.appendchild(FrameNode(name2, AT_CHARACTER)) 1383 root.appendchild(FrameNode(name3, AS_CHARACTER)) 1384 self.dotest(root) 1385 1386 def test_frames5(self): 1387 name1 = self.mkname("frame") 1388 name2 = self.mkname("frame") 1389 name3 = self.mkname("frame") 1390 root = TreeNode() 1391 root.appendchild(FrameNode(name1, AS_CHARACTER)) 1392 root.appendchild(FrameNode(name2, AT_CHARACTER)) 1393 root.appendchild(FrameNode(name3, AT_CHARACTER)) 1394 self.dotest(root) 1395 1396 def test_ruby_hyperlink1(self): 1397 name1 = self.mkname("ruby") 1398 name2 = self.mkname("url") 1399 root = TreeNode() 1400 ruby = RubyNode(name1) 1401 href = HyperlinkNode(name2) 1402 href.appendchild(TextNode("abc")) 1403 ruby.appendchild(href) 1404 root.appendchild(ruby) 1405 self.dotest(root) 1406 1407 def test_ruby_hyperlink2(self): 1408 name1 = self.mkname("url") 1409 name2 = self.mkname("ruby") 1410 root = TreeNode() 1411 href = HyperlinkNode(name1) 1412 ruby = RubyNode(name2) 1413 ruby.appendchild(TextNode("abc")) 1414 href.appendchild(ruby) 1415 root.appendchild(href) 1416 self.dotest(root) 1417 1418 def test_end1(self): 1419 name1 = self.mkname("bookmark") 1420 name2 = self.mkname("toxmark") 1421 name3 = self.mkname("refmark") 1422 root = TreeNode() 1423 root.appendchild(TextNode("abc")) 1424 root.appendchild(BookmarkNode(name1)) 1425 root.appendchild(DocumentIndexMarkNode(name2)) 1426 root.appendchild(ReferenceMarkNode(name3)) 1427 self.dotest(root) 1428 1429 def test_end2(self): 1430 name1 = self.mkname("bookmark") 1431 name2 = self.mkname("frame") 1432 name3 = self.mkname("refmark") 1433 name4 = self.mkname("frame") 1434 name5 = self.mkname("frame") 1435 root = TreeNode() 1436 root.appendchild(TextNode("abc")) 1437 root.appendchild(BookmarkStartNode(name1)) 1438 root.appendchild(FrameNode(name2, AT_CHARACTER)) 1439 root.appendchild(BookmarkEndNode(name1)) 1440 root.appendchild(ReferenceMarkNode(name3)) 1441 root.appendchild(FrameNode(name4, AT_CHARACTER)) 1442 root.appendchild(FrameNode(name5, AT_CHARACTER)) 1443 self.dotest(root) 1444 1445 def test_end3(self): 1446 name1 = self.mkname("ftn") 1447 name2 = self.mkname("toxmark") 1448 root = TreeNode() 1449 root.appendchild(TextNode("abc")) 1450 root.appendchild(FootnoteNode(name1)) 1451 root.appendchild(DocumentIndexMarkNode(name2)) 1452 self.dotest(root) 1453 1454 def test_end4(self): 1455 name1 = self.mkname("bookmark") 1456 name2 = self.mkname("frame") 1457 root = TreeNode() 1458 root.appendchild(BookmarkStartNode(name1)) 1459 root.appendchild(TextNode("abc")) 1460 root.appendchild(FrameNode(name2, AS_CHARACTER)) 1461 root.appendchild(BookmarkEndNode(name1)) 1462 self.dotest(root) 1463 1464 def test_end5(self): 1465 name1 = self.mkname("refmark") 1466 name2 = self.mkname("ruby") 1467 root = TreeNode() 1468 root.appendchild(ReferenceMarkStartNode(name1)) 1469 root.appendchild(TextNode("abc")) 1470 ruby = RubyNode(name2) 1471 ruby.appendchild(TextFieldNode("de")) 1472 root.appendchild(ruby) 1473 root.appendchild(ReferenceMarkEndNode(name1)) 1474 self.dotest(root) 1475 1476 def test_empty1(self): 1477 name1 = self.mkname("refmark") 1478 name2 = self.mkname("toxmark") 1479 name3 = self.mkname("bookmark") 1480 name4 = self.mkname("frame") 1481 name7 = self.mkname("refmark") 1482 name8 = self.mkname("toxmark") 1483 name9 = self.mkname("bookmark") 1484 nameA = self.mkname("frame") 1485 root = TreeNode() 1486 root.appendchild(ReferenceMarkNode(name1)) 1487 root.appendchild(DocumentIndexMarkNode(name2)) 1488 root.appendchild(BookmarkStartNode(name3)) 1489 root.appendchild(FrameNode(name4, AT_CHARACTER)) 1490 root.appendchild(BookmarkEndNode(name3)) 1491 root.appendchild(ReferenceMarkNode(name7)) 1492 root.appendchild(DocumentIndexMarkNode(name8)) 1493 root.appendchild(BookmarkStartNode(name9)) 1494 root.appendchild(FrameNode(nameA, AT_CHARACTER)) 1495 root.appendchild(BookmarkEndNode(name9)) 1496 self.dotest(root) 1497 1498 def test_empty2(self): 1499 name3 = self.mkname("bookmark") 1500 name4 = self.mkname("frame") 1501 name9 = self.mkname("bookmark") 1502 nameA = self.mkname("frame") 1503 root = TreeNode() 1504 root.appendchild(BookmarkStartNode(name3)) 1505 root.appendchild(FrameNode(name4, AT_CHARACTER)) 1506 root.appendchild(BookmarkEndNode(name3)) 1507 root.appendchild(BookmarkStartNode(name9)) 1508 root.appendchild(FrameNode(nameA, AT_CHARACTER)) 1509 root.appendchild(BookmarkEndNode(name9)) 1510 self.dotest(root) 1511 1512 def test_empty3(self): 1513 name1 = self.mkname("refmark") 1514 name2 = self.mkname("toxmark") 1515 name3 = self.mkname("bookmark") 1516 name4 = self.mkname("frame") 1517 name5 = self.mkname("url") 1518 name6 = self.mkname("ruby") 1519 name7 = self.mkname("refmark") 1520 name8 = self.mkname("toxmark") 1521 name9 = self.mkname("bookmark") 1522 nameA = self.mkname("frame") 1523 root = TreeNode() 1524 root.appendchild(ReferenceMarkNode(name1)) 1525 root.appendchild(DocumentIndexMarkNode(name2)) 1526 root.appendchild(BookmarkStartNode(name3)) 1527 root.appendchild(FrameNode(name4, AT_CHARACTER)) 1528 root.appendchild(BookmarkEndNode(name3)) 1529 ## currently empty hyperlinks may get eaten... 1530 # href = HyperlinkNode(name5) 1531 # href.appendchild(TextNode("")) 1532 # root.appendchild(href) 1533 ruby = RubyNode(name6) 1534 root.appendchild(ruby) 1535 root.appendchild(ReferenceMarkNode(name7)) 1536 root.appendchild(DocumentIndexMarkNode(name8)) 1537 root.appendchild(BookmarkStartNode(name9)) 1538 root.appendchild(FrameNode(nameA, AT_CHARACTER)) 1539 root.appendchild(BookmarkEndNode(name9)) 1540 self.dotest(root) 1541 1542 def test1(self): 1543 name1 = self.mkname("frame") 1544 name2 = self.mkname("bookmark") 1545 name3 = self.mkname("ruby") 1546 name4 = self.mkname("ftn") 1547 name5 = self.mkname("frame") 1548 root = TreeNode() 1549 root.appendchild(FrameNode(name1, AT_CHARACTER)) 1550 root.appendchild(BookmarkStartNode(name2)) 1551 root.appendchild(TextNode("abc")) 1552 ruby = RubyNode(name3) 1553 ruby.appendchild(TextNode("de")) 1554 ruby.appendchild(FootnoteNode(name4)) 1555 ruby.appendchild(BookmarkEndNode(name2)) 1556 root.appendchild(ruby) 1557 root.appendchild(TextNode("fg")) 1558 root.appendchild(FrameNode(name5, AT_CHARACTER)) 1559 root.appendchild(TextFieldNode("h")) 1560 self.dotest(root) 1561 1562 # some range tests for the insertion: these are for the current 1563 # API which treats hyperlinks and rubys not as entities, but as formatting 1564 # attributes; if these ever become entities, they should not be split!''' 1565 1566 def test_range1(self): 1567 name1 = self.mkname("url") 1568 inserter = RangeInserter(self.__class__.xDoc) 1569 text = TextNode("12345") 1570 inserter.insertrange(Range(0, 0, text)) 1571 url1 = HyperlinkNode(name1) 1572 range1 = Range(0, 5, url1) 1573 inserter.insertrange(range1) 1574 root = TreeNode() 1575 root.appendchild(url1) 1576 url1.appendchild(text) 1577 self.dotest(root, False) 1578 1579 def test_range_hyperlink_hyperlink(self): 1580 inserter = RangeInserter(self.__class__.xDoc) 1581 text = TextNode("123456789") 1582 inserter.insertrange(Range(0, 0, text)) 1583 url1 = HyperlinkNode(self.mkname("url")) 1584 inserter.insertrange(Range(1, 4, url1)) 1585 ## overlap left 1586 url2 = HyperlinkNode(self.mkname("url")) 1587 inserter.insertrange(Range(0, 2, url2)) 1588 root = TreeNode() 1589 root.appendchild(url2.dup().appendchild(TextNode("12"))) 1590 root.appendchild(url1.dup().appendchild(TextNode("34"))) 1591 root.appendchild(TextNode("56789")) 1592 self.dotest(root, False) 1593 ## overlap right 1594 url3 = HyperlinkNode(self.mkname("url")) 1595 inserter.insertrange(Range(3, 7, url3)) 1596 root = TreeNode() 1597 root.appendchild(url2.dup().appendchild(TextNode("12"))) 1598 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1599 root.appendchild(url3.dup().appendchild(TextNode("4567"))) 1600 root.appendchild(TextNode("89")) 1601 self.dotest(root, False) 1602 ## around 1603 url4 = HyperlinkNode(self.mkname("url")) 1604 inserter.insertrange(Range(3, 7, url4)) 1605 root = TreeNode() 1606 root.appendchild(url2.dup().appendchild(TextNode("12"))) 1607 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1608 root.appendchild(url4.dup().appendchild(TextNode("4567"))) 1609 root.appendchild(TextNode("89")) 1610 self.dotest(root, False) 1611 ## inside 1612 url5 = HyperlinkNode(self.mkname("url")) 1613 inserter.insertrange(Range(4, 6, url5)) 1614 root = TreeNode() 1615 root.appendchild(url2.dup().appendchild(TextNode("12"))) 1616 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1617 root.appendchild(url4.dup().appendchild(TextNode("4"))) 1618 root.appendchild(url5.dup().appendchild(TextNode("56"))) 1619 root.appendchild(url4.dup().appendchild(TextNode("7"))) 1620 root.appendchild(TextNode("89")) 1621 self.dotest(root, False) 1622 ## empty 1623 url6 = HyperlinkNode(self.mkname("url")) 1624 inserter.insertrange(Range(7, 7, url6)) 1625 root = TreeNode() 1626 root.appendchild(url2.dup().appendchild(TextNode("12"))) 1627 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1628 root.appendchild(url4.dup().appendchild(TextNode("4"))) 1629 root.appendchild(url5.dup().appendchild(TextNode("56"))) 1630 root.appendchild(url4.dup().appendchild(TextNode("7"))) 1631 ## this one gets eaten, but we still need to test inserting it (#i106930#) 1632 # root.appendchild(url6.dup().appendchild(TextNode(""))) 1633 root.appendchild(TextNode("89")) 1634 ## inside (left-edge) 1635 url7 = HyperlinkNode(self.mkname("url")) 1636 inserter.insertrange(Range(0, 1, url7)) 1637 root = TreeNode() 1638 root.appendchild(url7.dup().appendchild(TextNode("1"))) 1639 root.appendchild(url2.dup().appendchild(TextNode("2"))) 1640 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1641 root.appendchild(url4.dup().appendchild(TextNode("4"))) 1642 root.appendchild(url5.dup().appendchild(TextNode("56"))) 1643 root.appendchild(url4.dup().appendchild(TextNode("7"))) 1644 root.appendchild(TextNode("89")) 1645 ## inside (right-edge) 1646 url8 = HyperlinkNode(self.mkname("url")) 1647 inserter.insertrange(Range(5, 6, url8)) 1648 root = TreeNode() 1649 root.appendchild(url7.dup().appendchild(TextNode("1"))) 1650 root.appendchild(url2.dup().appendchild(TextNode("2"))) 1651 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1652 root.appendchild(url4.dup().appendchild(TextNode("4"))) 1653 root.appendchild(url5.dup().appendchild(TextNode("5"))) 1654 root.appendchild(url8.dup().appendchild(TextNode("6"))) 1655 root.appendchild(url4.dup().appendchild(TextNode("7"))) 1656 root.appendchild(TextNode("89")) 1657 self.dotest(root, False) 1658 1659 def test_range_hyperlink_ruby(self): 1660 inserter = RangeInserter(self.__class__.xDoc) 1661 text = TextNode("123456789") 1662 inserter.insertrange(Range(0, 0, text)) 1663 url1 = HyperlinkNode(self.mkname("url")) 1664 inserter.insertrange(Range(1, 4, url1)) 1665 # overlap left 1666 rby2 = RubyNode(self.mkname("ruby")) 1667 inserter.insertrange(Range(0, 2, rby2)) 1668 root = TreeNode() 1669 root.appendchild(rby2.dup() 1670 .appendchild(TextNode("1")) 1671 .appendchild(url1.dup().appendchild(TextNode("2")))) 1672 root.appendchild(url1.dup().appendchild(TextNode("34"))) 1673 root.appendchild(TextNode("56789")) 1674 self.dotest(root, False) 1675 # overlap right 1676 rby3 = RubyNode(self.mkname("ruby")) 1677 inserter.insertrange(Range(3, 5, rby3)) 1678 root = TreeNode() 1679 root.appendchild(rby2.dup() 1680 .appendchild(TextNode("1")) 1681 .appendchild(url1.dup().appendchild(TextNode("2")))) 1682 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1683 root.appendchild(rby3.dup() 1684 .appendchild(url1.dup().appendchild(TextNode("4"))) 1685 .appendchild(TextNode("5"))) 1686 root.appendchild(TextNode("6789")) 1687 self.dotest(root, False) 1688 # around 1689 rby4 = RubyNode(self.mkname("ruby")) 1690 inserter.insertrange(Range(2, 3, rby4)) 1691 root = TreeNode() 1692 root.appendchild(rby2.dup() 1693 .appendchild(TextNode("1")) 1694 .appendchild(url1.dup().appendchild(TextNode("2")))) 1695 root.appendchild(rby4.dup() 1696 .appendchild(url1.dup().appendchild(TextNode("3")))) 1697 root.appendchild(rby3.dup() 1698 .appendchild(url1.dup().appendchild(TextNode("4"))) 1699 .appendchild(TextNode("5"))) 1700 root.appendchild(TextNode("6789")) 1701 self.dotest(root, False) 1702 # inside 1703 url5 = HyperlinkNode(self.mkname("url")) 1704 inserter.insertrange(Range(6, 9, url5)) 1705 rby6 = RubyNode(self.mkname("ruby")) 1706 inserter.insertrange(Range(7, 8, rby6)) 1707 root = TreeNode() 1708 root.appendchild(rby2.dup() 1709 .appendchild(TextNode("1")) 1710 .appendchild(url1.dup().appendchild(TextNode("2")))) 1711 root.appendchild(rby4.dup() 1712 .appendchild(url1.dup().appendchild(TextNode("3")))) 1713 root.appendchild(rby3.dup() 1714 .appendchild(url1.dup().appendchild(TextNode("4"))) 1715 .appendchild(TextNode("5"))) 1716 root.appendchild(TextNode("6")) 1717 root.appendchild(url5.dup().appendchild(TextNode("7"))) 1718 root.appendchild(rby6.dup() 1719 .appendchild(url5.dup().appendchild(TextNode("8")))) 1720 root.appendchild(url5.dup().appendchild(TextNode("9"))) 1721 self.dotest(root, False) 1722 1723 def test_range_ruby_hyperlink(self): 1724 inserter = RangeInserter(self.__class__.xDoc) 1725 text = TextNode("123456789") 1726 inserter.insertrange(Range(0, 0, text)) 1727 rby1 = RubyNode(self.mkname("ruby")) 1728 inserter.insertrange(Range(1, 6, rby1)) 1729 ## overlap left 1730 url2 = HyperlinkNode(self.mkname("url")) 1731 inserter.insertrange(Range(0, 3, url2)) 1732 root = TreeNode() 1733 root.appendchild(url2.dup().appendchild(TextNode("1"))) 1734 root.appendchild(rby1.dup() 1735 .appendchild(url2.dup().appendchild(TextNode("23"))) 1736 .appendchild(TextNode("456"))) 1737 root.appendchild(TextNode("789")) 1738 self.dotest(root, False) 1739 ## overlap right 1740 url3 = HyperlinkNode(self.mkname("url")) 1741 inserter.insertrange(Range(5, 7, url3)) 1742 root = TreeNode() 1743 root.appendchild(url2.dup().appendchild(TextNode("1"))) 1744 root.appendchild(rby1.dup() 1745 .appendchild(url2.dup().appendchild(TextNode("23"))) 1746 .appendchild(TextNode("45")) 1747 .appendchild(url3.dup().appendchild(TextNode("6")))) 1748 root.appendchild(url3.dup().appendchild(TextNode("7"))) 1749 root.appendchild(TextNode("89")) 1750 self.dotest(root, False) 1751 ## around (not quite, due to API) 1752 url4 = HyperlinkNode(self.mkname("url")) 1753 inserter.insertrange(Range(1, 8, url4)) 1754 root = TreeNode() 1755 root.appendchild(url2.dup().appendchild(TextNode("1"))) 1756 root.appendchild(rby1.dup() 1757 .appendchild(url4.dup() 1758 .appendchild(TextNode("23456")))) 1759 root.appendchild(url4.dup().appendchild(TextNode("78"))) 1760 root.appendchild(TextNode("9")) 1761 self.dotest(root, False) 1762 ## inside 1763 url5 = HyperlinkNode(self.mkname("url")) 1764 inserter.insertrange(Range(3, 5, url5)) 1765 root = TreeNode() 1766 root.appendchild(url2.dup().appendchild(TextNode("1"))) 1767 root.appendchild(rby1.dup() 1768 .appendchild(url4.dup() 1769 .appendchild(TextNode("23"))) 1770 .appendchild(url5.dup() 1771 .appendchild(TextNode("45"))) 1772 .appendchild(url4.dup() 1773 .appendchild(TextNode("6")))) 1774 root.appendchild(url4.dup().appendchild(TextNode("78"))) 1775 root.appendchild(TextNode("9")) 1776 self.dotest(root, False) 1777 1778 def test_range_ruby_ruby(self): 1779 inserter = RangeInserter(self.__class__.xDoc) 1780 text = TextNode("123456789") 1781 inserter.insertrange(Range(0, 0, text)) 1782 rby1 = RubyNode(self.mkname("ruby")) 1783 inserter.insertrange(Range(1, 4, rby1)) 1784 ## overlap left 1785 rby2 = RubyNode(self.mkname("ruby")) 1786 inserter.insertrange(Range(0, 2, rby2)) 1787 root = TreeNode() 1788 root.appendchild(rby2.dup().appendchild(TextNode("12"))) 1789 root.appendchild(rby1.dup().appendchild(TextNode("34"))) 1790 root.appendchild(TextNode("56789")) 1791 self.dotest(root, False) 1792 ## overlap right 1793 rby3 = RubyNode(self.mkname("ruby")) 1794 inserter.insertrange(Range(3, 7, rby3)) 1795 root = TreeNode() 1796 root.appendchild(rby2.dup().appendchild(TextNode("12"))) 1797 root.appendchild(rby1.dup().appendchild(TextNode("3"))) 1798 root.appendchild(rby3.dup().appendchild(TextNode("4567"))) 1799 root.appendchild(TextNode("89")) 1800 self.dotest(root, False) 1801 ## around 1802 rby4 = RubyNode(self.mkname("ruby")) 1803 inserter.insertrange(Range(3, 7, rby4)) 1804 root = TreeNode() 1805 root.appendchild(rby2.dup().appendchild(TextNode("12"))) 1806 root.appendchild(rby1.dup().appendchild(TextNode("3"))) 1807 root.appendchild(rby4.dup().appendchild(TextNode("4567"))) 1808 root.appendchild(TextNode("89")) 1809 self.dotest(root, False) 1810 ## inside 1811 rby5 = RubyNode(self.mkname("ruby")) 1812 inserter.insertrange(Range(4, 6, rby5)) 1813 root = TreeNode() 1814 root.appendchild(rby2.dup().appendchild(TextNode("12"))) 1815 root.appendchild(rby1.dup().appendchild(TextNode("3"))) 1816 root.appendchild(rby4.dup().appendchild(TextNode("4"))) 1817 root.appendchild(rby5.dup().appendchild(TextNode("56"))) 1818 root.appendchild(rby4.dup().appendchild(TextNode("7"))) 1819 root.appendchild(TextNode("89")) 1820 self.dotest(root, False) 1821 1822 def test_range_hyperlink_meta(self): 1823 inserter = RangeInserter(self.__class__.xDoc) 1824 text = TextNode("123456789") 1825 inserter.insertrange(Range(0, 0, text)) 1826 url1 = HyperlinkNode(self.mkname("url")) 1827 inserter.insertrange(Range(1, 4, url1)) 1828 ## overlap left 1829 met2 = MetaNode(self.mkid("id")) 1830 inserter.insertrange(Range(0, 2, met2)) 1831 root = TreeNode() 1832 root.appendchild(met2.dup() 1833 .appendchild(TextNode("1")) 1834 .appendchild(url1.dup().appendchild(TextNode("2")))) 1835 root.appendchild(url1.dup().appendchild(TextNode("34"))) 1836 root.appendchild(TextNode("56789")) 1837 self.dotest(root, False) 1838 ## overlap right 1839 met3 = MetaNode(self.mkid("id")) 1840 # inserter.insertrange(Range(4-1, 6-1, met3)) 1841 inserter.insertrange(Range(4, 6, met3)) 1842 root = TreeNode() 1843 root.appendchild(met2.dup() 1844 .appendchild(TextNode("1")) 1845 .appendchild(url1.dup().appendchild(TextNode("2")))) 1846 root.appendchild(url1.dup().appendchild(TextNode("3"))) 1847 root.appendchild(met3.dup() 1848 .appendchild(url1.dup().appendchild(TextNode("4"))) 1849 .appendchild(TextNode("5"))) 1850 root.appendchild(TextNode("6789")) 1851 self.dotest(root, False) 1852 ## around 1853 met4 = MetaNode(self.mkid("id")) 1854 # inserter.insertrange(Range(3-1, 4-1, met4)) 1855 inserter.insertrange(Range(3, 4, met4)) 1856 root = TreeNode() 1857 root.appendchild(met2.dup() 1858 .appendchild(TextNode("1")) 1859 .appendchild(url1.dup().appendchild(TextNode("2")))) 1860 root.appendchild(met4.dup() 1861 .appendchild(url1.dup().appendchild(TextNode("3")))) 1862 root.appendchild(met3.dup() 1863 .appendchild(url1.dup().appendchild(TextNode("4"))) 1864 .appendchild(TextNode("5"))) 1865 root.appendchild(TextNode("6789")) 1866 self.dotest(root, False) 1867 ## inside 1868 url5 = HyperlinkNode(self.mkname("url")) 1869 # inserter.insertrange(Range(9-3, 12-3, url5)) 1870 inserter.insertrange(Range(9, 12, url5)) 1871 met6 = MetaNode(self.mkid("id")) 1872 # inserter.insertrange(Range(10-3, 11-3, met6)) 1873 inserter.insertrange(Range(10, 11, met6)) 1874 root = TreeNode() 1875 root.appendchild(met2.dup() 1876 .appendchild(TextNode("1")) 1877 .appendchild(url1.dup().appendchild(TextNode("2")))) 1878 root.appendchild(met4.dup() 1879 .appendchild(url1.dup().appendchild(TextNode("3")))) 1880 root.appendchild(met3.dup() 1881 .appendchild(url1.dup().appendchild(TextNode("4"))) 1882 .appendchild(TextNode("5"))) 1883 root.appendchild(TextNode("6")) 1884 root.appendchild(url5.dup().appendchild(TextNode("7"))) 1885 root.appendchild(met6.dup() 1886 .appendchild(url5.dup().appendchild(TextNode("8")))) 1887 root.appendchild(url5.dup().appendchild(TextNode("9"))) 1888 self.dotest(root, False) 1889 1890 def test_range_ruby_meta(self): 1891 inserter = RangeInserter(self.__class__.xDoc) 1892 text = TextNode("123456789") 1893 inserter.insertrange(Range(0, 0, text)) 1894 rby1 = RubyNode(self.mkname("ruby")) 1895 inserter.insertrange(Range(1, 4, rby1)) 1896 ## overlap left 1897 met2 = MetaNode(self.mkid("id")) 1898 inserter.insertrange(Range(0, 2, met2)) 1899 root = TreeNode() 1900 root.appendchild(met2.dup() 1901 .appendchild(TextNode("1")) 1902 .appendchild(rby1.dup().appendchild(TextNode("2")))) 1903 root.appendchild(rby1.dup().appendchild(TextNode("34"))) 1904 root.appendchild(TextNode("56789")) 1905 self.dotest(root, False) 1906 ## overlap right 1907 met3 = MetaNode(self.mkid("id")) 1908 # inserter.insertrange(Range(4-1, 6-1, met3)) 1909 inserter.insertrange(Range(4, 6, met3)) 1910 root = TreeNode() 1911 root.appendchild(met2.dup() 1912 .appendchild(TextNode("1")) 1913 .appendchild(rby1.dup().appendchild(TextNode("2")))) 1914 root.appendchild(rby1.dup().appendchild(TextNode("3"))) 1915 root.appendchild(met3.dup() 1916 .appendchild(rby1.dup().appendchild(TextNode("4"))) 1917 .appendchild(TextNode("5"))) 1918 root.appendchild(TextNode("6789")) 1919 self.dotest(root, False) 1920 ## around 1921 met4 = MetaNode(self.mkid("id")) 1922 # inserter.insertrange(Range(3-1, 4-1, met4)) 1923 inserter.insertrange(Range(3, 4, met4)) 1924 root = TreeNode() 1925 root.appendchild(met2.dup() 1926 .appendchild(TextNode("1")) 1927 .appendchild(rby1.dup().appendchild(TextNode("2")))) 1928 root.appendchild(met4.dup() 1929 .appendchild(rby1.dup().appendchild(TextNode("3")))) 1930 root.appendchild(met3.dup() 1931 .appendchild(rby1.dup().appendchild(TextNode("4"))) 1932 .appendchild(TextNode("5"))) 1933 root.appendchild(TextNode("6789")) 1934 self.dotest(root, False) 1935 ## inside 1936 rby5 = RubyNode(self.mkname("ruby")) 1937 # inserter.insertrange(Range(9-3, 12-3, rby5)) 1938 inserter.insertrange(Range(9, 12, rby5)) 1939 met6 = MetaNode(self.mkid("id")) 1940 # inserter.insertrange(Range(10-3, 11-3, met6)) 1941 inserter.insertrange(Range(10, 11, met6)) 1942 root = TreeNode() 1943 root.appendchild(met2.dup() 1944 .appendchild(TextNode("1")) 1945 .appendchild(rby1.dup().appendchild(TextNode("2")))) 1946 root.appendchild(met4.dup() 1947 .appendchild(rby1.dup().appendchild(TextNode("3")))) 1948 root.appendchild(met3.dup() 1949 .appendchild(rby1.dup().appendchild(TextNode("4"))) 1950 .appendchild(TextNode("5"))) 1951 root.appendchild(TextNode("6")) 1952 root.appendchild(rby5.dup() 1953 .appendchild(TextNode("7")) 1954 .appendchild(met6.dup() 1955 .appendchild(TextNode("8"))) 1956 .appendchild(TextNode("9"))) 1957 self.dotest(root, False) 1958 1959 def test_range_meta_hyperlink(self): 1960 inserter = RangeInserter(self.__class__.xDoc) 1961 text = TextNode("123456789") 1962 inserter.insertrange(Range(0, 0, text)) 1963 met1 = MetaNode(self.mkid("id")) 1964 inserter.insertrange(Range(1, 6, met1)) 1965 ## overlap left 1966 url2 = HyperlinkNode(self.mkname("url")) 1967 # inserter.insertrange(Range(0, 4-1, url2)) 1968 inserter.insertrange(Range(0, 4, url2)) 1969 root = TreeNode() 1970 root.appendchild(url2.dup().appendchild(TextNode("1"))) 1971 root.appendchild(met1.dup() 1972 .appendchild(url2.dup().appendchild(TextNode("23"))) 1973 .appendchild(TextNode("456"))) 1974 root.appendchild(TextNode("789")) 1975 self.dotest(root, False) 1976 ## overlap right 1977 url3 = HyperlinkNode(self.mkname("url")) 1978 # inserter.insertrange(Range(6-1, 8-1, url3)) 1979 inserter.insertrange(Range(6, 8, url3)) 1980 root = TreeNode() 1981 root.appendchild(url2.dup().appendchild(TextNode("1"))) 1982 root.appendchild(met1.dup() 1983 .appendchild(url2.dup().appendchild(TextNode("23"))) 1984 .appendchild(TextNode("45")) 1985 .appendchild(url3.dup().appendchild(TextNode("6")))) 1986 root.appendchild(url3.dup().appendchild(TextNode("7"))) 1987 root.appendchild(TextNode("89")) 1988 self.dotest(root, False) 1989 ## around (not quite, due to API) 1990 url4 = HyperlinkNode(self.mkname("url")) 1991 # inserter.insertrange(Range(1, 9-1, url4)) 1992 inserter.insertrange(Range(1, 9, url4)) 1993 root = TreeNode() 1994 root.appendchild(url2.dup().appendchild(TextNode("1"))) 1995 root.appendchild(met1.dup() 1996 .appendchild(url4.dup() 1997 .appendchild(TextNode("23456")))) 1998 root.appendchild(url4.dup().appendchild(TextNode("78"))) 1999 root.appendchild(TextNode("9")) 2000 self.dotest(root, False) 2001 ## inside 2002 url5 = HyperlinkNode(self.mkname("url")) 2003 # inserter.insertrange(Range(4-1, 6-1, url5)) 2004 inserter.insertrange(Range(4, 6, url5)) 2005 root = TreeNode() 2006 root.appendchild(url2.dup().appendchild(TextNode("1"))) 2007 root.appendchild(met1.dup() 2008 .appendchild(url4.dup() 2009 .appendchild(TextNode("23"))) 2010 .appendchild(url5.dup() 2011 .appendchild(TextNode("45"))) 2012 .appendchild(url4.dup() 2013 .appendchild(TextNode("6")))) 2014 root.appendchild(url4.dup().appendchild(TextNode("78"))) 2015 root.appendchild(TextNode("9")) 2016 self.dotest(root, False) 2017 2018 def test_range_meta_ruby(self): 2019 inserter = RangeInserter(self.__class__.xDoc) 2020 text = TextNode("123456789") 2021 inserter.insertrange(Range(0, 0, text)) 2022 met1 = MetaNode(self.mkid("id")) 2023 inserter.insertrange(Range(1, 5, met1)) 2024 ## overlap left 2025 rby2 = RubyNode(self.mkname("ruby")) 2026 # inserter.insertrange(Range(0, 3-1, rby2)) 2027 inserter.insertrange(Range(0, 3, rby2)) 2028 root = TreeNode() 2029 root.appendchild(rby2.dup().appendchild(TextNode("1"))) 2030 root.appendchild(met1.dup() 2031 .appendchild(rby2.dup().appendchild(TextNode("2"))) 2032 .appendchild(TextNode("345"))) 2033 root.appendchild(TextNode("6789")) 2034 self.dotest(root, False) 2035 ## overlap right 2036 rby3 = RubyNode(self.mkname("ruby")) 2037 # inserter.insertrange(Range(5-1, 7-1, rby3)) 2038 inserter.insertrange(Range(5, 7, rby3)) 2039 root = TreeNode() 2040 root.appendchild(rby2.dup().appendchild(TextNode("1"))) 2041 root.appendchild(met1.dup() 2042 .appendchild(rby2.dup().appendchild(TextNode("2"))) 2043 .appendchild(TextNode("34")) 2044 .appendchild(rby3.dup().appendchild(TextNode("5")))) 2045 root.appendchild(rby3.dup().appendchild(TextNode("6"))) 2046 root.appendchild(TextNode("789")) 2047 self.dotest(root, False) 2048 ## // around 2049 rby4 = RubyNode(self.mkname("ruby")) 2050 # inserter.insertrange(Range(1, 7-1, rby4)) 2051 inserter.insertrange(Range(1, 7, rby4)) 2052 root = TreeNode() 2053 root.appendchild(rby2.dup().appendchild(TextNode("1"))) 2054 root.appendchild(rby4.dup() 2055 .appendchild(met1.dup() 2056 .appendchild(TextNode("2345"))) 2057 .appendchild(TextNode("6"))) 2058 root.appendchild(TextNode("789")) 2059 self.dotest(root, False) 2060 ## inside 2061 met5 = MetaNode(self.mkid("id")) 2062 # inserter.insertrange(Range(7-1, 9-1, met5)) 2063 inserter.insertrange(Range(7, 9, met5)) 2064 rby6 = RubyNode(self.mkname("ruby")) 2065 # inserter.insertrange(Range(9-2, 10/-2, rby6)) 2066 inserter.insertrange(Range(9, 10, rby6)) 2067 root = TreeNode() 2068 root.appendchild(rby2.dup().appendchild(TextNode("1"))) 2069 root.appendchild(rby4.dup() 2070 .appendchild(met1.dup() 2071 .appendchild(TextNode("2345"))) 2072 .appendchild(TextNode("6"))) 2073 root.appendchild(met5.dup() 2074 .appendchild(TextNode("7")) 2075 .appendchild(rby6.dup() 2076 .appendchild(TextNode("8")))) 2077 root.appendchild(TextNode("9")) 2078 self.dotest(root, False) 2079 ## inside, with invalid range that includes the dummy char 2080 rby7 = RubyNode(self.mkname("ruby")) 2081 # inserter.insertrange(Range(7-1, 9-2, rby7)) 2082 inserter.insertrange(Range(7, 9, rby7)) 2083 root = TreeNode() 2084 root.appendchild(rby2.dup().appendchild(TextNode("1"))) 2085 root.appendchild(rby4.dup() 2086 .appendchild(met1.dup() 2087 .appendchild(TextNode("2345"))) 2088 .appendchild(TextNode("6"))) 2089 root.appendchild(met5.dup() 2090 .appendchild(rby7.dup() 2091 .appendchild(TextNode("7"))) 2092 .appendchild(rby6.dup() 2093 .appendchild(TextNode("8")))) 2094 root.appendchild(TextNode("9")) 2095 self.dotest(root, False) 2096 ## around, at same position as meta 2097 rby8 = RubyNode(self.mkname("ruby")) 2098 # inserter.insertrange(Range(7-1, 10-2, rby8)) 2099 inserter.insertrange(Range(7, 10, rby8)) 2100 root = TreeNode() 2101 root.appendchild(rby2.dup().appendchild(TextNode("1"))) 2102 root.appendchild(rby4.dup() 2103 .appendchild(met1.dup() 2104 .appendchild(TextNode("2345"))) 2105 .appendchild(TextNode("6"))) 2106 root.appendchild(rby8.dup() 2107 .appendchild(met5.dup() 2108 .appendchild(TextNode("78")))) 2109 root.appendchild(TextNode("9")) 2110 self.dotest(root, False) 2111 2112 def test_range_meta_meta(self): 2113 inserter = RangeInserter(self.__class__.xDoc) 2114 text = TextNode("123456789") 2115 inserter.insertrange(Range(0, 0, text)) 2116 met1 = MetaNode(self.mkid("id")) 2117 inserter.insertrange(Range(3, 6, met1)) 2118 ## overlap left 2119 met2 = MetaNode(self.mkid("id")) 2120 try: 2121 inserter.insertrange(Range(0, 4, met2)) 2122 fail("testRangeMetaMeta: overlap left allowed") 2123 except IllegalArgumentException: 2124 pass 2125 root = TreeNode() 2126 root.appendchild(TextNode("123")) 2127 root.appendchild(met1.dup().appendchild(TextNode("456"))) 2128 root.appendchild(TextNode("789")) 2129 self.dotest(root, False) 2130 ## overlap right 2131 met3 = MetaNode(self.mkid("id")) 2132 2133 try: 2134 # inserter.insertrange(Range(5-1, 8-1, met3)) 2135 inserter.insertrange(Range(5, 8, met3)) 2136 self.fail("testRangeMetaMeta: overlap right allowed") 2137 except IllegalArgumentException: 2138 pass 2139 2140 root = TreeNode() 2141 root.appendchild(TextNode("123")) 2142 root.appendchild(met1.dup().appendchild(TextNode("456"))) 2143 root.appendchild(TextNode("789")) 2144 self.dotest(root, False) 2145 ## around 2146 met4 = MetaNode(self.mkid("id")) 2147 # inserter.insertrange(Range(3, 7-1, met4)) 2148 inserter.insertrange(Range(3, 7, met4)) 2149 root = TreeNode() 2150 root.appendchild(TextNode("123")) 2151 root.appendchild(met4.dup() 2152 .appendchild(met1.dup().appendchild(TextNode("456")))) 2153 root.appendchild(TextNode("789")) 2154 self.dotest(root, False) 2155 ## inside 2156 met5 = MetaNode(self.mkid("id")) 2157 # inserter.insertrange(Range(6-2, 8-2, met5)) 2158 inserter.insertrange(Range(6, 8, met5)) 2159 root = TreeNode() 2160 root.appendchild(TextNode("123")) 2161 root.appendchild(met4.dup() 2162 .appendchild(met1.dup() 2163 .appendchild(TextNode("4")) 2164 .appendchild(met5.dup() 2165 .appendchild(TextNode("56"))))) 2166 root.appendchild(TextNode("789")) 2167 self.dotest(root, False) 2168 2169 def test_range2(self): 2170 inserter = RangeInserter(self.__class__.xDoc) 2171 text = TextNode("123456789") 2172 inserter.insertrange(Range(0, 0, text)) 2173 met1 = MetaNode(self.mkid("id")) 2174 inserter.insertrange(Range(1, 8, met1)) 2175 met2 = MetaNode(self.mkid("id")) 2176 # inserter.insertrange(Range(3-1, 8-1, met2)) 2177 inserter.insertrange(Range(3, 8, met2)) 2178 met3 = MetaNode(self.mkid("id")) 2179 # inserter.insertrange(Range(5-2, 8-2, met3)) 2180 inserter.insertrange(Range(5, 8, met3)) 2181 root = TreeNode() 2182 root.appendchild(TextNode("1")) 2183 root.appendchild(met1.dup() 2184 .appendchild(TextNode("2")) 2185 .appendchild(met2.dup() 2186 .appendchild(TextNode("3")) 2187 .appendchild(met3.dup() 2188 .appendchild(TextNode("456"))) 2189 .appendchild(TextNode("7"))) 2190 .appendchild(TextNode("8"))) 2191 root.appendchild(TextNode("9")) 2192 self.dotest(root, False) 2193 ## split ruby at every meta start! 2194 rby4 = RubyNode(self.mkname("ruby")) 2195 # inserter.insertrange(Range(0, 7-3, rby4)) 2196 inserter.insertrange(Range(0, 7, rby4)) 2197 root = TreeNode() 2198 root.appendchild(rby4.dup() 2199 .appendchild(TextNode("1"))) 2200 root.appendchild(met1.dup() 2201 .appendchild(rby4.dup() 2202 .appendchild(TextNode("2"))) 2203 .appendchild(met2.dup() 2204 .appendchild(rby4.dup() 2205 .appendchild(TextNode("3"))) 2206 .appendchild(met3.dup() 2207 .appendchild(rby4.dup() 2208 .appendchild(TextNode("4"))) 2209 .appendchild(TextNode("56"))) 2210 .appendchild(TextNode("7"))) 2211 .appendchild(TextNode("8"))) 2212 root.appendchild(TextNode("9")) 2213 self.dotest(root, False) 2214 ## split ruby at every meta end! 2215 rby5 = RubyNode(self.mkname("ruby")) 2216 # inserter.insertrange(Range(8-3, 12-3, rby5)) 2217 inserter.insertrange(Range(8, 12, rby5)) 2218 root = TreeNode() 2219 root.appendchild(rby4.dup() 2220 .appendchild(TextNode("1"))) 2221 root.appendchild(met1.dup() 2222 .appendchild(rby4.dup() 2223 .appendchild(TextNode("2"))) 2224 .appendchild(met2.dup() 2225 .appendchild(rby4.dup() 2226 .appendchild(TextNode("3"))) 2227 .appendchild(met3.dup() 2228 .appendchild(rby4.dup() 2229 .appendchild(TextNode("4"))) 2230 .appendchild(TextNode("5")) 2231 .appendchild(rby5.dup() 2232 .appendchild(TextNode("6")))) 2233 .appendchild(rby5.dup() 2234 .appendchild(TextNode("7")))) 2235 .appendchild(rby5.dup() 2236 .appendchild(TextNode("8")))) 2237 root.appendchild(rby5.dup() 2238 .appendchild(TextNode("9"))) 2239 self.dotest(root, False) 2240 2241 def test_range3(self): 2242 inserter = RangeInserter(self.__class__.xDoc) 2243 text = TextNode("123456789") 2244 inserter.insertrange(Range(0, 0, text)) 2245 rby1 = RubyNode(self.mkname("ruby")) 2246 inserter.insertrange(Range(0, 9, rby1)) 2247 met2 = MetaNode(self.mkid("id")) 2248 inserter.insertrange(Range(2, 7, met2)) 2249 root = TreeNode() 2250 root.appendchild(rby1.dup() 2251 .appendchild(TextNode("12")) 2252 .appendchild(met2.dup() 2253 .appendchild(TextNode("34567"))) 2254 .appendchild(TextNode("89"))) 2255 self.dotest(root, False) 2256 ## overwrite outer ruby, split remains at inner meta! 2257 rby3 = RubyNode(self.mkname("ruby")) 2258 # inserter.insertrange(Range(5-1, 6-1, rby3)) 2259 inserter.insertrange(Range(5, 6, rby3)) 2260 root = TreeNode() 2261 root.appendchild(rby1.dup() 2262 .appendchild(TextNode("12"))) 2263 root.appendchild(met2.dup() 2264 .appendchild(rby1.dup() 2265 .appendchild(TextNode("34"))) 2266 .appendchild(rby3.dup() 2267 .appendchild(TextNode("5"))) 2268 .appendchild(rby1.dup() 2269 .appendchild(TextNode("67")))) 2270 root.appendchild(rby1.dup() 2271 .appendchild(TextNode("89"))) 2272 self.dotest(root, False) 2273 2274 def test_range4(self): 2275 inserter = RangeInserter(self.__class__.xDoc) 2276 text = TextNode("123456789") 2277 inserter.insertrange(Range(0, 0, text)) 2278 rby1 = RubyNode(self.mkname("ruby")) 2279 inserter.insertrange(Range(0, 9, rby1)) 2280 met2 = MetaNode(self.mkid("id")) 2281 inserter.insertrange(Range(1, 8, met2)) 2282 met3 = MetaNode(self.mkid("id")) 2283 # inserter.insertrange(Range(3-1, 8-1, met3)) 2284 inserter.insertrange(Range(3, 8, met3)) 2285 met4 = MetaNode(self.mkid("id")) 2286 # inserter.insertrange(Range(5-2, 8-2, met4)) 2287 inserter.insertrange(Range(5, 8, met4)) 2288 root = TreeNode() 2289 root.appendchild(rby1.dup() 2290 .appendchild(TextNode("1")) 2291 .appendchild(met2.dup() 2292 .appendchild(TextNode("2")) 2293 .appendchild(met3.dup() 2294 .appendchild(TextNode("3")) 2295 .appendchild(met4.dup() 2296 .appendchild(TextNode("456"))) 2297 .appendchild(TextNode("7"))) 2298 .appendchild(TextNode("8"))) 2299 .appendchild(TextNode("9"))) 2300 self.dotest(root, False) 2301 ## overwrite outer ruby, split remains at every inner meta! 2302 rby5 = RubyNode(self.mkname("ruby")) 2303 # inserter.insertrange(Range(7-3, 8-3, rby5)) 2304 inserter.insertrange(Range(7, 8, rby5)) 2305 root = TreeNode() 2306 root.appendchild(rby1.dup() 2307 .appendchild(TextNode("1"))) 2308 root.appendchild(met2.dup() 2309 .appendchild(rby1.dup() 2310 .appendchild(TextNode("2"))) 2311 .appendchild(met3.dup() 2312 .appendchild(rby1.dup() 2313 .appendchild(TextNode("3"))) 2314 .appendchild(met4.dup() 2315 .appendchild(rby1.dup() 2316 .appendchild(TextNode("4"))) 2317 .appendchild(rby5.dup() 2318 .appendchild(TextNode("5"))) 2319 .appendchild(rby1.dup() 2320 .appendchild(TextNode("6")))) 2321 .appendchild(rby1.dup() 2322 .appendchild(TextNode("7")))) 2323 .appendchild(rby1.dup() 2324 .appendchild(TextNode("8")))) 2325 root.appendchild(rby1.dup() 2326 .appendchild(TextNode("9"))) 2327 self.dotest(root, False) 2328 2329 def test_range5(self): 2330 inserter = RangeInserter(self.__class__.xDoc) 2331 text = TextNode("123456789") 2332 inserter.insertrange(Range(0, 0, text)) 2333 rby1 = RubyNode(self.mkname("ruby")) 2334 inserter.insertrange(Range(0, 9, rby1)) 2335 met2 = MetaNode(self.mkid("id")) 2336 inserter.insertrange(Range(1, 3, met2)) 2337 met3 = MetaNode(self.mkid("id")) 2338 # inserter.insertrange(Range(5-1, 6-1, met3)) 2339 inserter.insertrange(Range(5, 6, met3)) 2340 met4 = MetaNode(self.mkid("id")) 2341 # inserter.insertrange(Range(8-2, 10-2, met4)) 2342 inserter.insertrange(Range(8, 10, met4)) 2343 root = TreeNode() 2344 root.appendchild(rby1.dup() 2345 .appendchild(TextNode("1")) 2346 .appendchild(met2.dup().appendchild(TextNode("23"))) 2347 .appendchild(TextNode("4")) 2348 .appendchild(met3.dup().appendchild(TextNode("5"))) 2349 .appendchild(TextNode("6")) 2350 .appendchild(met4.dup().appendchild(TextNode("78"))) 2351 .appendchild(TextNode("9"))) 2352 self.dotest(root, False) 2353 ## overwrite outer ruby, but split at inner metas! 2354 rby5 = RubyNode(self.mkname("ruby")) 2355 # inserter.insertrange(Range(3-1, 10-3, rby5)) 2356 inserter.insertrange(Range(3, 10, rby5)) 2357 root = TreeNode() 2358 root.appendchild(rby1.dup() 2359 .appendchild(TextNode("1"))) 2360 root.appendchild(met2.dup() 2361 .appendchild(rby1.dup() 2362 .appendchild(TextNode("2"))) 2363 .appendchild(rby5.dup() 2364 .appendchild(TextNode("3")))) 2365 root.appendchild(rby5.dup() 2366 .appendchild(TextNode("4")) 2367 .appendchild(met3.dup() 2368 .appendchild(TextNode("5"))) 2369 .appendchild(TextNode("6"))) 2370 root.appendchild(met4.dup() 2371 .appendchild(rby5.dup() 2372 .appendchild(TextNode("7"))) 2373 .appendchild(rby1.dup() 2374 .appendchild(TextNode("8")))) 2375 root.appendchild(rby1.dup() 2376 .appendchild(TextNode("9"))) 2377 self.dotest(root, False) 2378 2379 def test_range6(self): 2380 inserter = RangeInserter(self.__class__.xDoc) 2381 text = TextNode("123456789") 2382 inserter.insertrange(Range(0, 0, text)) 2383 met1 = MetaNode(self.mkid("id")) 2384 inserter.insertrange(Range(1, 5, met1)) 2385 met2 = MetaNode(self.mkid("id")) 2386 # inserter.insertrange(Range(3-1, 6-1, met2)) 2387 inserter.insertrange(Range(3, 6, met2)) 2388 met3 = MetaNode(self.mkid("id")) 2389 # inserter.insertrange(Range(5-2, 7-2, met3)) 2390 inserter.insertrange(Range(5, 7, met3)) 2391 root = TreeNode() 2392 root.appendchild(TextNode("1")) 2393 root.appendchild(met1.dup() 2394 .appendchild(TextNode("2")) 2395 .appendchild(met2.dup() 2396 .appendchild(TextNode("3")) 2397 .appendchild(met3.dup() 2398 .appendchild(TextNode("45"))))) 2399 root.appendchild(TextNode("6789")) 2400 self.dotest(root, False) 2401 ## split at 3 metas, all at same position 2402 rby4 = RubyNode(self.mkname("ruby")) 2403 # inserter.insertrange(Range(7-3, 10-3, rby4)) 2404 inserter.insertrange(Range(7, 10, rby4)) 2405 root = TreeNode() 2406 root.appendchild(TextNode("1")) 2407 root.appendchild(met1.dup() 2408 .appendchild(TextNode("2")) 2409 .appendchild(met2.dup() 2410 .appendchild(TextNode("3")) 2411 .appendchild(met3.dup() 2412 .appendchild(TextNode("4")) 2413 .appendchild(rby4.dup() 2414 .appendchild(TextNode("5")))))) 2415 root.appendchild(rby4.dup() 2416 .appendchild(TextNode("67"))) 2417 root.appendchild(TextNode("89")) 2418 self.dotest(root, False) 2419 2420 def test_range7(self): 2421 inserter = RangeInserter(self.__class__.xDoc) 2422 text = TextNode("123456789") 2423 inserter.insertrange(Range(0, 0, text)) 2424 url1 = HyperlinkNode(self.mkname("url")) 2425 inserter.insertrange(Range(1, 5, url1)) 2426 met2 = MetaNode(self.mkid("id")) 2427 inserter.insertrange(Range(3, 5, met2)) 2428 root = TreeNode() 2429 root.appendchild(TextNode("1")) 2430 root.appendchild(url1.dup() 2431 .appendchild(TextNode("23"))) 2432 root.appendchild(met2.dup() 2433 .appendchild(url1.dup() 2434 .appendchild(TextNode("45")))) 2435 root.appendchild(TextNode("6789")) 2436 self.dotest(root, False) 2437 ## this should result in not splitting the hyperlink, but due to API 2438 ## we can't tell :( 2439 rby3 = RubyNode(self.mkname("ruby")) 2440 # inserter.insertrange(Range(5-1, 8-1, rby3)) 2441 inserter.insertrange(Range(5, 8, rby3)) 2442 root = TreeNode() 2443 root.appendchild(TextNode("1")) 2444 root.appendchild(url1.dup() 2445 .appendchild(TextNode("23"))) 2446 root.appendchild(met2.dup() 2447 .appendchild(url1.dup() 2448 .appendchild(TextNode("4"))) 2449 .appendchild(rby3.dup() 2450 .appendchild(url1.dup() 2451 .appendchild(TextNode("5"))))) 2452 root.appendchild(rby3.dup() 2453 .appendchild(TextNode("67"))) 2454 root.appendchild(TextNode("89")) 2455 self.dotest(root, False) 2456 2457 # TODO: test partial selection, test UNDO/REDO 2458 2459 ##i109601# NestedTextContent and XChild 2460 def test_meta_xchild(self): 2461 xDoc = self.__class__.xDoc 2462 id1 = StringPair("content.xml", self.mkname("id")) 2463 id2 = StringPair("content.xml", self.mkname("id")) 2464 id3 = StringPair("content.xml", self.mkname("id")) 2465 id4 = StringPair("content.xml", self.mkname("id")) 2466 id5 = StringPair("content.xml", self.mkname("id")) 2467 id6 = StringPair("content.xml", self.mkname("id")) 2468 meta1 = MetaNode(id1) 2469 meta2 = MetaNode(id2) 2470 meta3 = MetaFieldNode(id3) 2471 meta4 = MetaNode(id4) 2472 meta5 = MetaNode(id5) 2473 meta6 = MetaFieldNode(id6) 2474 root = TreeNode() 2475 root.appendchild(meta1.dup() 2476 .appendchild(TextNode("1"))) 2477 root.appendchild(TextNode("2")) 2478 root.appendchild(meta2.dup() 2479 .appendchild(meta3.dup() 2480 .appendchild(TextNode("34")) 2481 .appendchild(meta4.dup() 2482 .appendchild(TextNode("56"))) 2483 .appendchild(meta5.dup()) 2484 .appendchild(TextNode("7")))) 2485 root.appendchild(TextNode("8")) 2486 root.appendchild(meta6.dup() 2487 .appendchild(TextNode("9"))) 2488 2489 inserter = RangeInserter(xDoc) 2490 text = TextNode("123456789") 2491 inserter.insertrange(Range(0, 0, text)) 2492 xMeta1 = inserter.insertrange(Range(0, 1, meta1)) 2493 xMeta2 = inserter.insertrange(Range(3, 8, meta2)) 2494 xMeta3 = inserter.insertrange(Range(4, 9, meta3)) 2495 xMeta4 = inserter.insertrange(Range(7, 9, meta4)) 2496 xMeta5 = inserter.insertrange(Range(10, 10, meta5)) 2497 xMeta6 = inserter.insertrange(Range(13, 14, meta6)) 2498 2499 self.dotest(root, False) 2500 2501 xDocText = xDoc.getText() 2502 xDocTextCursor = xDocText.createTextCursor() 2503 xDocTextCursor.gotoNextParagraph(False) # second paragraph 2504 # X12XX34X56X78X9 2505 # 1 23 4 5 6 2506 # 1 452 6 2507 # 3 2508 nestedTextContent = ( 2509 None, 2510 id1, 2511 id1, 2512 None, 2513 id2, 2514 id3, 2515 id3, 2516 id3, 2517 id4, 2518 id4, 2519 id4, 2520 id5, 2521 id3, 2522 None, 2523 id6, 2524 id6) 2525 for i, ntc in enumerate(nestedTextContent): 2526 oNTC = xDocTextCursor.NestedTextContent 2527 if ntc is None: 2528 self.assertIsNone(oNTC, 2529 "unexpected NestedTextContent at: {}".format(i)) 2530 else: 2531 xmlid = oNTC.MetadataReference 2532 self.assertTrue(MetaNode.eq(ntc, xmlid), 2533 "wrong NestedTextContent at: {}".format(i)) 2534 xDocTextCursor.goRight(1, False) 2535 2536 try: 2537 xMeta1.setParent(xMeta4) 2538 fail("setParent(): allowed?") 2539 except NoSupportException: 2540 pass 2541 self.assertIsNone(xMeta1.getParent(), "getParent(): not None") 2542 self.assertIsNone(xMeta2.getParent(), "getParent(): not None") 2543 self.assertIsNone(xMeta6.getParent(), "getParent(): not None") 2544 2545 xParent3 = xMeta3.getParent() 2546 self.assertIsNotNone(xParent3, "getParent(): None") 2547 xmlid = xParent3.MetadataReference 2548 self.assertTrue(MetaNode.eq(xmlid, id2), "getParent(): wrong") 2549 2550 xParent4 = xMeta4.getParent() 2551 self.assertIsNotNone(xParent4, "getParent(): None") 2552 xmlid = xParent4.MetadataReference 2553 self. assertTrue(MetaNode.eq(xmlid, id3), "getParent(): wrong") 2554 2555 xParent5 = xMeta5.getParent() 2556 self.assertIsNotNone(xParent5, "getParent(): None") 2557 xmlid = xParent5.MetadataReference 2558 self.assertTrue(MetaNode.eq(xmlid, id3), "getParent(): wrong") 2559 2560 # test SwXMeta XText interface 2561 def test_meta_xtext(self): 2562 xDoc = self.__class__.xDoc 2563 inserter = RangeInserter(xDoc) 2564 text = TextNode("12AB6789") 2565 inserter.insertrange(Range(0, 0, text)) 2566 meta = MetaNode(self.mkid("id")) 2567 xMeta = inserter.makemeta() 2568 2569 xDocText = xDoc.getText() 2570 xDocTextCursor = xDocText.createTextCursor() 2571 xDocTextCursor.goRight(3, False) 2572 xDocTextCursor.goRight(2, True) 2573 xDocText.insertTextContent(xDocTextCursor, xMeta, True) 2574 2575 xMeta.MetadataReference = meta.xmlid 2576 xParentText = xMeta.getText() 2577 self.assertIsNotNone(xParentText, "getText(): no parent") 2578 2579 xStart = xMeta.getStart() 2580 self.assertIsNotNone(xStart, "getStart(): no start") 2581 2582 xEnd = xMeta.getEnd() 2583 self.assertIsNotNone(xEnd, "getEnd(): no end") 2584 2585 xMeta.setString("45") 2586 2587 string = xMeta.getString() 2588 self.assertEqual("45", string, "getString(): invalid string returned") 2589 2590 xTextCursor = xMeta.createTextCursor() 2591 self.assertIsNotNone(xTextCursor, "createTextCursor(): failed") 2592 2593 try: 2594 xMeta.createTextCursorByRange(None) 2595 fail("createTextCursorByRange(): None allowed?") 2596 except RuntimeException: 2597 pass 2598 2599 xTextCursorStart = xMeta.createTextCursorByRange(xStart) 2600 self.assertIsNotNone(xTextCursorStart, 2601 "createTextCursorByRange(): failed for start") 2602 2603 xTextCursorEnd = xMeta.createTextCursorByRange(xEnd) 2604 self.assertIsNotNone(xTextCursorEnd, 2605 "createTextCursorByRange(): failed for end") 2606 2607 ## move outside meta 2608 xDocTextCursor.gotoStart(False) 2609 2610 try: 2611 xMeta.insertString(None, "foo", False) 2612 fail("insertString(): None allowed?") 2613 except RuntimeException: 2614 pass 2615 2616 try: 2617 xMeta.insertString(xDocTextCursor, "foo", False) 2618 fail("insertString(): cursor outside allowed?") 2619 except RuntimeException: 2620 pass 2621 2622 xStart = xMeta.getStart() 2623 xMeta.insertString(xStart, "A", False) 2624 string = xMeta.getString() 2625 self.assertEqual("A45", string, "getString(): invalid string returned") 2626 2627 xMeta.insertString(xEnd, "B", False) 2628 string = xMeta.getString() 2629 self.assertEqual("A45B", string, "getString(): invalid string returned") 2630 2631 try: 2632 xMeta.insertControlCharacter(None, HARD_HYPHEN, False) 2633 fail("insertControlCharacter(): None allowed?") 2634 except IllegalArgumentException: 2635 pass 2636 2637 xStart = xMeta.getStart() 2638 try: 2639 xMeta.insertControlCharacter(xDocTextCursor, HARD_HYPHEN, False) 2640 fail("insertControlCharacter(): cursor outside allowed?") 2641 except IllegalArgumentException: 2642 pass 2643 2644 xMeta.insertControlCharacter(xStart, HARD_HYPHEN, False) 2645 string = xMeta.getString() 2646 self.assertEqual('\u2011' + 'A45B', string, 2647 "getString(): invalid string returned") 2648 2649 xMeta.insertControlCharacter(xEnd, HARD_HYPHEN, False) 2650 string = xMeta.getString() 2651 self.assertEqual('\u2011' + 'A45B' + '\u2011', string, 2652 "getString(): invalid string returned") 2653 2654 xMeta.setString("45") 2655 try: 2656 xMeta.insertTextContent(None, xMeta, False) 2657 fail("insertTextContent(): None range allowed?") 2658 except IllegalArgumentException: 2659 pass 2660 2661 try: 2662 xMeta.insertTextContent(xStart, None, False) 2663 fail("insertTextContent(): None content allowed?") 2664 except IllegalArgumentException: 2665 pass 2666 2667 try: 2668 xMeta.insertTextContent(xDocTextCursor, xMeta, False) 2669 fail("insertTextContent(): cursor outside allowed?") 2670 except IllegalArgumentException: 2671 pass 2672 2673 field1 = TextFieldNode("f1") 2674 field2 = TextFieldNode("f2") 2675 xField1 = inserter.maketextfield(field1.content) 2676 xField2 = inserter.maketextfield(field2.content) 2677 2678 xStart = xMeta.getStart() 2679 xMeta.insertTextContent(xStart, xField1, False) 2680 2681 root = TreeNode() 2682 root.appendchild(TextNode("12")) 2683 root.appendchild(meta.dup() 2684 .appendchild(field1.dup()) 2685 .appendchild(TextNode("45"))) 2686 root.appendchild(TextNode("6789")) 2687 self.dotest(root, False) 2688 2689 xMeta.insertTextContent(xEnd, xField2, False) 2690 2691 root = TreeNode() 2692 root.appendchild(TextNode("12")) 2693 root.appendchild(meta.dup() 2694 .appendchild(field1.dup()) 2695 .appendchild(TextNode("45")) 2696 .appendchild(field2.dup())) 2697 root.appendchild(TextNode("6789")) 2698 self.dotest(root, False) 2699 2700 try: 2701 xMeta.removeTextContent(None) 2702 fail("removeTextContent(): None content allowed?") 2703 except RuntimeException: 2704 pass 2705 2706 xMeta.removeTextContent(xField1) 2707 2708 xAnchor = xMeta.getAnchor() 2709 self.assertIsNotNone(xAnchor, "getAnchor(): None") 2710 2711 ## evil test case: insert ruby around meta 2712 ruby = RubyNode(self.mkname("ruby")) 2713 inserter.insertrange(Range(2, 6, ruby)) 2714 2715 ## prevent caching... 2716 # root = TreeNode() 2717 # root.appendchild(TextNode("12")) 2718 # root.appendchild(ruby.dup() 2719 # .appendchild(meta.dup() 2720 # .appendchild(TextNode("45")) 2721 # .appendchild(field2.dup()))) 2722 # root.appendchild(TextNode("6789")) 2723 # self.dotest(root, False) 2724 2725 xEnum = xMeta.createEnumeration() 2726 self.assertIsNotNone("createEnumeration(): returns None", xEnum) 2727 2728 self.assertTrue(xEnum.hasMoreElements(),"hasNext(): first missing") 2729 xPortion = xEnum.nextElement() 2730 type_ = xPortion.TextPortionType 2731 self.assertEqual("Text", type_, "first: not text") 2732 txt = xPortion.getString() 2733 self.assertEqual("45", txt, "first: text differs") 2734 2735 self.assertTrue(xEnum.hasMoreElements(),"hasNext(): second missing") 2736 xPortion = xEnum.nextElement() 2737 type_ = xPortion.TextPortionType 2738 self.assertEqual("TextField", type_, "second: not text") 2739 2740 ## no ruby end here!!! 2741 self.assertFalse(xEnum.hasMoreElements(), "hasNext(): more elements?") 2742 2743 xMeta.dispose() 2744 2745 try: 2746 xCursor = xMeta.createTextCursor() 2747 self.assertIsNone(xCursor, 2748 "createTextCursor(): succeeds on disposed object?") 2749 except RuntimeException: 2750 pass 2751 2752 # check that cursor move methods move to positions in the meta, 2753 # but do not move to positions outside the meta. 2754 def test_meta_xtextcursor(self): 2755 xDoc = self.__class__.xDoc 2756 inserter = RangeInserter(xDoc) 2757 text = TextNode("Text. 12 More text here.") 2758 inserter.insertrange(Range(0, 0, text)) 2759 met1 = MetaNode(self.mkid("id")) 2760 xMeta = inserter.makemeta() 2761 2762 xDocText = xDoc.getText() 2763 xDocTextCursor = xDocText.createTextCursor() 2764 xDocTextCursor.goRight(7, False) 2765 xDocTextCursor.goRight(2, True) 2766 xDocText.insertTextContent(xDocTextCursor, xMeta, True) 2767 xDocTextCursor.gotoStart(True) 2768 2769 xMeta.MetadataReference = met1.xmlid 2770 xStart = xMeta.getStart() 2771 self.assertIsNotNone(xStart, "getStart(): no start") 2772 xEnd = xMeta.getEnd() 2773 self.assertIsNotNone(xEnd, "getEnd(): no end") 2774 2775 ## XTextCursor 2776 xMetaCursor = xMeta.createTextCursor() 2777 self.assertIsNotNone(xMetaCursor, "createTextCursor(): no cursor") 2778 bSuccess = False 2779 xMetaCursor.gotoStart(False) 2780 xMetaCursor.gotoEnd(False) 2781 bSuccess = xMetaCursor.goLeft(1, False) 2782 self.assertTrue(bSuccess, "goLeft(): failed") 2783 bSuccess = xMetaCursor.goLeft(1000, False) 2784 self.assertFalse(bSuccess, "goLeft(): succeeded") 2785 bSuccess = xMetaCursor.goRight(1, False) 2786 self.assertTrue(bSuccess, "goRight(): failed") 2787 bSuccess = xMetaCursor.goRight(1000, False) 2788 self.assertFalse(bSuccess, "goRight(): succeeded") 2789 xMetaCursor.gotoRange(xStart, False) 2790 xMetaCursor.gotoRange(xEnd, False) 2791 try: 2792 xMetaCursor.gotoRange(xDocTextCursor, False) 2793 fail("gotoRange(): succeeded") 2794 except RuntimeException: 2795 pass 2796 2797 ## XWordCursor 2798 xMeta.setString("Two words") 2799 xMetaCursor.gotoStart(False) 2800 2801 bSuccess = xMetaCursor.gotoNextWord(True) # at start of "words" 2802 self.assertTrue(bSuccess, "gotoNextWord(): failed") 2803 2804 string = xMetaCursor.getString() 2805 self.assertEqual("Two ", string, "gotoNextWord(): wrong string") 2806 2807 bSuccess = xMetaCursor.gotoNextWord(False) # at end of "words", cannot leave metafield 2808 self.assertFalse(bSuccess,"gotoNextWord(): succeeded") 2809 xMetaCursor.collapseToEnd() 2810 bSuccess = xMetaCursor.gotoPreviousWord(True) # at start of "words" 2811 self.assertTrue(bSuccess, "gotoPreviousWord(): failed") 2812 2813 string = xMetaCursor.getString() 2814 self.assertEqual("words", string, "gotoPreviousWord(): wrong string") 2815 2816 bSuccess = xMetaCursor.gotoPreviousWord(False) # at start of "Two" 2817 self.assertTrue(bSuccess, "gotoPreviousWord(): failed") 2818 2819 bSuccess = xMetaCursor.gotoPreviousWord(False) # cannot leave metafield 2820 self.assertFalse(bSuccess, "gotoPreviousWord(): succeeded") 2821 2822 bSuccess = xMetaCursor.gotoEndOfWord(True) # at end of "Two" 2823 self.assertTrue(bSuccess, "gotoEndOfWord(): failed") 2824 2825 string = xMetaCursor.getString() 2826 self.assertEqual("Two", string, "gotoEndOfWord(): wrong string") 2827 2828 xMetaCursor.gotoEnd(False) 2829 bSuccess = xMetaCursor.gotoStartOfWord(True) 2830 self.assertTrue(bSuccess, "gotoStartOfWord(): failed") 2831 2832 string = xMetaCursor.getString() 2833 self.assertEqual("words", string, "gotoStartOfWord(): wrong string") 2834 2835 xMeta.setString("") 2836 bSuccess = xMetaCursor.gotoEndOfWord(False) 2837 self.assertFalse(bSuccess, "gotoEndOfWord(): succeeded") 2838 bSuccess = xMetaCursor.gotoStartOfWord(False) 2839 self.assertFalse(bSuccess, "gotoStartOfWord(): succeeded") 2840 2841 ## XSentenceCursor 2842 xMeta.setString("This is a sentence. Another sentence.") 2843 xMetaCursor.gotoStart(False) 2844 2845 bSuccess = xMetaCursor.gotoNextSentence(True) 2846 self.assertTrue(bSuccess,"gotoNextSentence(): failed") 2847 2848 string = xMetaCursor.getString() 2849 self.assertEqual("This is a sentence. ", string, 2850 "gotoNextSentence(): wrong string") 2851 2852 bSuccess = xMetaCursor.gotoNextSentence(False) 2853 self.assertFalse(bSuccess, "gotoNextSentence(): succeeded") 2854 ## FIXME: 2855 ## the sentence cursor seems to work differently than the word cursor 2856 xMeta.setString("This is a sentence. Another sentence. Sentence 3.") 2857 xMetaCursor.gotoEnd(False) 2858 bSuccess = xMetaCursor.gotoPreviousSentence(True) 2859 self.assertTrue(bSuccess, "gotoPreviousSentence(): failed") 2860 2861 string = xMetaCursor.getString() 2862 self.assertEqual("Another sentence. Sentence 3.", string, 2863 "gotoPreviousSentence(): wrong string") 2864 2865 bSuccess = xMetaCursor.gotoPreviousSentence(False) 2866 self.assertFalse(bSuccess, "gotoPreviousSentence(): succeeded") 2867 bSuccess = xMetaCursor.gotoEndOfSentence(True) 2868 self.assertTrue(bSuccess, "gotoEndOfSentence(): failed") 2869 2870 string = xMetaCursor.getString() 2871 self.assertEqual("This is a sentence.", string, 2872 "gotoEndOfSentence(): wrong string") 2873 2874 xMetaCursor.gotoEnd(False) 2875 bSuccess = xMetaCursor.gotoStartOfSentence(True) 2876 self.assertTrue(bSuccess,"gotoStartOfSentence(): failed") 2877 2878 string = xMetaCursor.getString() 2879 self.assertEqual("Sentence 3.", string, 2880 "gotoStartOfSentence(): wrong string") 2881 2882 xMeta.setString("") 2883 bSuccess = xMetaCursor.gotoEndOfSentence(False) 2884 self.assertFalse(bSuccess, "gotoEndOfSentence(): succeeded") 2885 bSuccess = xMetaCursor.gotoStartOfSentence(False) 2886 self.assertFalse(bSuccess, "gotoStartOfSentence(): succeeded") 2887 2888 ## XParagraphCursor (does not make sense) 2889 bSuccess = xMetaCursor.gotoNextParagraph(False) 2890 self.assertFalse(bSuccess, "gotoNextParagraph(): succeeded") 2891 bSuccess = xMetaCursor.gotoPreviousParagraph(False) 2892 self.assertFalse(bSuccess, "gotoPreviousParagraph(): succeeded") 2893 bSuccess = xMetaCursor.gotoStartOfParagraph(False) 2894 self.assertFalse(bSuccess, "gotoStartOfParagraph(): succeeded") 2895 bSuccess = xMetaCursor.gotoEndOfParagraph(False) 2896 self.assertFalse(bSuccess, "gotoEndOfParagraph(): succeeded") 2897 2898 # See https://bugs.libreoffice.org/show_bug.cgi?id=49629 2899 # ensure that gotoEndOfWord does not fail when footnote is at word end 2900 def test_xtextcursor(self): 2901 xDoc = self.__class__.xDoc 2902 inserter = RangeInserter(xDoc) 2903 xDocText = xDoc.getText() 2904 xDocTextCursor = xDocText.createTextCursor() 2905 xDocTextCursor.gotoNextParagraph(False) 2906 inserter.inserttext(xDocTextCursor, "Text") 2907 xDocTextCursor.gotoEndOfWord(False) 2908 inserter.insertfootnote(xDocTextCursor, "footnote") 2909 xDocTextCursor.gotoStartOfParagraph(False) 2910 bSuccess = xDocTextCursor.gotoEndOfWord(True) 2911 self.assertTrue(bSuccess, "gotoEndOfWord(): failed") 2912 string = xDocTextCursor.getString() 2913 self.assertEqual("Text", string, "gotoEndOfWord(): wrong string") 2914 self.assertNotEqual("a","b") 2915 2916 class AttachHelper(): 2917 def isattribute(self): pass 2918 def mktreenode(self): pass 2919 def mktextcontent(self, inserter, node): pass 2920 def postinserted(self, node, xContent): pass 2921 2922 def test_meta_xtextattach_toxmark(self): 2923 class Helper(self.AttachHelper): 2924 def isattribute(_): 2925 return True 2926 def mktreenode(_): 2927 return DocumentIndexMarkNode(self.mkname("toxmark")) 2928 def mktextcontent(_, inserter, node): 2929 return inserter.makedocumentindexmark(node.name) 2930 self.do_meta_xtextattach(Helper()) 2931 2932 def test_meta_xtextattach_refmark(self): 2933 class Helper(self.AttachHelper): 2934 def isattribute(_): 2935 return True 2936 def mktreenode(_): 2937 return ReferenceMarkNode(self.mkname("refmark")) 2938 def mktextcontent(_, inserter, node): 2939 return inserter.makereferencemark(node.name) 2940 self.do_meta_xtextattach(Helper()) 2941 2942 def test_meta_xtextattach_textfield(self): 2943 class Helper(self.AttachHelper): 2944 def isattribute(_): 2945 return False 2946 def mktreenode(_): 2947 return TextFieldNode(self.mkname("field")) 2948 def mktextcontent(_, inserter, node): 2949 return inserter.maketextfield(node.content) 2950 self.do_meta_xtextattach(Helper()) 2951 2952 def test_meta_xtextattach_footnote(self): 2953 class Helper(self.AttachHelper): 2954 def isattribute(_): 2955 return False 2956 def mktreenode(_): 2957 return FootnoteNode(self.mkname("ftn")) 2958 def mktextcontent(_, inserter, node): 2959 return inserter.makefootnote(node.label) 2960 self.do_meta_xtextattach(Helper()) 2961 2962 def test_meta_xtextattach_meta(self): 2963 class Helper(self.AttachHelper): 2964 def isattribute(_): 2965 return True 2966 def mktreenode(_): 2967 return MetaNode(self.mkid("id")) 2968 def mktextcontent(_, inserter, node): 2969 return inserter.makemeta() 2970 def postinserted(_, node, xContent): 2971 xContent.MetadataReference = node.xmlid 2972 self.do_meta_xtextattach(Helper()) 2973 2974 def do_meta_xtextattach(self, helper): 2975 xDoc = self.__class__.xDoc 2976 inserter = RangeInserter(xDoc) 2977 text = TextNode("12AB6789") 2978 inserter.insertrange(Range(0, 0, text)) 2979 met1 = MetaNode(self.mkid("id")) 2980 xMeta = inserter.makemeta() 2981 2982 xDocText = xDoc.getText() 2983 xDocTextCursor = xDocText.createTextCursor() 2984 xDocTextCursor.goRight(3, False) 2985 xDocTextCursor.goRight(2, True) 2986 xDocText.insertTextContent(xDocTextCursor, xMeta, True) 2987 2988 xMeta.MetadataReference = met1.xmlid 2989 xStart = None 2990 xEnd = None 2991 2992 xStart = xMeta.getStart() 2993 xEnd = xMeta.getEnd() 2994 2995 nod1 = helper.mktreenode() 2996 nod2 = helper.mktreenode() 2997 xContent1 = helper.mktextcontent(inserter, nod1) 2998 xContent2 = helper.mktextcontent(inserter, nod2) 2999 3000 ## insertTextContent with meta getStart()/getEnd() 3001 xMeta.insertTextContent(xStart, xContent1, False) 3002 xMeta.insertTextContent(xEnd, xContent2, False) 3003 3004 helper.postinserted(nod1, xContent1) 3005 helper.postinserted(nod2, xContent2) 3006 3007 root = TreeNode() 3008 root.appendchild(TextNode("12")) 3009 root.appendchild(met1.dup() 3010 .appendchild(nod1.dup()) 3011 .appendchild(TextNode("AB")) 3012 .appendchild(nod2.dup())) 3013 root.appendchild(TextNode("6789")) 3014 self.dotest(root, False) 3015 3016 xMeta.setString("AB") 3017 xStart = xMeta.getStart() 3018 xEnd = xMeta.getEnd() 3019 3020 nod1 = helper.mktreenode() 3021 nod2 = helper.mktreenode() 3022 xContent1 = helper.mktextcontent(inserter, nod1) 3023 xContent2 = helper.mktextcontent(inserter, nod2) 3024 3025 xTextCursor = xMeta.createTextCursor() 3026 xTextCursor.gotoStart(False) 3027 3028 ## insertTextContent with meta cursor 3029 xMeta.insertTextContent(xTextCursor, xContent1, False) 3030 xTextCursor.gotoEnd(False) 3031 xMeta.insertTextContent(xTextCursor, xContent2, False) 3032 3033 helper.postinserted(nod1, xContent1) 3034 helper.postinserted(nod2, xContent2) 3035 3036 root = TreeNode() 3037 root.appendchild(TextNode("12")) 3038 root.appendchild(met1.dup() 3039 .appendchild(nod1.dup()) 3040 .appendchild(TextNode("AB")) 3041 .appendchild(nod2.dup())) 3042 root.appendchild(TextNode("6789")) 3043 self.dotest(root, False) 3044 3045 if not helper.isattribute(): 3046 # xMeta.setString("AB") 3047 xStart = xMeta.getStart() 3048 xEnd = xMeta.getEnd() 3049 3050 nod1 = helper.mktreenode() 3051 nod2 = helper.mktreenode() 3052 xContent1 = helper.mktextcontent(inserter, nod1) 3053 xContent2 = helper.mktextcontent(inserter, nod2) 3054 3055 xTextCursor = xMeta.createTextCursor() 3056 xTextCursor.gotoStart(False) 3057 xTextCursor.goRight(1, True) 3058 3059 ## insertTextContent with meta cursor and absorb 3060 xMeta.insertTextContent(xTextCursor, xContent1, True) 3061 xTextCursor.gotoEnd(False) 3062 xTextCursor.goLeft(1, True) 3063 xMeta.insertTextContent(xTextCursor, xContent2, True) 3064 3065 helper.postinserted(nod1, xContent1) 3066 helper.postinserted(nod2, xContent2) 3067 3068 root = TreeNode() 3069 root.appendchild(TextNode("12")) 3070 root.appendchild(met1.dup() 3071 .appendchild(nod1.dup()) 3072 .appendchild(TextNode("AB")) 3073 .appendchild(nod2.dup())) 3074 root.appendchild(TextNode("6789")) 3075 self.dotest(root, False) 3076 3077 xMeta.setString("AB") 3078 xStart = xMeta.getStart() 3079 xEnd = xMeta.getEnd() 3080 3081 nod1 = helper.mktreenode() 3082 nod2 = helper.mktreenode() 3083 xContent1 = helper.mktextcontent(inserter, nod1) 3084 xContent2 = helper.mktextcontent(inserter, nod2) 3085 3086 xDocTextCursor.gotoRange(xStart, False) 3087 3088 ## insertTextContent with document cursor 3089 xMeta.insertTextContent(xDocTextCursor, xContent1, False) 3090 xDocTextCursor.gotoRange(xEnd, False) 3091 xMeta.insertTextContent(xDocTextCursor, xContent2, False) 3092 3093 helper.postinserted(nod1, xContent1) 3094 helper.postinserted(nod2, xContent2) 3095 3096 root = TreeNode() 3097 root.appendchild(TextNode("12")) 3098 root.appendchild(met1.dup() 3099 .appendchild(nod1.dup()) 3100 .appendchild(TextNode("AB")) 3101 .appendchild(nod2.dup())) 3102 root.appendchild(TextNode("6789")) 3103 self.dotest(root, False) 3104 3105 if not helper.isattribute(): 3106 xStart = xMeta.getStart() 3107 xEnd = xMeta.getEnd() 3108 3109 nod1 = helper.mktreenode() 3110 nod2 = helper.mktreenode() 3111 xContent1 = helper.mktextcontent(inserter, nod1) 3112 xContent2 = helper.mktextcontent(inserter, nod2) 3113 3114 xDocTextCursor.gotoRange(xStart, False) 3115 xDocTextCursor.goRight(1, True) 3116 3117 ## insertTextContent with document cursor and absorb 3118 xMeta.insertTextContent(xDocTextCursor, xContent1, True) 3119 xDocTextCursor.gotoRange(xEnd, False) 3120 xDocTextCursor.goLeft(1, True) 3121 xMeta.insertTextContent(xDocTextCursor, xContent2, True) 3122 3123 helper.postinserted(nod1, xContent1) 3124 helper.postinserted(nod2, xContent2) 3125 3126 root = TreeNode() 3127 root.appendchild(TextNode("12")) 3128 root.appendchild(met1.dup() 3129 .appendchild(nod1.dup()) 3130 .appendchild(TextNode("AB")) 3131 .appendchild(nod2.dup())) 3132 root.appendchild(TextNode("6789")) 3133 self.dotest(root, False) 3134 3135 xMeta.setString("AB") 3136 xStart = xMeta.getStart() 3137 xEnd = xMeta.getEnd() 3138 3139 nod1 = helper.mktreenode() 3140 nod2 = helper.mktreenode() 3141 xContent1 = helper.mktextcontent(inserter, nod1) 3142 xContent2 = helper.mktextcontent(inserter, nod2) 3143 3144 ## attach to range from meta getStart()/getEnd() 3145 xContent1.attach(xStart) 3146 xContent2.attach(xEnd) 3147 3148 helper.postinserted(nod1, xContent1) 3149 helper.postinserted(nod2, xContent2) 3150 3151 root = TreeNode() 3152 root.appendchild(TextNode("12")) 3153 root.appendchild(met1.dup() 3154 .appendchild(nod1.dup()) 3155 .appendchild(TextNode("AB")) 3156 .appendchild(nod2.dup())) 3157 root.appendchild(TextNode("6789")) 3158 self.dotest(root, False) 3159 3160 xMeta.setString("AB") 3161 xStart = xMeta.getStart() 3162 xEnd = xMeta.getEnd() 3163 3164 nod1 = helper.mktreenode() 3165 nod2 = helper.mktreenode() 3166 xContent1 = helper.mktextcontent(inserter, nod1) 3167 xContent2 = helper.mktextcontent(inserter, nod2) 3168 3169 xTextCursor = xMeta.createTextCursor() 3170 xTextCursor.gotoStart(False) 3171 3172 ## attach to cursor from meta XText 3173 xContent1.attach(xTextCursor) 3174 xTextCursor.gotoEnd(False) 3175 xContent2.attach(xTextCursor) 3176 3177 helper.postinserted(nod1, xContent1) 3178 helper.postinserted(nod2, xContent2) 3179 3180 root = TreeNode() 3181 root.appendchild(TextNode("12")) 3182 root.appendchild(met1.dup() 3183 .appendchild(nod1.dup()) 3184 .appendchild(TextNode("AB")) 3185 .appendchild(nod2.dup())) 3186 root.appendchild(TextNode("6789")) 3187 self.dotest(root, False) 3188 3189 def test_metafield_xtextfield(self): 3190 xDoc = self.__class__.xDoc 3191 smgr = self.__class__._uno.xContext.ServiceManager 3192 xRepo = xDoc.getRDFRepository() 3193 ## for testing just add it to the first graph 3194 Graphs = xRepo.getGraphNames() 3195 xGraph = xRepo.getGraph(Graphs[0]) 3196 xOdfPrefix = smgr.createInstance("com.sun.star.rdf.URI") 3197 xOdfPrefix.initialize((ODF_PREFIX,)) 3198 xOdfSuffix = smgr.createInstance("com.sun.star.rdf.URI") 3199 xOdfSuffix.initialize((ODF_SUFFIX,)) 3200 3201 xPrefix = smgr.createInstance("com.sun.star.rdf.Literal") 3202 xPrefix.initialize(("foo",)) 3203 xSuffix = smgr.createInstance("com.sun.star.rdf.Literal") 3204 xSuffix.initialize(("bar",)) 3205 3206 inserter = RangeInserter(xDoc) 3207 text = TextNode("abc") 3208 inserter.insertrange(Range(0, 0, text)) 3209 xDocText = xDoc.getText() 3210 xDocTextCursor = xDocText.createTextCursor() 3211 xDocTextCursor.goRight(1, False) 3212 xDocTextCursor.goRight(3, True) 3213 3214 xMetaField = inserter.makemetafield() 3215 3216 xDocText.insertTextContent(xDocTextCursor, xMetaField, True) 3217 3218 xMetaField.ensureMetadataReference 3219 3220 xGraph.addStatement(xMetaField, xOdfPrefix, xPrefix) 3221 xGraph.addStatement(xMetaField, xOdfSuffix, xSuffix) 3222 self.assertEqual("fooabcbar", xMetaField.getPresentation(False), 3223 "getPresentation(): wrong") 3224 inserter.insertrange(Range(0, 0, text)) 3225 3226 def test_metafield_xpropertyset(self): 3227 xDoc = self.__class__.xDoc 3228 inserter = RangeInserter(xDoc) 3229 text = TextNode("123") 3230 inserter.insertrange(Range(0, 0, text)) 3231 xDocText = xDoc.getText() 3232 xDocTextCursor = xDocText.createTextCursor() 3233 xDocTextCursor.goRight(1, False) 3234 xDocTextCursor.goRight(3, True) 3235 3236 xMetaField = inserter.makemetafield() 3237 3238 xDocText.insertTextContent(xDocTextCursor, xMetaField, True) 3239 3240 self.assertIsNotNone(xMetaField, "PropertySet: not supported?") 3241 xPropertySetInfo = xMetaField.getPropertySetInfo() 3242 self.assertTrue(xPropertySetInfo.hasPropertyByName("NumberFormat"), 3243 'hasPropertyByName("NumberFormat"):') 3244 self.assertTrue(xPropertySetInfo.hasPropertyByName("IsFixedLanguage"), 3245 'hasPropertyByName("IsFixedLanguage"):') 3246 3247 def_ = xMetaField.NumberFormat 3248 print("NumberFormat: default is {}".format(def_)) 3249 xMetaField.NumberFormat = NUMBER_INT 3250 xMetaField.IsFixedLanguage = True 3251 format = xMetaField.NumberFormat 3252 self.assertEqual(NUMBER_INT, format, "NumberFormat: failed") 3253 isfixed = xMetaField.IsFixedLanguage 3254 self.assertTrue(isfixed, "IsFixedLanguage: failed") 3255 3256 def dostore(self, xComp, file): 3257 print("Storing test document...") 3258 file = uno.systemPathToFileUrl(file) 3259 xComp.storeToURL(file, ()) 3260 print("...done") 3261 3262 def doload(self, file): 3263 xComp = None 3264 print("Loading test document...") 3265 xComp = self.__class__._uno.openDocFromAbsolutePath(file) 3266 self.assertIsNotNone(xComp, "cannot load: {}".format(file)) 3267 print("...done") 3268 return xComp 3269 3270 def close(self, i_comp): 3271 try: 3272 if i_comp: 3273 i_comp.close(True) 3274 except Exception as e: 3275 pass 3276 3277 def test_load_store(self): 3278 xComp = None 3279 filename = "TESTMETA.odt" 3280 try: 3281 xComp = self.__class__._uno.openDocFromTDOC(filename) 3282 if xComp: 3283 self.checkloadmeta(xComp) 3284 with TemporaryDirectory() as tempdir: 3285 if os.altsep: # we need URL so replace "\" with "/" 3286 tempdir = tempdir.replace(os.sep, os.altsep) 3287 file = tempdir + "/" + filename 3288 self.dostore(xComp, file) 3289 self.close(xComp) 3290 xComp2 = None 3291 try: 3292 xComp2 = self.doload(file) 3293 self.checkloadmeta(xComp2) 3294 finally: 3295 self.close(xComp2) 3296 finally: 3297 self.close(xComp) 3298 3299 def checkloadmeta(self, xTextDoc): 3300 xText = xTextDoc.getText() 3301 print("Checking meta(-field)s in loaded test document...") 3302 root = TreeNode() 3303 root.appendchild(RubyNode("ruby1") 3304 .appendchild(TextNode("1"))) 3305 root.appendchild(MetaNode(self.mkid_("id1")) 3306 .appendchild(TextNode("2"))) 3307 root.appendchild(MetaFieldNode(self.mkid_("id2")) 3308 .appendchild(TextNode("3"))) 3309 root.appendchild(RubyNode("ruby2") 3310 .appendchild(MetaNode(self.mkid_("id3")) 3311 .appendchild(TextNode("4")))) 3312 root.appendchild(RubyNode("ruby3") 3313 .appendchild(MetaFieldNode(self.mkid_("id4")) 3314 .appendchild(TextNode("5")))) 3315 root.appendchild(MetaNode(self.mkid_("id5")) 3316 .appendchild(RubyNode("ruby4") 3317 .appendchild(TextNode("6")))) 3318 root.appendchild(MetaFieldNode(self.mkid_("id6")) 3319 .appendchild(RubyNode("ruby5") 3320 .appendchild(TextNode("7")))) 3321 root.appendchild(MetaNode(self.mkid_("id7")) 3322 .appendchild(MetaNode(self.mkid_("id8")) 3323 .appendchild(TextNode("8")))) 3324 root.appendchild(MetaNode(self.mkid_("id9")) 3325 .appendchild(MetaFieldNode(self.mkid_("id10")) 3326 .appendchild(TextNode("9")))) 3327 root.appendchild(MetaFieldNode(self.mkid_("id11")) 3328 .appendchild(MetaNode(self.mkid_("id12")) 3329 .appendchild(TextNode("10")))) 3330 root.appendchild(MetaFieldNode(self.mkid_("id13")) 3331 .appendchild(MetaFieldNode(self.mkid_("id14")) 3332 .appendchild(TextNode("11")))) 3333 root.appendchild(MetaNode(self.mkid_("id15")) 3334 .appendchild(RubyNode("ruby6") 3335 .appendchild(MetaFieldNode(self.mkid_("id16")) 3336 .appendchild(TextNode("12"))))) 3337 3338 class MetaNode_(MetaNode): 3339 def __init__(self, id): 3340 super().__init__(id) 3341 def __eq__(self, other): 3342 return isinstance(other, MetaNode) 3343 root.appendchild(MetaNode_(self.mkid_("")) 3344 .appendchild(TextNode("13"))) 3345 root.appendchild(TextNode(" X X ")) 3346 self._dotest(xTextDoc, root, False) 3347 print("...done") 3348 3349 def test_load_store_xmlid(self): 3350 xComp = None 3351 filename = "TESTXMLID.odt" 3352 try: 3353 xComp = self.__class__._uno.openDocFromTDOC(filename) 3354 if xComp: 3355 self.checkloadxmlid(xComp) 3356 with TemporaryDirectory() as tempdir: 3357 if os.altsep: # we need URL so replace "\" with "/" 3358 tempdir = tempdir.replace(os.sep, os.altsep) 3359 file = tempdir + "/" + filename 3360 self.dostore(xComp, file) 3361 self.close(xComp) 3362 xComp2 = None 3363 try: 3364 xComp2 = self.doload(file) 3365 self.checkloadxmlid(xComp2) 3366 finally: 3367 self.close(xComp2) 3368 finally: 3369 self.close(xComp) 3370 3371 def checkloadxmlid(self, xTextDoc): 3372 xText = xTextDoc.getText() 3373 xRepo = xTextDoc.getRDFRepository() 3374 3375 print("Checking bookmarks in loaded test document...") 3376 xBookmarks = xTextDoc.getBookmarks() 3377 xMark1 = xBookmarks["mk1"] 3378 self.assertTrue(self.eq(xMark1.MetadataReference, 3379 StringPair("content.xml", "id90")), "mark1") 3380 xMark2 = xBookmarks["mk2"] 3381 result = xRepo.getStatementRDFa(xMark2) 3382 self.assertTrue(len(result.First) == 1 and 3383 result.First[0].Subject.StringValue == "uri:foo" and 3384 result.First[0].Predicate.StringValue == "uri:bar" and 3385 result.First[0].Object.Value == "a fooish bar", 3386 "mark2") 3387 xMark3 = xBookmarks["mk3"] 3388 self.assertTrue(self.eq(xMark3.MetadataReference, 3389 StringPair("content.xml", "id91")), "mark3") 3390 print("...done") 3391 3392 print("Checking sections in loaded test document...") 3393 xSections = xTextDoc.getTextSections() 3394 xSection1 = xSections["Section 1"] 3395 self.assertTrue(self.eq(xSection1.MetadataReference, 3396 StringPair("content.xml", "idSection1")), "idsection1") 3397 xSection2 = xSections["Section 2"] 3398 self.assertTrue(self.eq(xSection2.MetadataReference, 3399 StringPair("content.xml", "idSection2")),"idSection2") 3400 xSection3 = xSections["Table of Contents1_Head"] 3401 self.assertTrue(self.eq(xSection3.MetadataReference, 3402 StringPair("content.xml", "idTOCTitle")), "idTOCTitle") 3403 xSection4 = xSections["Alphabetical Index1_Head"] 3404 self.assertTrue(self.eq(xSection4.MetadataReference, 3405 StringPair("content.xml", "idAITitle")), "idAITitle") 3406 xSection5 = xSections["Illustration Index1_Head"] 3407 self.assertTrue(self.eq(xSection5.MetadataReference, 3408 StringPair("content.xml", "idIITitle")), "idIITitle") 3409 xSection6 = xSections["Index of Tables1_Head"] 3410 self.assertTrue(self.eq(xSection6.MetadataReference, 3411 StringPair("content.xml", "idIOTTitle")), "idIOTTitle") 3412 xSection7 = xSections["User-Defined1_Head"] 3413 self.assertTrue(self.eq(xSection7.MetadataReference, 3414 StringPair("content.xml", "idUDTitle")), "idUDTitle") 3415 xSection8 = xSections["Table of Objects1_Head"] 3416 self.assertTrue(self.eq(xSection8.MetadataReference, 3417 StringPair("content.xml", "idTOOTitle")), "idTOOTitle") 3418 xSection9 = xSections["Bibliography1_Head"] 3419 self.assertTrue(self.eq(xSection9.MetadataReference, 3420 StringPair("content.xml", "idBibTitle")), "idBibTitle") 3421 print("...done") 3422 3423 print("Checking indexes in loaded test document...") 3424 xIndexes = xTextDoc.getDocumentIndexes() 3425 xIndex1 = xIndexes["Table of Contents1"] 3426 self.assertTrue(self.eq(xIndex1.MetadataReference, 3427 StringPair("content.xml", "idTOC")), "idTOC") 3428 xIndex1s = xSections["Table of Contents1"] 3429 self.assertTrue(self.eq(xIndex1s.MetadataReference, 3430 StringPair("content.xml", "idTOC")), "idTOC") 3431 xIndex2 = xIndexes["Alphabetical Index1"] 3432 self.assertTrue(self.eq(xIndex2.MetadataReference, 3433 StringPair("content.xml", "idAI")), "idAI") 3434 xIndex2s = xSections["Alphabetical Index1"] 3435 self.assertTrue(self.eq(xIndex2s.MetadataReference, 3436 StringPair("content.xml", "idAI")), "idAI") 3437 xIndex3 = xIndexes["Illustration Index1"] 3438 self.assertTrue(self.eq(xIndex3.MetadataReference, 3439 StringPair("content.xml", "idII")), "idII") 3440 xIndex3s = xSections["Table of Figures1"] 3441 self.assertTrue(self.eq(xIndex3s.MetadataReference, 3442 StringPair("content.xml", "idII")), "idII") 3443 xIndex4 = xIndexes["Index of Tables1"] 3444 self.assertTrue(self.eq(xIndex4.MetadataReference, 3445 StringPair("content.xml", "idIOT")), "idIOT") 3446 xIndex4s = xSections["Index of Tables1"] 3447 self.assertTrue(self.eq(xIndex4s.MetadataReference, 3448 StringPair("content.xml", "idIOT")), "idIOT") 3449 xIndex5 = xIndexes["User-Defined1"] 3450 self.assertTrue(self.eq(xIndex5.MetadataReference, 3451 StringPair("content.xml", "idUD")), "idUD") 3452 xIndex5s = xSections["User-Defined1"] 3453 self.assertTrue(self.eq(xIndex5s.MetadataReference, 3454 StringPair("content.xml", "idUD")), "idUD") 3455 xIndex6 = xIndexes["Table of Objects1"] 3456 self.assertTrue(self.eq(xIndex6.MetadataReference, 3457 StringPair("content.xml", "idTOO")), "idTOO") 3458 xIndex6s = xSections["Table of Objects1"] 3459 self.assertTrue(self.eq(xIndex6s.MetadataReference, 3460 StringPair("content.xml", "idTOO")), "idTOO") 3461 xIndex7 = xIndexes["Bibliography1"] 3462 self.assertTrue(self.eq(xIndex7.MetadataReference, 3463 StringPair("content.xml", "idBib")), "idBib") 3464 xIndex7s = xSections["Bibliography1"] 3465 self.assertTrue(self.eq(xIndex7s.MetadataReference, 3466 StringPair("content.xml", "idBib")), "idBib") 3467 print("...done") 3468 3469 def dotest(self, intree, insert=True): 3470 xDoc = self.__class__.xDoc 3471 self._dotest(xDoc, intree, insert) 3472 3473 def _dotest(self, xDoc, intree, insert): 3474 self._dumptree(intree, "I: ") 3475 if insert: 3476 TreeInserter(xDoc).inserttree(intree) 3477 xText = xDoc.getText() 3478 xTextEnum = xText.createEnumeration() 3479 ## skip to right paragraph 3480 xTextEnum.nextElement(); # skip first -- always empty! 3481 xElement = xTextEnum.nextElement() # second contains test case 3482 xEnum = xElement.createEnumeration() 3483 outtree = EnumConverter().convert(xEnum) 3484 self._dumptree(outtree, "O: ") 3485 FuzzyTester().dotest(intree, outtree) 3486 3487 def _dumptree(self, tree, prefix): 3488 print('{}{}'.format(prefix, str(tree))) 3489 children = tree.createenumeration() 3490 for node in children: 3491 self._dumptree(node, "{} ".format(prefix)) 3492 3493 def mkname(self, prefix): 3494 self.__class__.count += 1 3495 return "{}{}".format(prefix, self.__class__.count) 3496 3497 def mkid(self, prefix): 3498 id = self.mkname(prefix) 3499 return StringPair("content.xml", self.mkname(prefix)) 3500 3501 def mkid_(self, id): 3502 return StringPair("content.xml", id) 3503 3504 def eq(self, left, right): 3505 return (left.First == right.First and 3506 left.Second == right.Second) 3507 3508 3509if __name__ == '__main__': 3510 unittest.main() 3511