2021-02-21 05:53:09 +01:00
|
|
|
|
#!/usr/bin/env python3
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# -*- coding: utf-8 -*-
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
# @file simpleTests.py
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# Requires Python 2.7 or later
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
from __future__ import with_statement
|
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
import ctypes, string, sys, unittest
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
import XiteWin as Xite
|
|
|
|
|
|
|
|
|
|
# Unicode line ends are only available for lexers that support the feature so requires lexers
|
|
|
|
|
lexersAvailable = Xite.lexillaAvailable or Xite.scintillaIncludesLexers
|
|
|
|
|
unicodeLineEndsAvailable = lexersAvailable
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
class TestSimple(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
2019-07-21 15:26:02 +02:00
|
|
|
|
def testStatus(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetStatus(), 0)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
self.ed.SetStatus(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetStatus(), 1)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
self.ed.SetStatus(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetStatus(), 0)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testLength(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testAddText(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(1, b"x")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetCharAt(0), ord("x"))
|
|
|
|
|
self.assertEqual(self.ed.GetStyleAt(0), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ClearAll()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testDeleteRange(self):
|
|
|
|
|
self.ed.AddText(5, b"abcde")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 5)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.DeleteRange(1, 2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 3)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), b"ade")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testAddStyledText(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.EndStyled, 0)
|
2022-04-13 13:10:12 +02:00
|
|
|
|
self.ed.AddStyledText(4, b"x\002y\377")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.ed.GetCharAt(0), ord("x"))
|
|
|
|
|
self.assertEqual(self.ed.GetStyleAt(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetStyleIndexAt(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetStyleIndexAt(1), 255)
|
|
|
|
|
self.assertEqual(self.ed.StyledTextRange(0, 1), b"x\002")
|
|
|
|
|
self.assertEqual(self.ed.StyledTextRange(1, 2), b"y\377")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ClearDocumentStyle()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.ed.GetCharAt(0), ord("x"))
|
|
|
|
|
self.assertEqual(self.ed.GetStyleAt(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.StyledTextRange(0, 1), b"x\0")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-12-10 13:35:16 +01:00
|
|
|
|
def testStyledTextRangeFull(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.EndStyled, 0)
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.AddStyledText(4, b"x\002y\377")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyledTextRangeFull(0, 1), b"x\002")
|
|
|
|
|
self.assertEqual(self.ed.StyledTextRangeFull(1, 2), b"y\377")
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.ClearDocumentStyle()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.ed.StyledTextRangeFull(0, 1), b"x\0")
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testStyling(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.EndStyled, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddStyledText(4, b"x\002y\003")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyledTextRange(0, 2), b"x\002y\003")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.StartStyling(0,0xf)
|
|
|
|
|
self.ed.SetStyling(1, 5)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyledTextRange(0, 2), b"x\005y\003")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
self.ed.StartStyling(0,0xff)
|
|
|
|
|
self.ed.SetStylingEx(2, b"\100\101")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyledTextRange(0, 2), b"x\100y\101")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testPosition(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 0)
|
|
|
|
|
self.assertEqual(self.ed.Anchor, 0)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(1, b"x")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Caret has automatically moved
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 1)
|
|
|
|
|
self.assertEqual(self.ed.Anchor, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SelectAll()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 0)
|
|
|
|
|
self.assertEqual(self.ed.Anchor, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Anchor = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Anchor, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Check line positions
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.PositionFromLine(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.PositionFromLine(1), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
self.ed.CurrentPos = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Anchor, 0)
|
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
def testBeyonEnd(self):
|
|
|
|
|
self.ed.AddText(1, b"x")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(1), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(2), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testSelection(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 0)
|
|
|
|
|
self.assertEqual(self.ed.Anchor, 0)
|
|
|
|
|
self.assertEqual(self.ed.SelectionStart, 0)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, 0)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(1, b"x")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SelectionStart = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 1)
|
|
|
|
|
self.assertEqual(self.ed.Anchor, 0)
|
|
|
|
|
self.assertEqual(self.ed.SelectionStart, 0)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SelectionStart = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 1)
|
|
|
|
|
self.assertEqual(self.ed.Anchor, 1)
|
|
|
|
|
self.assertEqual(self.ed.SelectionStart, 1)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
self.ed.SelectionEnd = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 0)
|
|
|
|
|
self.assertEqual(self.ed.Anchor, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testSetSelection(self):
|
|
|
|
|
self.ed.AddText(4, b"abcd")
|
|
|
|
|
self.ed.SetSel(1, 3)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionStart, 1)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, 3)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
result = self.ed.GetSelText(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"bc")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ReplaceSel(0, b"1234")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 6)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a1234d")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testReadOnly(self):
|
|
|
|
|
self.ed.AddText(1, b"x")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ReadOnly, 0)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), b"x")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ReadOnly = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ReadOnly, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddText(1, b"x")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"x")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ReadOnly = 0
|
|
|
|
|
self.ed.AddText(1, b"x")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"xx")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Null()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"xx")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testAddLine(self):
|
|
|
|
|
data = b"x" * 70 + b"\n"
|
|
|
|
|
for i in range(5):
|
|
|
|
|
self.ed.AddText(len(data), data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, i + 2)
|
|
|
|
|
self.assertTrue(self.ed.Length > 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testInsertText(self):
|
|
|
|
|
data = b"xy"
|
|
|
|
|
self.ed.InsertText(0, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(data, self.ed.ByteRange(0,2))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
self.ed.InsertText(1, data)
|
|
|
|
|
# Should now be "xxyy"
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 4)
|
|
|
|
|
self.assertEqual(b"xxyy", self.ed.ByteRange(0,4))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-05-25 22:16:39 +02:00
|
|
|
|
def testTextRangeFull(self):
|
|
|
|
|
data = b"xy"
|
|
|
|
|
self.ed.InsertText(0, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(data, self.ed.ByteRangeFull(0,2))
|
2022-05-25 22:16:39 +02:00
|
|
|
|
|
|
|
|
|
self.ed.InsertText(1, data)
|
|
|
|
|
# Should now be "xxyy"
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 4)
|
|
|
|
|
self.assertEqual(b"xxyy", self.ed.ByteRangeFull(0,4))
|
2022-05-25 22:16:39 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testInsertNul(self):
|
|
|
|
|
data = b"\0"
|
|
|
|
|
self.ed.AddText(1, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 1)
|
|
|
|
|
self.assertEqual(data, self.ed.ByteRange(0,1))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2023-02-09 17:57:24 +01:00
|
|
|
|
def testNewLine(self):
|
|
|
|
|
self.ed.SetContents(b"12")
|
|
|
|
|
self.ed.SetSel(1, 1)
|
|
|
|
|
self.ed.NewLine()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1\r\n2")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testUndoRedo(self):
|
|
|
|
|
data = b"xy"
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Modify, 0)
|
|
|
|
|
self.assertEqual(self.ed.UndoCollection, 1)
|
|
|
|
|
self.assertEqual(self.ed.CanRedo(), 0)
|
|
|
|
|
self.assertEqual(self.ed.CanUndo(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.ed.Modify, 1)
|
|
|
|
|
self.assertEqual(self.ed.CanRedo(), 0)
|
|
|
|
|
self.assertEqual(self.ed.CanUndo(), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.ed.Modify, 0)
|
|
|
|
|
self.assertEqual(self.ed.CanRedo(), 1)
|
|
|
|
|
self.assertEqual(self.ed.CanUndo(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Redo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.ed.Modify, 1)
|
|
|
|
|
self.assertEqual(data, self.ed.Contents())
|
|
|
|
|
self.assertEqual(self.ed.CanRedo(), 0)
|
|
|
|
|
self.assertEqual(self.ed.CanUndo(), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testUndoSavePoint(self):
|
|
|
|
|
data = b"xy"
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Modify, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Modify, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSavePoint()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Modify, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Modify, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testUndoCollection(self):
|
|
|
|
|
data = b"xy"
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.UndoCollection, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.UndoCollection = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.UndoCollection, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CanRedo(), 0)
|
|
|
|
|
self.assertEqual(self.ed.CanUndo(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.UndoCollection = 1
|
|
|
|
|
|
|
|
|
|
def testGetColumn(self):
|
|
|
|
|
self.ed.AddText(1, b"x")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetColumn(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetColumn(1), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Next line caused infinite loop in 1.71
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetColumn(2), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetColumn(3), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testTabWidth(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TabWidth, 8)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddText(3, b"x\tb")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetColumn(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetColumn(1), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetColumn(2), 8)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
for col in range(10):
|
|
|
|
|
if col == 0:
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindColumn(0, col), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
elif col == 1:
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindColumn(0, col), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
elif col == 8:
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindColumn(0, col), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
elif col == 9:
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindColumn(0, col), 3)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
else:
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindColumn(0, col), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TabWidth = 4
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TabWidth, 4)
|
|
|
|
|
self.assertEqual(self.ed.GetColumn(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetColumn(1), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetColumn(2), 4)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testIndent(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Indent, 0)
|
|
|
|
|
self.assertEqual(self.ed.UseTabs, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Indent = 8
|
|
|
|
|
self.ed.UseTabs = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Indent, 8)
|
|
|
|
|
self.assertEqual(self.ed.UseTabs, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddText(3, b"x\tb")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineIndentation(0), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, b" ")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineIndentation(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineIndentPosition(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), b" x\tb")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetLineIndentation(0,2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b" x\tb")
|
|
|
|
|
self.assertEqual(self.ed.GetLineIndentPosition(0), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.UseTabs = 1
|
|
|
|
|
self.ed.SetLineIndentation(0,8)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"\tx\tb")
|
|
|
|
|
self.assertEqual(self.ed.GetLineIndentPosition(0), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testGetCurLine(self):
|
|
|
|
|
self.ed.AddText(1, b"x")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
data = ctypes.create_string_buffer(b"\0" * 100)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
caret = self.ed.GetCurLine(len(data), data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(caret, 1)
|
|
|
|
|
self.assertEqual(data.value, b"x")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testGetLine(self):
|
|
|
|
|
self.ed.AddText(1, b"x")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
data = ctypes.create_string_buffer(b"\0" * 100)
|
|
|
|
|
self.ed.GetLine(0, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(data.value, b"x")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testLineEnds(self):
|
|
|
|
|
self.ed.AddText(3, b"x\ny")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(1), 3)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(1), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
# Test lines out of range.
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineLength(2), 0)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(-1), 0)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
if sys.platform == "win32":
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.EOLMode, self.ed.SC_EOL_CRLF)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
else:
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.EOLMode, self.ed.SC_EOL_LF)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
lineEnds = [b"\r\n", b"\r", b"\n"]
|
|
|
|
|
for lineEndType in [self.ed.SC_EOL_CR, self.ed.SC_EOL_LF, self.ed.SC_EOL_CRLF]:
|
|
|
|
|
self.ed.EOLMode = lineEndType
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.EOLMode, lineEndType)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ConvertEOLs(lineEndType)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"x" + lineEnds[lineEndType] + b"y")
|
|
|
|
|
self.assertEqual(self.ed.LineLength(0), 1 + len(lineEnds[lineEndType]))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# Several tests for unicode line ends U+2028 and U+2029
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testUnicodeLineEnds(self):
|
|
|
|
|
# Add two lines separated with U+2028 and ensure it is seen as two lines
|
|
|
|
|
# Then remove U+2028 and should be just 1 lines
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
|
|
|
|
self.ed.AddText(5, b"x\xe2\x80\xa8y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(1), 5)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(0), 4)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(1), 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 4
|
|
|
|
|
self.ed.ReplaceTarget(0, b"")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.LineEndTypesSupported, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
|
|
|
|
def testUnicodeLineEndsWithCodePage0(self):
|
|
|
|
|
# Try the Unicode line ends when not in Unicode mode -> should remain 1 line
|
|
|
|
|
self.ed.SetCodePage(0)
|
|
|
|
|
self.ed.AddText(5, b"x\xe2\x80\xa8y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(4, b"x\xc2\x85y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testUnicodeLineEndsSwitchToUnicodeAndBack(self):
|
|
|
|
|
# Add the Unicode line ends when not in Unicode mode
|
|
|
|
|
self.ed.SetCodePage(0)
|
|
|
|
|
self.ed.AddText(5, b"x\xe2\x80\xa8y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# Into UTF-8 mode - should now be interpreting as two lines
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# Back to code page 0 and 1 line
|
|
|
|
|
self.ed.SetCodePage(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testUFragmentedEOLCompletion(self):
|
|
|
|
|
# Add 2 starting bytes of UTF-8 line end then complete it
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.AddText(4, b"x\xe2\x80y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 4)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(3,3)
|
|
|
|
|
self.ed.AddText(1, b"\xa8")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"x\xe2\x80\xa8y")
|
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
|
|
|
|
# Add 1 starting bytes of UTF-8 line end then complete it
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.AddText(3, b"x\xe2y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 3)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(2,2)
|
|
|
|
|
self.ed.AddText(2, b"\x80\xa8")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"x\xe2\x80\xa8y")
|
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testUFragmentedEOLStart(self):
|
|
|
|
|
# Add end of UTF-8 line end then insert start
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(4, b"x\x80\xa8y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(1,1)
|
|
|
|
|
self.ed.AddText(1, b"\xe2")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testUBreakApartEOL(self):
|
|
|
|
|
# Add two lines separated by U+2029 then remove and add back each byte ensuring
|
|
|
|
|
# only one line after each removal of any byte in line end and 2 lines after reinsertion
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
2023-06-01 01:11:12 +02:00
|
|
|
|
text = b"x\xe2\x80\xa9y"
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(5, text)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
for i in range(len(text)):
|
|
|
|
|
self.ed.TargetStart = i
|
|
|
|
|
self.ed.TargetEnd = i + 1
|
|
|
|
|
self.ed.ReplaceTarget(0, b"")
|
|
|
|
|
if i in [0, 4]:
|
|
|
|
|
# Removing text characters does not change number of lines
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
else:
|
|
|
|
|
# Removing byte from line end, removes 1 line
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.TargetEnd = i
|
|
|
|
|
self.ed.ReplaceTarget(1, text[i:i+1])
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testURemoveEOLFragment(self):
|
|
|
|
|
# Add UTF-8 line end then delete each byte causing line end to disappear
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
|
|
|
|
for i in range(3):
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.AddText(5, b"x\xe2\x80\xa8y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.TargetStart = i+1
|
|
|
|
|
self.ed.TargetEnd = i+2
|
|
|
|
|
self.ed.ReplaceTarget(0, b"")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# Several tests for unicode NEL line ends U+0085
|
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testNELLineEnds(self):
|
|
|
|
|
# Add two lines separated with U+0085 and ensure it is seen as two lines
|
|
|
|
|
# Then remove U+0085 and should be just 1 lines
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
|
|
|
|
self.ed.AddText(4, b"x\xc2\x85y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(1), 4)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(1), 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 3
|
|
|
|
|
self.ed.ReplaceTarget(0, b"")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
|
|
|
|
self.assertEqual(self.ed.LineLength(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testNELFragmentedEOLCompletion(self):
|
|
|
|
|
# Add starting byte of UTF-8 NEL then complete it
|
|
|
|
|
self.ed.AddText(3, b"x\xc2y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetLineEndPosition(0), 3)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(2,2)
|
|
|
|
|
self.ed.AddText(1, b"\x85")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"x\xc2\x85y")
|
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testNELFragmentedEOLStart(self):
|
|
|
|
|
# Add end of UTF-8 NEL then insert start
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(4, b"x\x85y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(1,1)
|
|
|
|
|
self.ed.AddText(1, b"\xc2")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testNELBreakApartEOL(self):
|
|
|
|
|
# Add two lines separated by U+0085 then remove and add back each byte ensuring
|
|
|
|
|
# only one line after each removal of any byte in line end and 2 lines after reinsertion
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
self.ed.SetLineEndTypesAllowed(1)
|
2023-06-01 01:11:12 +02:00
|
|
|
|
text = b"x\xc2\x85y"
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.AddText(4, text)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
for i in range(len(text)):
|
|
|
|
|
self.ed.TargetStart = i
|
|
|
|
|
self.ed.TargetEnd = i + 1
|
|
|
|
|
self.ed.ReplaceTarget(0, b"")
|
|
|
|
|
if i in [0, 3]:
|
|
|
|
|
# Removing text characters does not change number of lines
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
else:
|
|
|
|
|
# Removing byte from line end, removes 1 line
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.TargetEnd = i
|
|
|
|
|
self.ed.ReplaceTarget(1, text[i:i+1])
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testNELRemoveEOLFragment(self):
|
|
|
|
|
# Add UTF-8 NEL then delete each byte causing line end to disappear
|
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
for i in range(2):
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.AddText(4, b"x\xc2\x85y")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.TargetStart = i+1
|
|
|
|
|
self.ed.TargetEnd = i+2
|
|
|
|
|
self.ed.ReplaceTarget(0, b"")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineCount, 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testGoto(self):
|
|
|
|
|
self.ed.AddText(5, b"a\nb\nc")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 5)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.GotoLine(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.GotoPos(4)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CurrentPos, 4)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testCutCopyPaste(self):
|
|
|
|
|
self.ed.AddText(5, b"a1b2c")
|
|
|
|
|
self.ed.SetSel(1,3)
|
|
|
|
|
self.ed.Cut()
|
2019-05-04 20:14:48 +02:00
|
|
|
|
# Clipboard = "1b"
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a2c")
|
|
|
|
|
self.assertEqual(self.ed.CanPaste(), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0, 0)
|
|
|
|
|
self.ed.Paste()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1ba2c")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(4,5)
|
|
|
|
|
self.ed.Copy()
|
2019-05-04 20:14:48 +02:00
|
|
|
|
# Clipboard = "c"
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(1,3)
|
|
|
|
|
self.ed.Paste()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1c2c")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(2,4)
|
|
|
|
|
self.ed.Clear()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1c")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
def testReplaceRectangular(self):
|
|
|
|
|
self.ed.AddText(5, b"a\nb\nc")
|
|
|
|
|
self.ed.SetSel(0,0)
|
|
|
|
|
self.ed.ReplaceRectangular(3, b"1\n2")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1a\n2b\nc")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testCopyAllowLine(self):
|
|
|
|
|
lineEndType = self.ed.EOLMode
|
|
|
|
|
self.ed.EOLMode = self.ed.SC_EOL_LF
|
|
|
|
|
self.ed.AddText(5, b"a1\nb2")
|
|
|
|
|
self.ed.SetSel(1,1)
|
|
|
|
|
self.ed.CopyAllowLine()
|
2019-05-04 20:14:48 +02:00
|
|
|
|
# Clipboard = "a1\n"
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CanPaste(), 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(0, 0)
|
|
|
|
|
self.ed.Paste()
|
|
|
|
|
self.ed.EOLMode = lineEndType
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a1\na1\nb2")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
|
|
|
|
def testDuplicate(self):
|
|
|
|
|
self.ed.AddText(3, b"1b2")
|
|
|
|
|
self.ed.SetSel(1,2)
|
|
|
|
|
self.ed.SelectionDuplicate()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1bb2")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2023-02-09 17:57:24 +01:00
|
|
|
|
def testLineDuplicate(self):
|
|
|
|
|
self.ed.SetContents(b"1\r\nb\r\n2")
|
|
|
|
|
self.ed.SetSel(3, 3)
|
|
|
|
|
# Duplicates the second line containing 'b'
|
|
|
|
|
self.ed.LineDuplicate()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1\r\nb\r\nb\r\n2")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
def testLineDuplicateDifferentLineEnd(self):
|
|
|
|
|
self.ed.SetContents(b"1\nb\n2")
|
|
|
|
|
self.ed.SetSel(3, 3)
|
|
|
|
|
# Duplicates the second line containing 'b'
|
|
|
|
|
self.ed.LineDuplicate()
|
Update: Scintilla 5.3.6 and Lexilla 5.2.6
update to Scinitlla Release 5.3.6 (https://www.scintilla.org/scintilla536.zip)
Released 26 July 2023.
Redraw calltip after showing as didn't update when size of new text exactly same as previous. Feature #1486.
On Win32 fix reverse arrow cursor when scaled. Bug #2382.
On Win32 hide cursor when typing if that system preference has been chosen. Bug #2333.
On Win32 and Qt, stop aligning IME candidate window to target. It is now always aligned to start of composition string. This undoes part of feature #1300. Feature #1488, Bug #2391, Feature #1300.
On Qt, for IMEs, update micro focus when selection changes. This may move the location of IME popups to align with the caret.
On Qt, implement replacement for IMEs which may help with actions like reconversion. This is similar to delete-surrounding on GTK.
and Lexilla Release 5.2.6 (https://www.scintilla.org/lexilla526.zip)
Released 26 July 2023.
Include empty word list names in value returned by DescribeWordListSets and SCI_DESCRIBEKEYWORDSETS. Issue #175, Pull request #176.
Bash: style here-doc end delimiters as SCE_SH_HERE_DELIM instead of SCE_SH_HERE_Q. Issue #177.
Bash: allow '$' as last character in string. Issue #180, Pull request #181.
Bash: fix state after expansion. Highlight all numeric and file test operators. Don't highlight dash in long option as operator. Issue #182, Pull request #183.
Bash: strict checking of special parameters ($*, $@, $$, ...) with property lexer.bash.special.parameter to specify valid parameters. Issue #184, Pull request #186.
Bash: recognize keyword before redirection operators (< and >). Issue #188, Pull request #189.
Errorlist: recognize Bash diagnostic messages.
HTML: allow ASP block to terminate inside line comment. Issue #185.
HTML: fix folding with JSP/ASP.NET <%-- comment. Issue #191.
HTML: fix incremental styling of multi-line ASP.NET directive. Issue #191.
Matlab: improve arguments blocks. Add support for multiple arguments blocks. Prevent "arguments" from being keyword in function declaration line. Fix semicolon handling. Pull request #179.
Visual Prolog: add support for embedded syntax with SCE_VISUALPROLOG_EMBEDDED and SCE_VISUALPROLOG_PLACEHOLDER.
Styling of string literals changed with no differentiation between literals with quotes and those that are prefixed with "@". Quote characters are in a separate style (SCE_VISUALPROLOG_STRING_QUOTE) to contents (SCE_VISUALPROLOG_STRING).
SCE_VISUALPROLOG_CHARACTER, SCE_VISUALPROLOG_CHARACTER_TOO_MANY, SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR, SCE_VISUALPROLOG_STRING_EOL_OPEN, and SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL were removed (replaced with SCE_VISUALPROLOG_UNUSED[1-5]). Pull request #178.
Fix #13901, fix #13911, fix #13943, close #13940
2023-07-27 19:57:12 +02:00
|
|
|
|
# Same as above but end of duplicated line is \r\n
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"1\nb\r\nb\n2")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testTransposeLines(self):
|
|
|
|
|
self.ed.AddText(8, b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(3,3)
|
|
|
|
|
self.ed.LineTranspose()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"b2\na1\nc3")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2023-02-09 17:57:24 +01:00
|
|
|
|
def testReverseLines(self):
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(0, 8)
|
|
|
|
|
self.ed.LineReverse()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"c3\nb2\na1")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3\n")
|
|
|
|
|
self.ed.SetSel(0, 9)
|
|
|
|
|
self.ed.LineReverse()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"c3\nb2\na1\n")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
def testMoveSelectedLines(self):
|
|
|
|
|
lineEndType = self.ed.EOLMode
|
|
|
|
|
self.ed.EOLMode = self.ed.SC_EOL_LF
|
|
|
|
|
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(3, 6)
|
|
|
|
|
self.ed.MoveSelectedLinesDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a1\nc3\nb2")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(3, 6)
|
|
|
|
|
self.ed.MoveSelectedLinesUp()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"b2\na1\nc3")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
# Exercise the 'appendEol' case as the last line has no EOL characters to copy
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(4, 7)
|
|
|
|
|
self.ed.MoveSelectedLinesUp()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"b2\nc3\na1")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
# Testing extreme lines
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(6, 7)
|
|
|
|
|
self.ed.MoveSelectedLinesDown()
|
|
|
|
|
# No change as moving last line down
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a1\nb2\nc3")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(1, 2)
|
|
|
|
|
self.ed.MoveSelectedLinesUp()
|
|
|
|
|
# No change as moving first line up
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a1\nb2\nc3")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
# Moving line to end with different line end uses that line end
|
|
|
|
|
self.ed.EOLMode = self.ed.SC_EOL_CRLF
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(3, 6)
|
|
|
|
|
self.ed.MoveSelectedLinesDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a1\nc3\r\nb2")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
# Exercise 'appendEol'
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(4, 7)
|
|
|
|
|
self.ed.MoveSelectedLinesUp()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"b2\nc3\r\na1")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.SetSel(1, 2)
|
|
|
|
|
self.ed.MoveSelectedLinesDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"b2\na1\nc3")
|
|
|
|
|
|
|
|
|
|
# Exercise rectangular selection
|
|
|
|
|
self.ed.EOLMode = self.ed.SC_EOL_LF
|
|
|
|
|
self.ed.SetContents(b"a1\nb2\nc3")
|
|
|
|
|
self.ed.RectangularSelectionAnchor = 1
|
|
|
|
|
self.ed.RectangularSelectionCaret = 4
|
|
|
|
|
# Check rectangular not stream
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionMode(), self.ed.SC_SEL_RECTANGLE)
|
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.ed.MoveSelectedLinesDown()
|
|
|
|
|
self.assertEqual(self.ed.Contents(), b"c3\na1\nb2")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
# Restore line end
|
|
|
|
|
self.ed.EOLMode = lineEndType
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testGetSet(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(b"abc")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TextLength, 3)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
# String buffer containing exactly 5 digits
|
|
|
|
|
result = ctypes.create_string_buffer(b"12345", 5)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result.raw, b"12345")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
length = self.ed.GetText(4, result)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(length, 3)
|
|
|
|
|
self.assertEqual(result.value, b"abc")
|
2019-07-21 15:26:02 +02:00
|
|
|
|
# GetText has written the 3 bytes of text and a terminating NUL but left the final digit 5
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result.raw, b"abc\x005")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testAppend(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(b"abc")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionStart, 0)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
text = b"12"
|
|
|
|
|
self.ed.AppendText(len(text), text)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionStart, 0)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, 0)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), b"abc12")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testTarget(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(b"abcd")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 3
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TargetStart, 1)
|
|
|
|
|
self.assertEqual(self.ed.TargetEnd, 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
rep = b"321"
|
|
|
|
|
self.ed.ReplaceTarget(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a321d")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SearchFlags = self.ed.SCFIND_REGEXP
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SearchFlags, self.ed.SCFIND_REGEXP)
|
|
|
|
|
searchString = rb"\([1-9]+\)"
|
2013-01-25 01:46:29 +01:00
|
|
|
|
pos = self.ed.SearchInTarget(len(searchString), searchString)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(1, pos)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
tagString = self.ed.GetTag(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(tagString, b"321")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
rep = b"\\1"
|
|
|
|
|
self.ed.TargetStart = 0
|
|
|
|
|
self.ed.TargetEnd = 0
|
|
|
|
|
self.ed.ReplaceTargetRE(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"321a321d")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(4,5)
|
|
|
|
|
self.ed.TargetFromSelection()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TargetStart, 4)
|
|
|
|
|
self.assertEqual(self.ed.TargetEnd, 5)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-12-10 13:35:16 +01:00
|
|
|
|
def testReplaceTargetMinimal(self):
|
|
|
|
|
# 1: No common characters
|
|
|
|
|
self.ed.SetContents(b"abcd")
|
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 3
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TargetStart, 1)
|
|
|
|
|
self.assertEqual(self.ed.TargetEnd, 3)
|
2022-12-10 13:35:16 +01:00
|
|
|
|
rep = b"321"
|
|
|
|
|
self.ed.ReplaceTargetMinimal(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a321d")
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
|
|
|
|
# 2: New characters with common prefix and suffix
|
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 4
|
|
|
|
|
rep = b"3<>1"
|
|
|
|
|
self.ed.ReplaceTargetMinimal(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a3<>1d")
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
|
|
|
|
# 3: Remove characters with common prefix and suffix
|
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 5
|
|
|
|
|
rep = b"31"
|
|
|
|
|
self.ed.ReplaceTargetMinimal(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a31d")
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
|
|
|
|
# 4: Common prefix
|
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 3
|
|
|
|
|
rep = b"3bc"
|
|
|
|
|
self.ed.ReplaceTargetMinimal(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a3bcd")
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
|
|
|
|
# 5: Common suffix
|
|
|
|
|
self.ed.TargetStart = 2
|
|
|
|
|
self.ed.TargetEnd = 5
|
|
|
|
|
rep = b"cd"
|
|
|
|
|
self.ed.ReplaceTargetMinimal(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a3cd")
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
2019-05-04 20:14:48 +02:00
|
|
|
|
def testTargetWhole(self):
|
|
|
|
|
self.ed.SetContents(b"abcd")
|
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 3
|
|
|
|
|
self.ed.TargetWholeDocument()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TargetStart, 0)
|
|
|
|
|
self.assertEqual(self.ed.TargetEnd, 4)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testTargetEscape(self):
|
|
|
|
|
# Checks that a literal \ can be in the replacement. Bug #2959876
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(b"abcd")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 3
|
|
|
|
|
rep = b"\\\\n"
|
|
|
|
|
self.ed.ReplaceTargetRE(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a\\nd")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
def testTargetVirtualSpace(self):
|
|
|
|
|
self.ed.SetContents(b"a\nbcd")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TargetStart, 0)
|
|
|
|
|
self.assertEqual(self.ed.TargetStartVirtualSpace, 0)
|
|
|
|
|
self.assertEqual(self.ed.TargetEnd, 5)
|
|
|
|
|
self.assertEqual(self.ed.TargetEndVirtualSpace, 0)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetStartVirtualSpace = 2
|
|
|
|
|
self.ed.TargetEnd = 3
|
|
|
|
|
self.ed.TargetEndVirtualSpace = 4
|
|
|
|
|
# Adds 2 spaces to first line due to virtual space, and replace 2 characters with 3
|
|
|
|
|
rep = b"12\n"
|
|
|
|
|
self.ed.ReplaceTarget(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a 12\ncd")
|
2021-02-21 05:53:09 +01:00
|
|
|
|
# 1+2v realized to 3
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.TargetStart, 3)
|
|
|
|
|
self.assertEqual(self.ed.TargetStartVirtualSpace, 0)
|
|
|
|
|
self.assertEqual(self.ed.TargetEnd, 6)
|
|
|
|
|
self.assertEqual(self.ed.TargetEndVirtualSpace, 0)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testPointsAndPositions(self):
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.ed.SetContents(b"xyz")
|
|
|
|
|
|
|
|
|
|
# Inter-character positions
|
|
|
|
|
# Start of text
|
|
|
|
|
self.assertEqual(self.ed.PositionFromPoint(1,1), 0)
|
|
|
|
|
# End of text
|
|
|
|
|
self.assertEqual(self.ed.PositionFromPoint(100, 1), 3)
|
|
|
|
|
self.assertEqual(self.ed.PositionFromPointClose(100, 1), -1)
|
|
|
|
|
|
|
|
|
|
# Character positions
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Start of text
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(self.ed.CharPositionFromPoint(0,0), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# End of text
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(self.ed.CharPositionFromPoint(100, 0), 3)
|
|
|
|
|
self.assertEqual(self.ed.CharPositionFromPointClose(100, 0), -1)
|
|
|
|
|
|
|
|
|
|
def testSelectionFromPoint(self):
|
|
|
|
|
self.ed.SetContents(b"xxxxxx")
|
|
|
|
|
self.ed.SetSelection(3, 2)
|
|
|
|
|
self.ed.AddSelection(0, 1)
|
|
|
|
|
self.ed.AddSelection(5, 5) # Empty
|
|
|
|
|
xStart = self.ed.PointXFromPosition(0, 0)
|
|
|
|
|
xEnd = self.ed.PointXFromPosition(0, 5)
|
|
|
|
|
width = xEnd-xStart
|
|
|
|
|
charWidth = width // 5
|
|
|
|
|
widthMid = charWidth // 2
|
|
|
|
|
|
|
|
|
|
posMid1 = xStart+widthMid
|
|
|
|
|
self.assertEqual(self.ed.SelectionFromPoint(posMid1, 1), 1)
|
|
|
|
|
posMid2 = xStart+charWidth+widthMid
|
|
|
|
|
self.assertEqual(self.ed.SelectionFromPoint(posMid2, 1), -1)
|
|
|
|
|
posMid3 = xStart+charWidth*2+widthMid
|
|
|
|
|
self.assertEqual(self.ed.SelectionFromPoint(posMid3, 1), 0)
|
|
|
|
|
# Empty selection at 5. Exact and then a few pixels either side
|
|
|
|
|
self.assertEqual(self.ed.SelectionFromPoint(xEnd, 1), 2)
|
|
|
|
|
self.assertEqual(self.ed.SelectionFromPoint(xEnd-2, 1), 2)
|
|
|
|
|
self.assertEqual(self.ed.SelectionFromPoint(xEnd+2, 1), 2)
|
|
|
|
|
self.assertEqual(self.ed.SelectionFromPoint(100, 0), -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testLinePositions(self):
|
|
|
|
|
text = b"ab\ncd\nef"
|
|
|
|
|
nl = b"\n"
|
|
|
|
|
if sys.version_info[0] == 3:
|
|
|
|
|
nl = ord(b"\n")
|
|
|
|
|
self.ed.AddText(len(text), text)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineFromPosition(-1), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
line = 0
|
|
|
|
|
for pos in range(len(text)+1):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineFromPosition(pos), line)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
if pos < len(text) and text[pos] == nl:
|
|
|
|
|
line += 1
|
|
|
|
|
|
|
|
|
|
def testWordPositions(self):
|
|
|
|
|
text = b"ab cd\tef"
|
|
|
|
|
self.ed.AddText(len(text), text)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.WordStartPosition(3, 0), 2)
|
|
|
|
|
self.assertEqual(self.ed.WordStartPosition(4, 0), 3)
|
|
|
|
|
self.assertEqual(self.ed.WordStartPosition(5, 0), 3)
|
|
|
|
|
self.assertEqual(self.ed.WordStartPosition(6, 0), 5)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.WordEndPosition(2, 0), 3)
|
|
|
|
|
self.assertEqual(self.ed.WordEndPosition(3, 0), 5)
|
|
|
|
|
self.assertEqual(self.ed.WordEndPosition(4, 0), 5)
|
|
|
|
|
self.assertEqual(self.ed.WordEndPosition(5, 0), 6)
|
|
|
|
|
self.assertEqual(self.ed.WordEndPosition(6, 0), 8)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2019-05-04 20:14:48 +02:00
|
|
|
|
def testWordRange(self):
|
|
|
|
|
text = b"ab cd\t++"
|
|
|
|
|
self.ed.AddText(len(text), text)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(0, 0), 0)
|
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(0, 1), 0)
|
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(0, 2), 1)
|
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(0, 3), 0)
|
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(0, 4), 0)
|
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(0, 5), 1)
|
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(6, 7), 0)
|
|
|
|
|
self.assertEqual(self.ed.IsRangeWord(6, 8), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
2022-10-12 20:45:40 +02:00
|
|
|
|
class TestChangeHistory(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.data = b"xy"
|
|
|
|
|
|
|
|
|
|
def testChangeHistory(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ChangeHistory, 0)
|
|
|
|
|
self.assertEqual(self.ed.UndoCollection, 1)
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.ed.UndoCollection = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.UndoCollection, 0)
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.ed.InsertText(0, self.data)
|
|
|
|
|
self.ed.UndoCollection = 1
|
|
|
|
|
self.ed.ChangeHistory = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ChangeHistory, 1)
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.ed.InsertText(0, self.data)
|
|
|
|
|
self.ed.DeleteRange(0, 2)
|
|
|
|
|
self.ed.ChangeHistory = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ChangeHistory, 0)
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.ed.ChangeHistory = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ChangeHistory, 1)
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.ed.Undo()
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
MODI = 1
|
|
|
|
|
UNDO = 2
|
|
|
|
|
REDO = 4
|
|
|
|
|
|
|
|
|
|
class TestContainerUndo(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.data = b"xy"
|
|
|
|
|
|
|
|
|
|
def UndoState(self):
|
|
|
|
|
return (MODI if self.ed.Modify else 0) | \
|
|
|
|
|
(UNDO if self.ed.CanUndo() else 0) | \
|
|
|
|
|
(REDO if self.ed.CanRedo() else 0)
|
|
|
|
|
|
|
|
|
|
def testContainerActNoCoalesce(self):
|
|
|
|
|
self.ed.InsertText(0, self.data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddUndoAction(5, 0)
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO | REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Redo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo()
|
|
|
|
|
|
|
|
|
|
def testContainerActCoalesce(self):
|
|
|
|
|
self.ed.InsertText(0, self.data)
|
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Redo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testContainerMultiStage(self):
|
|
|
|
|
self.ed.InsertText(0, self.data)
|
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Redo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testContainerMultiStageNoText(self):
|
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Redo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testContainerActCoalesceEnd(self):
|
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, self.data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Redo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testContainerBetweenInsertAndInsert(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, self.data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(2, self.data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 4)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Undoes both insertions and the containerAction in the middle
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testContainerNoCoalesceBetweenInsertAndInsert(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, self.data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddUndoAction(5, 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(2, self.data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 4)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Undo last insertion
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO | REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Undo container
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO | REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Undo first insertion
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testContainerBetweenDeleteAndDelete(self):
|
|
|
|
|
self.ed.InsertText(0, self.data)
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(2,2)
|
|
|
|
|
self.ed.DeleteBack()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
|
|
|
|
self.ed.DeleteBack()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Undoes both deletions and the containerAction in the middle
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testContainerBetweenInsertAndDelete(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.InsertText(0, self.data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AddUndoAction(5, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0,1)
|
|
|
|
|
self.ed.Cut()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 1)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.Undo() # Only undoes the deletion
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
|
|
|
|
self.assertEqual(self.UndoState(), MODI | UNDO | REDO)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
class TestKeyCommands(unittest.TestCase):
|
|
|
|
|
""" These commands are normally assigned to keys and take no arguments """
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def selRange(self):
|
|
|
|
|
return self.ed.CurrentPos, self.ed.Anchor
|
|
|
|
|
|
|
|
|
|
def testLineMove(self):
|
|
|
|
|
self.ed.AddText(8, b"x1\ny2\nz3")
|
|
|
|
|
self.ed.SetSel(0,0)
|
|
|
|
|
self.ed.ChooseCaretX()
|
|
|
|
|
self.ed.LineDown()
|
|
|
|
|
self.ed.LineDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (6, 6))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.LineUp()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (3, 3))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.LineDownExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (6, 3))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.LineUpExtend()
|
|
|
|
|
self.ed.LineUpExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (0, 3))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testCharMove(self):
|
|
|
|
|
self.ed.AddText(8, b"x1\ny2\nz3")
|
|
|
|
|
self.ed.SetSel(0,0)
|
|
|
|
|
self.ed.CharRight()
|
|
|
|
|
self.ed.CharRight()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (2, 2))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.CharLeft()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (1, 1))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.CharRightExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (2, 1))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.CharLeftExtend()
|
|
|
|
|
self.ed.CharLeftExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (0, 1))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testWordMove(self):
|
|
|
|
|
self.ed.AddText(10, b"a big boat")
|
|
|
|
|
self.ed.SetSel(3,3)
|
|
|
|
|
self.ed.WordRight()
|
|
|
|
|
self.ed.WordRight()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (10, 10))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.WordLeft()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (6, 6))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.WordRightExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (10, 6))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.WordLeftExtend()
|
|
|
|
|
self.ed.WordLeftExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (2, 6))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testHomeEndMove(self):
|
|
|
|
|
self.ed.AddText(10, b"a big boat")
|
|
|
|
|
self.ed.SetSel(3,3)
|
|
|
|
|
self.ed.Home()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (0, 0))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.LineEnd()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (10, 10))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(3,3)
|
|
|
|
|
self.ed.HomeExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (0, 3))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.LineEndExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (10, 3))
|
|
|
|
|
|
|
|
|
|
def testVCHome(self):
|
|
|
|
|
# Goes to the indent unless there already when goes to origin
|
|
|
|
|
self.ed.AddText(10, b" a big boat")
|
|
|
|
|
self.ed.SetSel(6,6)
|
|
|
|
|
self.ed.VCHome()
|
|
|
|
|
self.assertEqual(self.selRange(), (3, 3))
|
|
|
|
|
self.ed.VCHome()
|
|
|
|
|
self.assertEqual(self.selRange(), (0, 0))
|
|
|
|
|
self.ed.VCHome()
|
|
|
|
|
self.assertEqual(self.selRange(), (3, 3))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testStartEndMove(self):
|
|
|
|
|
self.ed.AddText(10, b"a\nbig\nboat")
|
|
|
|
|
self.ed.SetSel(3,3)
|
|
|
|
|
self.ed.DocumentStart()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (0, 0))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.DocumentEnd()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (10, 10))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(3,3)
|
|
|
|
|
self.ed.DocumentStartExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (0, 3))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.DocumentEndExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (10, 3))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-12-10 13:35:16 +01:00
|
|
|
|
def testParagraphMove(self):
|
|
|
|
|
example = b"a\n\nbig\n\n\n\nboat"
|
|
|
|
|
self.ed.AddText(len(example), example)
|
|
|
|
|
start1 = 0 # Before 'a'
|
|
|
|
|
start2 = 3 # Before 'big'
|
|
|
|
|
start3 = 10 # Before 'boat'
|
|
|
|
|
|
|
|
|
|
# Paragraph 2 to 1
|
|
|
|
|
self.ed.SetSel(start2, start2)
|
|
|
|
|
self.ed.ParaUp()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start1, start1))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.ParaDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start2, start2))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.SetSel(start2, start2)
|
|
|
|
|
self.ed.ParaUpExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start1, start2))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.ParaDownExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start2, start2))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
|
|
|
|
# Inside paragraph 2 to start paragraph 2
|
|
|
|
|
mid2 = start2+1
|
|
|
|
|
self.ed.SetSel(mid2, mid2)
|
|
|
|
|
# Next line behaved differently before change for bug #2363
|
|
|
|
|
self.ed.ParaUp()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start2, start2))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.ParaDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start3, start3))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.SetSel(mid2, mid2)
|
|
|
|
|
self.ed.ParaUpExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start2, mid2))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.ParaDownExtend()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start3, mid2))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
|
|
|
|
# Paragraph 3 to 2
|
|
|
|
|
self.ed.SetSel(start3, start3)
|
|
|
|
|
self.ed.ParaUp()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start2, start2))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
self.ed.ParaDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.selRange(), (start3, start3))
|
2022-12-10 13:35:16 +01:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
class TestMarkers(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.ed.AddText(5, b"x\ny\nz")
|
|
|
|
|
|
|
|
|
|
def testMarker(self):
|
|
|
|
|
handle = self.ed.MarkerAdd(1,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(handle), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerDelete(1,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(handle), -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testTwiceAddedDelete(self):
|
|
|
|
|
handle = self.ed.MarkerAdd(1,1)
|
2023-06-01 01:11:12 +02:00
|
|
|
|
self.assertNotEqual(handle, -1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(1), 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
handle2 = self.ed.MarkerAdd(1,1)
|
2023-06-01 01:11:12 +02:00
|
|
|
|
self.assertNotEqual(handle2, -1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(1), 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.MarkerDelete(1,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(1), 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.MarkerDelete(1,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(1), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testMarkerDeleteAll(self):
|
|
|
|
|
h1 = self.ed.MarkerAdd(0,1)
|
|
|
|
|
h2 = self.ed.MarkerAdd(1,2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(h1), 0)
|
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(h2), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerDeleteAll(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(h1), -1)
|
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(h2), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerDeleteAll(-1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(h1), -1)
|
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(h2), -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testMarkerDeleteHandle(self):
|
|
|
|
|
handle = self.ed.MarkerAdd(0,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(handle), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerDeleteHandle(handle)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerLineFromHandle(handle), -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testMarkerBits(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(0), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerAdd(0,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(0), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerAdd(0,2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(0), 6)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testMarkerAddSet(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(0), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerAddSet(0,5)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGet(0), 5)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarkerDeleteAll(-1)
|
|
|
|
|
|
|
|
|
|
def testMarkerNext(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerNext(0, 2), -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
h1 = self.ed.MarkerAdd(0,1)
|
2023-06-01 01:11:12 +02:00
|
|
|
|
self.assertNotEqual(h1, -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
h2 = self.ed.MarkerAdd(2,1)
|
2023-06-01 01:11:12 +02:00
|
|
|
|
self.assertNotEqual(h2, -1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerNext(0, 2), 0)
|
|
|
|
|
self.assertEqual(self.ed.MarkerNext(1, 2), 2)
|
|
|
|
|
self.assertEqual(self.ed.MarkerNext(2, 2), 2)
|
|
|
|
|
self.assertEqual(self.ed.MarkerPrevious(0, 2), 0)
|
|
|
|
|
self.assertEqual(self.ed.MarkerPrevious(1, 2), 0)
|
|
|
|
|
self.assertEqual(self.ed.MarkerPrevious(2, 2), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testMarkerNegative(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerNext(-1, 2), -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testLineState(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MaxLineState, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetLineState(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetLineState(1), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetLineState(2), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetLineState(1, 100)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertNotEqual(self.ed.MaxLineState, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetLineState(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetLineState(1), 100)
|
|
|
|
|
self.assertEqual(self.ed.GetLineState(2), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testSymbolRetrieval(self):
|
|
|
|
|
self.ed.MarkerDefine(1,3)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerSymbolDefined(1), 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
def markerFromLineIndex(self, line, index):
|
|
|
|
|
""" Helper that returns (handle, number) """
|
|
|
|
|
return (self.ed.MarkerHandleFromLine(line, index), self.ed.MarkerNumberFromLine(line, index))
|
|
|
|
|
|
|
|
|
|
def markerSetFromLine(self, line):
|
|
|
|
|
""" Helper that returns set of (handle, number) """
|
|
|
|
|
markerSet = set()
|
|
|
|
|
index = 0
|
|
|
|
|
while 1:
|
|
|
|
|
marker = self.markerFromLineIndex(line, index)
|
|
|
|
|
if marker[0] == -1:
|
|
|
|
|
return markerSet
|
|
|
|
|
markerSet.add(marker)
|
|
|
|
|
index += 1
|
|
|
|
|
|
|
|
|
|
def testMarkerFromLine(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerHandleFromLine(1, 0), -1)
|
|
|
|
|
self.assertEqual(self.ed.MarkerNumberFromLine(1, 0), -1)
|
|
|
|
|
self.assertEqual(self.markerFromLineIndex(1, 0), (-1, -1))
|
|
|
|
|
self.assertEqual(self.markerSetFromLine(1), set())
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
handle = self.ed.MarkerAdd(1,10)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.markerFromLineIndex(1, 0), (handle, 10))
|
|
|
|
|
self.assertEqual(self.markerFromLineIndex(1, 1), (-1, -1))
|
|
|
|
|
self.assertEqual(self.markerSetFromLine(1), {(handle, 10)})
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
handle2 = self.ed.MarkerAdd(1,11)
|
|
|
|
|
# Don't want to depend on ordering so check as sets
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.markerSetFromLine(1), {(handle, 10), (handle2, 11)})
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
self.ed.MarkerDeleteHandle(handle2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.markerSetFromLine(1), {(handle, 10)})
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestIndicators(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
def indicatorValueString(self, indicator):
|
|
|
|
|
# create a string with -/X where indicator off/on to make checks simple
|
|
|
|
|
return "".join("-X"[self.ed.IndicatorValueAt(indicator, index)] for index in range(self.ed.TextLength))
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testSetIndicator(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndicGetStyle(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.IndicGetFore(0), 0x007f00)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.IndicSetStyle(0, 2)
|
|
|
|
|
self.ed.IndicSetFore(0, 0xff0080)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndicGetStyle(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.IndicGetFore(0), 0xff0080)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testIndicatorFill(self):
|
|
|
|
|
self.ed.InsertText(0, b"abc")
|
|
|
|
|
self.ed.IndicatorCurrent = 3
|
|
|
|
|
self.ed.IndicatorFillRange(1,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.indicatorValueString(3), "-X-")
|
|
|
|
|
self.assertEqual(self.ed.IndicatorStart(3, 0), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorEnd(3, 0), 1)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorStart(3, 1), 1)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorEnd(3, 1), 2)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorStart(3, 2), 2)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorEnd(3, 2), 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testIndicatorAtEnd(self):
|
|
|
|
|
self.ed.InsertText(0, b"ab")
|
|
|
|
|
self.ed.IndicatorCurrent = 3
|
|
|
|
|
self.ed.IndicatorFillRange(1,1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndicatorValueAt(3, 0), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorValueAt(3, 1), 1)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorStart(3, 0), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorEnd(3, 0), 1)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorStart(3, 1), 1)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorEnd(3, 1), 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.DeleteRange(1, 1)
|
|
|
|
|
# Now only one character left and does not have indicator so indicator 3 is null
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndicatorValueAt(3, 0), 0)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# Since null, remaining calls return 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndicatorStart(3, 0), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorEnd(3, 0), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorStart(3, 1), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndicatorEnd(3, 1), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
def testIndicatorMovement(self):
|
|
|
|
|
# Create a two character indicator over "BC" in "aBCd" and ensure that it doesn't
|
|
|
|
|
# leak onto surrounding characters when insertions made at either end but
|
|
|
|
|
# insertion inside indicator does extend length
|
|
|
|
|
self.ed.InsertText(0, b"aBCd")
|
|
|
|
|
self.ed.IndicatorCurrent = 3
|
|
|
|
|
self.ed.IndicatorFillRange(1,2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.indicatorValueString(3), "-XX-")
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
# Insertion 1 before
|
|
|
|
|
self.ed.InsertText(0, b"1")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(b"1aBCd", self.ed.Contents())
|
|
|
|
|
self.assertEqual(self.indicatorValueString(3), "--XX-")
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
# Insertion at start of indicator
|
|
|
|
|
self.ed.InsertText(2, b"2")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(b"1a2BCd", self.ed.Contents())
|
|
|
|
|
self.assertEqual(self.indicatorValueString(3), "---XX-")
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
# Insertion inside indicator
|
|
|
|
|
self.ed.InsertText(4, b"3")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(b"1a2B3Cd", self.ed.Contents())
|
|
|
|
|
self.assertEqual(self.indicatorValueString(3), "---XXX-")
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
# Insertion at end of indicator
|
|
|
|
|
self.ed.InsertText(6, b"4")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(b"1a2B3C4d", self.ed.Contents())
|
|
|
|
|
self.assertEqual(self.indicatorValueString(3), "---XXX--")
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
# Insertion 1 after
|
|
|
|
|
self.ed.InsertText(8, b"5")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.indicatorValueString(3), "---XXX---")
|
|
|
|
|
self.assertEqual(b"1a2B3C4d5", self.ed.Contents())
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestScrolling(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
# 150 should be enough lines
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.InsertText(0, b"a" * 150 + b"\n" * 150)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testTop(self):
|
|
|
|
|
self.ed.GotoLine(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FirstVisibleLine, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testLineScroll(self):
|
|
|
|
|
self.ed.GotoLine(0)
|
|
|
|
|
self.ed.LineScroll(0, 3)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FirstVisibleLine, 3)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.LineScroll(0, -2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FirstVisibleLine, 1)
|
|
|
|
|
self.assertEqual(self.ed.XOffset, 0)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.LineScroll(10, 0)
|
|
|
|
|
self.assertGreater(self.ed.XOffset, 0)
|
|
|
|
|
scroll_width = float(self.ed.XOffset) / 10
|
|
|
|
|
self.ed.LineScroll(-2, 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.XOffset, scroll_width * 8)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testVisibleLine(self):
|
|
|
|
|
self.ed.FirstVisibleLine = 7
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FirstVisibleLine, 7)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
class TestSearch(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.ed.InsertText(0, b"a\tbig boat\t")
|
|
|
|
|
|
|
|
|
|
def testFind(self):
|
|
|
|
|
pos = self.ed.FindBytes(0, self.ed.Length, b"zzz", 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(pos, -1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
pos = self.ed.FindBytes(0, self.ed.Length, b"big", 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(pos, 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-05-25 22:16:39 +02:00
|
|
|
|
def testFindFull(self):
|
|
|
|
|
pos = self.ed.FindBytesFull(0, self.ed.Length, b"zzz", 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(pos, -1)
|
2022-05-25 22:16:39 +02:00
|
|
|
|
pos = self.ed.FindBytesFull(0, self.ed.Length, b"big", 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(pos, 2)
|
2022-05-25 22:16:39 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testFindEmpty(self):
|
|
|
|
|
pos = self.ed.FindBytes(0, self.ed.Length, b"", 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(pos, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testCaseFind(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"big", 0), 2)
|
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"bIg", 0), 2)
|
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"bIg",
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SCFIND_MATCHCASE), -1)
|
|
|
|
|
|
|
|
|
|
def testWordFind(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"bi", 0), 2)
|
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"bi",
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SCFIND_WHOLEWORD), -1)
|
|
|
|
|
|
|
|
|
|
def testWordStartFind(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"bi", 0), 2)
|
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"bi",
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SCFIND_WORDSTART), 2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"ig", 0), 3)
|
|
|
|
|
self.assertEqual(self.ed.FindBytes(0, self.ed.Length, b"ig",
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SCFIND_WORDSTART), -1)
|
|
|
|
|
|
|
|
|
|
def testREFind(self):
|
|
|
|
|
flags = self.ed.SCFIND_REGEXP
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"b.g", 0))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"b.g", flags))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, rb"\<b.g\>", flags))
|
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"b[A-Z]g",
|
2013-01-25 01:46:29 +01:00
|
|
|
|
flags | self.ed.SCFIND_MATCHCASE))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]g", flags))
|
|
|
|
|
self.assertEqual(6, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]*t", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, b"^a", flags))
|
|
|
|
|
self.assertEqual(10, self.ed.FindBytes(0, self.ed.Length, b"\t$", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, b"\\([a]\\).*\0", flags))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testPosixREFind(self):
|
|
|
|
|
flags = self.ed.SCFIND_REGEXP | self.ed.SCFIND_POSIX
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"b.g", 0))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"b.g", flags))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, rb"\<b.g\>", flags))
|
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"b[A-Z]g",
|
2013-01-25 01:46:29 +01:00
|
|
|
|
flags | self.ed.SCFIND_MATCHCASE))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]g", flags))
|
|
|
|
|
self.assertEqual(6, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]*t", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, b"^a", flags))
|
|
|
|
|
self.assertEqual(10, self.ed.FindBytes(0, self.ed.Length, b"\t$", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, b"([a]).*\0", flags))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
def testCxx11REFind(self):
|
|
|
|
|
flags = self.ed.SCFIND_REGEXP | self.ed.SCFIND_CXX11REGEX
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"b.g", 0))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"b.g", flags))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, rb"\bb.g\b", flags))
|
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"b[A-Z]g",
|
2022-01-05 00:07:50 +01:00
|
|
|
|
flags | self.ed.SCFIND_MATCHCASE))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]g", flags))
|
|
|
|
|
self.assertEqual(6, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]*t", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, b"^a", flags))
|
|
|
|
|
self.assertEqual(10, self.ed.FindBytes(0, self.ed.Length, b"\t$", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, b"([a]).*\0", flags))
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testCxx11RETooMany(self):
|
|
|
|
|
# For bug #2281
|
|
|
|
|
self.ed.InsertText(0, b"3ringsForTheElvenKing")
|
|
|
|
|
flags = self.ed.SCFIND_REGEXP | self.ed.SCFIND_CXX11REGEX
|
|
|
|
|
# Only MAXTAG (10) matches allocated, but doesn't modify a vulnerable address until 15
|
|
|
|
|
pattern = b"(.)" * 15
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, pattern, flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, pattern, flags))
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testPhilippeREFind(self):
|
|
|
|
|
# Requires 1.,72
|
|
|
|
|
flags = self.ed.SCFIND_REGEXP
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, rb"\w", flags))
|
|
|
|
|
self.assertEqual(1, self.ed.FindBytes(0, self.ed.Length, rb"\W", flags))
|
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, rb"\d", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, rb"\D", flags))
|
|
|
|
|
self.assertEqual(1, self.ed.FindBytes(0, self.ed.Length, rb"\s", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, rb"\S", flags))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"\x62", flags))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testRENonASCII(self):
|
|
|
|
|
self.ed.InsertText(0, b"\xAD")
|
|
|
|
|
flags = self.ed.SCFIND_REGEXP
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"\\x10", flags))
|
|
|
|
|
self.assertEqual(2, self.ed.FindBytes(0, self.ed.Length, b"\\x09", flags))
|
|
|
|
|
self.assertEqual(-1, self.ed.FindBytes(0, self.ed.Length, b"\\xAB", flags))
|
|
|
|
|
self.assertEqual(0, self.ed.FindBytes(0, self.ed.Length, b"\\xAD", flags))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2019-05-04 20:14:48 +02:00
|
|
|
|
def testMultipleAddSelection(self):
|
|
|
|
|
# Find both 'a'
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MultipleSelection, 0)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.MultipleSelection = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MultipleSelection, 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.TargetWholeDocument()
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
self.ed.SetSelection(1, 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.MultipleSelectAddNext()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(1), 8)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(1), 9)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.MultipleSelection = 0
|
|
|
|
|
|
|
|
|
|
def testMultipleAddEachSelection(self):
|
|
|
|
|
# Find each 'b'
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MultipleSelection, 0)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.MultipleSelection = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MultipleSelection, 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.TargetWholeDocument()
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
self.ed.SetSelection(3, 2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.MultipleSelectAddEach()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(1), 6)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(1), 7)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.MultipleSelection = 0
|
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
class TestRepresentations(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def testGetControl(self):
|
|
|
|
|
result = self.ed.GetRepresentation(b"\001")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"SOH")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testClearControl(self):
|
|
|
|
|
result = self.ed.GetRepresentation(b"\002")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"STX")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.ClearRepresentation(b"\002")
|
|
|
|
|
result = self.ed.GetRepresentation(b"\002")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testSetOhm(self):
|
|
|
|
|
ohmSign = b"\xe2\x84\xa6"
|
|
|
|
|
ohmExplained = b"U+2126 \xe2\x84\xa6"
|
|
|
|
|
self.ed.SetRepresentation(ohmSign, ohmExplained)
|
|
|
|
|
result = self.ed.GetRepresentation(ohmSign)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, ohmExplained)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
def testNul(self):
|
|
|
|
|
self.ed.SetRepresentation(b"", b"Nul")
|
|
|
|
|
result = self.ed.GetRepresentation(b"")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"Nul")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testAppearance(self):
|
|
|
|
|
ohmSign = b"\xe2\x84\xa6"
|
|
|
|
|
ohmExplained = b"U+2126 \xe2\x84\xa6"
|
|
|
|
|
self.ed.SetRepresentation(ohmSign, ohmExplained)
|
|
|
|
|
result = self.ed.GetRepresentationAppearance(ohmSign)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, self.ed.SC_REPRESENTATION_BLOB)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.SetRepresentationAppearance(ohmSign, self.ed.SC_REPRESENTATION_PLAIN)
|
|
|
|
|
result = self.ed.GetRepresentationAppearance(ohmSign)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, self.ed.SC_REPRESENTATION_PLAIN)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testColour(self):
|
|
|
|
|
ohmSign = b"\xe2\x84\xa6"
|
|
|
|
|
ohmExplained = b"U+2126 \xe2\x84\xa6"
|
|
|
|
|
self.ed.SetRepresentation(ohmSign, ohmExplained)
|
|
|
|
|
result = self.ed.GetRepresentationColour(ohmSign)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.SetRepresentationColour(ohmSign, 0x10203040)
|
|
|
|
|
result = self.ed.GetRepresentationColour(ohmSign)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, 0x10203040)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(lexersAvailable, "no lexers included")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestProperties(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def testSet(self):
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
|
|
|
|
# For Lexilla, only known property names may work
|
|
|
|
|
propName = b"lexer.cpp.allow.dollars"
|
|
|
|
|
self.ed.SetProperty(propName, b"1")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetPropertyInt(propName), 1)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
result = self.ed.GetProperty(propName)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"1")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.SetProperty(propName, b"0")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetPropertyInt(propName), 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
result = self.ed.GetProperty(propName)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"0")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
# No longer expands but should at least return the value
|
|
|
|
|
result = self.ed.GetPropertyExpanded(propName)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, b"0")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
class TestTextMargin(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.txt = b"abcd"
|
|
|
|
|
self.ed.AddText(1, b"x")
|
|
|
|
|
|
|
|
|
|
def testAscent(self):
|
|
|
|
|
lineHeight = self.ed.TextHeight(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ExtraAscent, 0)
|
|
|
|
|
self.assertEqual(self.ed.ExtraDescent, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ExtraAscent = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ExtraAscent, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.ExtraDescent = 2
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.ExtraDescent, 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
lineHeightIncreased = self.ed.TextHeight(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(lineHeightIncreased, lineHeight + 2 + 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testTextMargin(self):
|
|
|
|
|
self.ed.MarginSetText(0, self.txt)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
result = self.ed.MarginGetText(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, self.txt)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarginTextClearAll()
|
|
|
|
|
|
|
|
|
|
def testTextMarginStyle(self):
|
|
|
|
|
self.ed.MarginSetText(0, self.txt)
|
|
|
|
|
self.ed.MarginSetStyle(0, 33)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarginGetStyle(0), 33)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarginTextClearAll()
|
|
|
|
|
|
|
|
|
|
def testTextMarginStyles(self):
|
|
|
|
|
styles = b"\001\002\003\004"
|
|
|
|
|
self.ed.MarginSetText(0, self.txt)
|
|
|
|
|
self.ed.MarginSetStyles(0, styles)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
result = self.ed.MarginGetStyles(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, styles)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MarginTextClearAll()
|
|
|
|
|
|
|
|
|
|
def testTextMarginStyleOffset(self):
|
|
|
|
|
self.ed.MarginSetStyleOffset(300)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarginGetStyleOffset(), 300)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
class TestAnnotation(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.txt = b"abcd"
|
|
|
|
|
self.ed.AddText(1, b"x")
|
|
|
|
|
|
|
|
|
|
def testTextAnnotation(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AnnotationGetLines(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AnnotationSetText(0, self.txt)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AnnotationGetLines(), 1)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
result = self.ed.AnnotationGetText(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(len(result), 4)
|
|
|
|
|
self.assertEqual(result, self.txt)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AnnotationClearAll()
|
|
|
|
|
|
|
|
|
|
def testTextAnnotationStyle(self):
|
|
|
|
|
self.ed.AnnotationSetText(0, self.txt)
|
|
|
|
|
self.ed.AnnotationSetStyle(0, 33)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AnnotationGetStyle(0), 33)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AnnotationClearAll()
|
|
|
|
|
|
|
|
|
|
def testTextAnnotationStyles(self):
|
|
|
|
|
styles = b"\001\002\003\004"
|
|
|
|
|
self.ed.AnnotationSetText(0, self.txt)
|
|
|
|
|
self.ed.AnnotationSetStyles(0, styles)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
result = self.ed.AnnotationGetStyles(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(result, styles)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AnnotationClearAll()
|
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testExtendedStyles(self):
|
|
|
|
|
start0 = self.ed.AllocateExtendedStyles(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(start0, 256)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
start1 = self.ed.AllocateExtendedStyles(10)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(start1, 256)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
start2 = self.ed.AllocateExtendedStyles(20)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(start2, start1 + 10)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# Reset by changing lexer
|
|
|
|
|
self.ed.ReleaseAllExtendedStyles()
|
|
|
|
|
start0 = self.ed.AllocateExtendedStyles(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(start0, 256)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testTextAnnotationStyleOffset(self):
|
|
|
|
|
self.ed.AnnotationSetStyleOffset(300)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AnnotationGetStyleOffset(), 300)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testTextAnnotationVisible(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AnnotationGetVisible(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AnnotationSetVisible(2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AnnotationGetVisible(), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AnnotationSetVisible(0)
|
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
def selectionPositionRepresentation(selectionPosition):
|
|
|
|
|
position, virtualSpace = selectionPosition
|
|
|
|
|
representation = str(position)
|
|
|
|
|
if virtualSpace > 0:
|
|
|
|
|
representation += "+" + str(virtualSpace) + "v"
|
|
|
|
|
return representation
|
|
|
|
|
|
|
|
|
|
def selectionRangeRepresentation(selectionRange):
|
|
|
|
|
anchor, caret = selectionRange
|
|
|
|
|
return selectionPositionRepresentation(anchor) + "-" + selectionPositionRepresentation(caret)
|
|
|
|
|
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
def selectionRepresentation(ed, n):
|
|
|
|
|
anchor = (ed.GetSelectionNAnchor(n), ed.GetSelectionNAnchorVirtualSpace(n))
|
|
|
|
|
caret = (ed.GetSelectionNCaret(n), ed.GetSelectionNCaretVirtualSpace(n))
|
|
|
|
|
return selectionRangeRepresentation((anchor, caret))
|
|
|
|
|
|
|
|
|
|
def allSelectionsRepresentation(ed):
|
|
|
|
|
reps = [selectionRepresentation(ed, i) for i in range(ed.Selections)]
|
|
|
|
|
return ';'.join(reps)
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestMultiSelection(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
# 3 lines of 3 characters
|
|
|
|
|
t = b"xxx\nxxx\nxxx"
|
|
|
|
|
self.ed.AddText(len(t), t)
|
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
def textOfSelection(self, n):
|
|
|
|
|
self.ed.TargetStart = self.ed.GetSelectionNStart(n)
|
|
|
|
|
self.ed.TargetEnd = self.ed.GetSelectionNEnd(n)
|
|
|
|
|
return bytes(self.ed.GetTargetText())
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
def testSelectionCleared(self):
|
|
|
|
|
self.ed.ClearSelections()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def test1Selection(self):
|
|
|
|
|
self.ed.SetSelection(1, 2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNStart(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNEnd(0), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SwapMainAnchorCaret()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def test1SelectionReversed(self):
|
|
|
|
|
self.ed.SetSelection(2, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNStart(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNEnd(0), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def test1SelectionByStartEnd(self):
|
|
|
|
|
self.ed.SetSelectionNStart(0, 2)
|
|
|
|
|
self.ed.SetSelectionNEnd(0, 3)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNStart(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNEnd(0), 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def test2Selections(self):
|
|
|
|
|
self.ed.SetSelection(1, 2)
|
|
|
|
|
self.ed.AddSelection(4, 5)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(1), 4)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(1), 5)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNStart(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNEnd(0), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.MainSelection = 0
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RotateSelection()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MainSelection, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testRectangularSelection(self):
|
|
|
|
|
self.ed.RectangularSelectionAnchor = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionAnchor, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RectangularSelectionCaret = 10
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionCaret, 10)
|
|
|
|
|
self.assertEqual(self.ed.Selections, 3)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(1), 5)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(1), 6)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(2), 9)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(2), 10)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testVirtualSpace(self):
|
|
|
|
|
self.ed.SetSelection(3, 7)
|
|
|
|
|
self.ed.SetSelectionNCaretVirtualSpace(0, 3)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaretVirtualSpace(0), 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSelectionNAnchorVirtualSpace(0, 2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchorVirtualSpace(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNStartVirtualSpace(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNEndVirtualSpace(0), 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Does not check that virtual space is valid by being at end of line
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
|
|
|
|
self.ed.SetSelectionNCaretVirtualSpace(0, 3)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaretVirtualSpace(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNStartVirtualSpace(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNEndVirtualSpace(0), 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testRectangularVirtualSpace(self):
|
|
|
|
|
self.ed.VirtualSpaceOptions=1
|
|
|
|
|
self.ed.RectangularSelectionAnchor = 3
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionAnchor, 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RectangularSelectionCaret = 7
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionCaret, 7)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RectangularSelectionAnchorVirtualSpace = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionAnchorVirtualSpace, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RectangularSelectionCaretVirtualSpace = 10
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionCaretVirtualSpace, 10)
|
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchorVirtualSpace(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaretVirtualSpace(0), 10)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testRectangularVirtualSpaceOptionOff(self):
|
|
|
|
|
# Same as previous test but virtual space option off so no virtual space in result
|
|
|
|
|
self.ed.VirtualSpaceOptions=0
|
|
|
|
|
self.ed.RectangularSelectionAnchor = 3
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionAnchor, 3)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RectangularSelectionCaret = 7
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionCaret, 7)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RectangularSelectionAnchorVirtualSpace = 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionAnchorVirtualSpace, 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.RectangularSelectionCaretVirtualSpace = 10
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.RectangularSelectionCaretVirtualSpace, 10)
|
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchorVirtualSpace(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 3)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaretVirtualSpace(0), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
def testDropSelectionN(self):
|
|
|
|
|
self.ed.SetSelection(1, 2)
|
|
|
|
|
# Only one so dropping has no effect
|
|
|
|
|
self.ed.DropSelectionN(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.AddSelection(4, 5)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# Outside bounds so no effect
|
|
|
|
|
self.ed.DropSelectionN(2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# Dropping before main so main decreases
|
|
|
|
|
self.ed.DropSelectionN(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 4)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 5)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
self.ed.AddSelection(10, 11)
|
|
|
|
|
self.ed.AddSelection(20, 21)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 3)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 2)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.MainSelection = 1
|
|
|
|
|
# Dropping after main so main does not change
|
|
|
|
|
self.ed.DropSelectionN(2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MainSelection, 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
# Dropping first selection so wraps around to new last.
|
|
|
|
|
self.ed.AddSelection(30, 31)
|
|
|
|
|
self.ed.AddSelection(40, 41)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 4)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.MainSelection = 0
|
|
|
|
|
self.ed.DropSelectionN(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MainSelection, 2)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
def partFromSelection(self, n):
|
|
|
|
|
# Return a tuple (order, text) from a selection part
|
|
|
|
|
# order is a boolean whether the caret is before the anchor
|
|
|
|
|
self.ed.TargetStart = self.ed.GetSelectionNStart(n)
|
|
|
|
|
self.ed.TargetEnd = self.ed.GetSelectionNEnd(n)
|
|
|
|
|
return (self.ed.GetSelectionNCaret(n) < self.ed.GetSelectionNAnchor(n), self.textOfSelection(n))
|
|
|
|
|
|
|
|
|
|
def replacePart(self, n, part):
|
|
|
|
|
startSelection = self.ed.GetSelectionNStart(n)
|
|
|
|
|
self.ed.TargetStart = startSelection
|
|
|
|
|
self.ed.TargetEnd = self.ed.GetSelectionNEnd(n)
|
|
|
|
|
direction, text = part
|
|
|
|
|
length = len(text)
|
|
|
|
|
self.ed.ReplaceTarget(len(text), text)
|
|
|
|
|
if direction:
|
|
|
|
|
self.ed.SetSelectionNCaret(n, startSelection)
|
|
|
|
|
self.ed.SetSelectionNAnchor(n, startSelection + length)
|
|
|
|
|
else:
|
|
|
|
|
self.ed.SetSelectionNAnchor(n, startSelection)
|
|
|
|
|
self.ed.SetSelectionNCaret(n, startSelection + length)
|
|
|
|
|
|
|
|
|
|
def swapSelections(self):
|
|
|
|
|
# Swap the selections
|
|
|
|
|
part0 = self.partFromSelection(0)
|
|
|
|
|
part1 = self.partFromSelection(1)
|
|
|
|
|
|
|
|
|
|
self.replacePart(1, part0)
|
|
|
|
|
self.replacePart(0, part1)
|
|
|
|
|
|
|
|
|
|
def checkAdjacentSelections(self, selections, invert):
|
|
|
|
|
# Only called from testAdjacentSelections to try one permutation
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
t = b"ab"
|
|
|
|
|
texts = (b'b', b'a') if invert else (b'a', b'b')
|
|
|
|
|
self.ed.AddText(len(t), t)
|
|
|
|
|
sel0, sel1 = selections
|
|
|
|
|
self.ed.SetSelection(sel0[0], sel0[1])
|
|
|
|
|
self.ed.AddSelection(sel1[0], sel1[1])
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.textOfSelection(0), texts[0])
|
|
|
|
|
self.assertEqual(self.textOfSelection(1), texts[1])
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.swapSelections()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b'ba')
|
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.textOfSelection(0), texts[1])
|
|
|
|
|
self.assertEqual(self.textOfSelection(1), texts[0])
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
def testAdjacentSelections(self):
|
|
|
|
|
# For various permutations of selections, try swapping the text and ensure that the
|
|
|
|
|
# selections remain distinct
|
|
|
|
|
self.checkAdjacentSelections(((1, 0),(1, 2)), False)
|
|
|
|
|
self.checkAdjacentSelections(((0, 1),(1, 2)), False)
|
|
|
|
|
self.checkAdjacentSelections(((1, 0),(2, 1)), False)
|
|
|
|
|
self.checkAdjacentSelections(((0, 1),(2, 1)), False)
|
|
|
|
|
|
|
|
|
|
# Reverse order, first selection is after second
|
|
|
|
|
self.checkAdjacentSelections(((1, 2),(1, 0)), True)
|
|
|
|
|
self.checkAdjacentSelections(((1, 2),(0, 1)), True)
|
|
|
|
|
self.checkAdjacentSelections(((2, 1),(1, 0)), True)
|
|
|
|
|
self.checkAdjacentSelections(((2, 1),(0, 1)), True)
|
|
|
|
|
|
|
|
|
|
def testInsertBefore(self):
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
t = b"a"
|
|
|
|
|
self.ed.AddText(len(t), t)
|
|
|
|
|
self.ed.SetSelection(0, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.textOfSelection(0), b'a')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
self.ed.SetTargetRange(0, 0)
|
|
|
|
|
self.ed.ReplaceTarget(1, b'1')
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b'1a')
|
|
|
|
|
self.assertEqual(self.textOfSelection(0), b'a')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
def testInsertAfter(self):
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
t = b"a"
|
|
|
|
|
self.ed.AddText(len(t), t)
|
|
|
|
|
self.ed.SetSelection(0, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.textOfSelection(0), b'a')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
self.ed.SetTargetRange(1, 1)
|
|
|
|
|
self.ed.ReplaceTarget(1, b'9')
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b'a9')
|
|
|
|
|
self.assertEqual(self.textOfSelection(0), b'a')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
def testInsertBeforeVirtualSpace(self):
|
|
|
|
|
self.ed.SetContents(b"a")
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
|
|
|
|
self.ed.SetSelectionNAnchorVirtualSpace(0, 2)
|
|
|
|
|
self.ed.SetSelectionNCaretVirtualSpace(0, 2)
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(selectionRepresentation(self.ed, 0), "1+2v-1+2v")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.textOfSelection(0), b'')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
# Append '1'
|
|
|
|
|
self.ed.SetTargetRange(1, 1)
|
|
|
|
|
self.ed.ReplaceTarget(1, b'1')
|
|
|
|
|
# Selection moved on 1, but still empty
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(selectionRepresentation(self.ed, 0), "2+1v-2+1v")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b'a1')
|
|
|
|
|
self.assertEqual(self.textOfSelection(0), b'')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
def testInsertThroughVirtualSpace(self):
|
|
|
|
|
self.ed.SetContents(b"a")
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
|
|
|
|
self.ed.SetSelectionNAnchorVirtualSpace(0, 2)
|
|
|
|
|
self.ed.SetSelectionNCaretVirtualSpace(0, 3)
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(selectionRepresentation(self.ed, 0), "1+2v-1+3v")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.textOfSelection(0), b'')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
# Append '1' past current virtual space
|
|
|
|
|
self.ed.SetTargetRange(1, 1)
|
|
|
|
|
self.ed.SetTargetStartVirtualSpace(4)
|
|
|
|
|
self.ed.SetTargetEndVirtualSpace(5)
|
|
|
|
|
self.ed.ReplaceTarget(1, b'1')
|
|
|
|
|
# Virtual space of selection all converted to real positions
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(selectionRepresentation(self.ed, 0), "3-4")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b'a 1')
|
|
|
|
|
self.assertEqual(self.textOfSelection(0), b' ')
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
|
2019-05-04 20:14:48 +02:00
|
|
|
|
class TestModalSelection(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
# 3 lines of 3 characters
|
|
|
|
|
t = b"xxx\nxxx\nxxx"
|
|
|
|
|
self.ed.AddText(len(t), t)
|
|
|
|
|
|
|
|
|
|
def testCharacterSelection(self):
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.SelectionMode = self.ed.SC_SEL_STREAM
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetSelectionMode(), self.ed.SC_SEL_STREAM)
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(self.ed.MoveExtendsSelection, True)
|
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.CharRight()
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "1-2")
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.LineDown()
|
Updated to Scintilla 5.4.1 & Lexilla 5.3.0
Scintilla 5.4.1
https://www.scintilla.org/scintilla541.zip
Released 27 December 2023.
1. Add IDocumentEditable interface to allow efficient interaction with document objects which may not be visible in a Scintilla instance. This feature is provisonal and may change before being declared stable. For better type-safety, the ScintillaCall C++ API uses IDocumentEditable* where void* was used before which may require changes to client code that uses document pointer APIs DocPointer, SetDocPointer, CreateDocument, AddRefDocument, and ReleaseDocument.
2. Ctrl-click on a selection deselects it in multiple selection mode.
3. Add SCI_SELECTIONFROMPOINT for modifying multiple selections.
4. Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to simplify selection mode manipulation.
5. Improve performance of global replace by reducing cache invalidation overhead. [Feature #1502](https://sourceforge.net/p/scintilla/feature-requests/1502/).
6. Fix regular expression search for "\<" matching beginning of search when not beginning of word and for "\>" not matching line end. [Bug #2157](https://sourceforge.net/p/scintilla/bugs/2157/).
7. Fix regular expression search failure when search for "\<" followed by search for "\>". [Bug #2413](https://sourceforge.net/p/scintilla/bugs/2413/).
8. Fix regular expression assertion (^, $, \b. \B) failures when using SCFIND_CXX11REGEX. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
9. Fix regular expression bug in reverse direction where shortened match returned. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
10. Avoid character fragments in regular expression search results. [Bug #2405](https://sourceforge.net/p/scintilla/bugs/2405/).
11. With a document that does not have the SC_DOCUMENTOPTION_TEXT_LARGE option set, allocating more than 2G (calling SCI_ALLOCATE or similar) will now fail with SC_STATUS_FAILURE.
12. Protect SCI_REPLACETARGET, SCI_REPLACETARGETMINIMAL, and SCI_REPLACETARGETRE from application changing target in notification handlers. [Bug #2289](https://sourceforge.net/p/scintilla/bugs/2289/).
Lexilla 5.3.0
https://www.scintilla.org/lexilla530.zip
Released 27 December 2023.
1. Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. [Bug #2421](https://sourceforge.net/p/scintilla/bugs/2421/).
2. Bash: Fix shift operator << incorrectly recognized as here-doc. [Issue #215](https://github.com/ScintillaOrg/lexilla/issues/215).
3. Bash: Fix termination of '${' with first unquoted '}' instead of nesting. [Issue #216](https://github.com/ScintillaOrg/lexilla/issues/216).
4. HTML: JavaScript double-quoted strings may escape line end with '\'. [Issue #214](https://github.com/ScintillaOrg/lexilla/issues/214).
5. Lua: recognize --- doc comments. Defined by [LDoc](https://github.com/lunarmodules/ldoc). Does not recognize --[[-- doc comments which seem less common.
Close #14375
2023-11-19 18:46:55 +01:00
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "1-6")
|
|
|
|
|
self.ed.ClearSelections()
|
|
|
|
|
|
|
|
|
|
def testChangeSelectionMode(self):
|
|
|
|
|
# Like testCharacterSelection but calling ChangeSelectionMode instead of SetSelectionMode
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
|
|
|
|
|
self.ed.ChangeSelectionMode(self.ed.SC_SEL_STREAM)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionMode(), self.ed.SC_SEL_STREAM)
|
|
|
|
|
self.assertEqual(self.ed.MoveExtendsSelection, False)
|
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
|
|
|
|
|
self.ed.CharRight()
|
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "2-2")
|
|
|
|
|
self.ed.LineDown()
|
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "6-6")
|
|
|
|
|
self.ed.ClearSelections()
|
|
|
|
|
|
|
|
|
|
def testTurningOffMoveExtendsSelection(self):
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
|
|
|
|
self.ed.SelectionMode = self.ed.SC_SEL_STREAM
|
|
|
|
|
self.ed.CharRight()
|
|
|
|
|
self.ed.LineDown()
|
|
|
|
|
self.assertEqual(self.ed.MoveExtendsSelection, True)
|
|
|
|
|
self.ed.MoveExtendsSelection = False
|
|
|
|
|
self.assertEqual(self.ed.MoveExtendsSelection, False)
|
|
|
|
|
self.ed.CharRight()
|
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "6-6")
|
|
|
|
|
self.ed.CharRight()
|
|
|
|
|
self.assertEqual(allSelectionsRepresentation(self.ed), "7-7")
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ClearSelections()
|
|
|
|
|
|
|
|
|
|
def testRectangleSelection(self):
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.SelectionMode = self.ed.SC_SEL_RECTANGLE
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetSelectionMode(), self.ed.SC_SEL_RECTANGLE)
|
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.CharRight()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.LineDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 2)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 2)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(1), 6)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(1), 5)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ClearSelections()
|
|
|
|
|
|
|
|
|
|
def testLinesSelection(self):
|
|
|
|
|
self.ed.SetSelection(1, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.SelectionMode = self.ed.SC_SEL_LINES
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetSelectionMode(), self.ed.SC_SEL_LINES)
|
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 3)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.CharRight()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 3)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.LineDown()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Selections, 1)
|
|
|
|
|
self.assertEqual(self.ed.MainSelection, 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNCaret(0), 7)
|
|
|
|
|
self.assertEqual(self.ed.GetSelectionNAnchor(0), 0)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ClearSelections()
|
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
class TestTechnology(unittest.TestCase):
|
|
|
|
|
""" These tests are just to ensure that the calls set and retrieve values.
|
|
|
|
|
They assume running on a Direct2D compatible version of Windows.
|
|
|
|
|
They do not check visual appearance.
|
|
|
|
|
"""
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def testTechnologyAndBufferedDraw(self):
|
|
|
|
|
self.ed.Technology = self.ed.SC_TECHNOLOGY_DEFAULT
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetTechnology(), self.ed.SC_TECHNOLOGY_DEFAULT)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
if sys.platform == "win32":
|
|
|
|
|
self.ed.Technology = self.ed.SC_TECHNOLOGY_DIRECTWRITE
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetTechnology(), self.ed.SC_TECHNOLOGY_DIRECTWRITE)
|
|
|
|
|
self.assertEqual(self.ed.BufferedDraw, False)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.Technology = self.ed.SC_TECHNOLOGY_DEFAULT
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetTechnology(), self.ed.SC_TECHNOLOGY_DEFAULT)
|
|
|
|
|
self.assertEqual(self.ed.BufferedDraw, True)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
class TestStyleAttributes(unittest.TestCase):
|
|
|
|
|
""" These tests are just to ensure that the calls set and retrieve values.
|
|
|
|
|
They do not check the visual appearance of the style attributes.
|
|
|
|
|
"""
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.testColour = 0x171615
|
|
|
|
|
self.testFont = b"Georgia"
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.testRepresentation = "\N{BULLET}".encode("utf-8")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.StyleResetDefault()
|
|
|
|
|
|
|
|
|
|
def testFont(self):
|
|
|
|
|
self.ed.StyleSetFont(self.ed.STYLE_DEFAULT, self.testFont)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetFont(self.ed.STYLE_DEFAULT), self.testFont)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testSize(self):
|
|
|
|
|
self.ed.StyleSetSize(self.ed.STYLE_DEFAULT, 12)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetSize(self.ed.STYLE_DEFAULT), 12)
|
|
|
|
|
self.assertEqual(self.ed.StyleGetSizeFractional(self.ed.STYLE_DEFAULT), 12*self.ed.SC_FONT_SIZE_MULTIPLIER)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetSizeFractional(self.ed.STYLE_DEFAULT, 1234)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetSizeFractional(self.ed.STYLE_DEFAULT), 1234)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2022-10-12 20:45:40 +02:00
|
|
|
|
def testInvisibleRepresentation(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetInvisibleRepresentation(self.ed.STYLE_DEFAULT), b"")
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.ed.StyleSetInvisibleRepresentation(self.ed.STYLE_DEFAULT, self.testRepresentation)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetInvisibleRepresentation(self.ed.STYLE_DEFAULT), self.testRepresentation)
|
2022-10-12 20:45:40 +02:00
|
|
|
|
self.ed.StyleSetInvisibleRepresentation(self.ed.STYLE_DEFAULT, b"\000")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetInvisibleRepresentation(self.ed.STYLE_DEFAULT), b"")
|
2022-10-12 20:45:40 +02:00
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
def testBold(self):
|
|
|
|
|
self.ed.StyleSetBold(self.ed.STYLE_DEFAULT, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetBold(self.ed.STYLE_DEFAULT), 1)
|
|
|
|
|
self.assertEqual(self.ed.StyleGetWeight(self.ed.STYLE_DEFAULT), self.ed.SC_WEIGHT_BOLD)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetWeight(self.ed.STYLE_DEFAULT, 530)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetWeight(self.ed.STYLE_DEFAULT), 530)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testItalic(self):
|
|
|
|
|
self.ed.StyleSetItalic(self.ed.STYLE_DEFAULT, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetItalic(self.ed.STYLE_DEFAULT), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testUnderline(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetUnderline(self.ed.STYLE_DEFAULT), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetUnderline(self.ed.STYLE_DEFAULT, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetUnderline(self.ed.STYLE_DEFAULT), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testFore(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetFore(self.ed.STYLE_DEFAULT), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetFore(self.ed.STYLE_DEFAULT, self.testColour)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetFore(self.ed.STYLE_DEFAULT), self.testColour)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testBack(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetBack(self.ed.STYLE_DEFAULT), 0xffffff)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetBack(self.ed.STYLE_DEFAULT, self.testColour)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetBack(self.ed.STYLE_DEFAULT), self.testColour)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testEOLFilled(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetEOLFilled(self.ed.STYLE_DEFAULT), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetEOLFilled(self.ed.STYLE_DEFAULT, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetEOLFilled(self.ed.STYLE_DEFAULT), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testCharacterSet(self):
|
|
|
|
|
self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_RUSSIAN)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetCharacterSet(self.ed.STYLE_DEFAULT), self.ed.SC_CHARSET_RUSSIAN)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testCase(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetCase(self.ed.STYLE_DEFAULT), self.ed.SC_CASE_MIXED)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetCase(self.ed.STYLE_DEFAULT, self.ed.SC_CASE_UPPER)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetCase(self.ed.STYLE_DEFAULT), self.ed.SC_CASE_UPPER)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetCase(self.ed.STYLE_DEFAULT, self.ed.SC_CASE_LOWER)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetCase(self.ed.STYLE_DEFAULT), self.ed.SC_CASE_LOWER)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testVisible(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetVisible(self.ed.STYLE_DEFAULT), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetVisible(self.ed.STYLE_DEFAULT, 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetVisible(self.ed.STYLE_DEFAULT), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testChangeable(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetChangeable(self.ed.STYLE_DEFAULT), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetChangeable(self.ed.STYLE_DEFAULT, 0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetChangeable(self.ed.STYLE_DEFAULT), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testHotSpot(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetHotSpot(self.ed.STYLE_DEFAULT), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.StyleSetHotSpot(self.ed.STYLE_DEFAULT, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetHotSpot(self.ed.STYLE_DEFAULT), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2019-07-21 15:26:02 +02:00
|
|
|
|
def testFoldDisplayTextStyle(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FoldDisplayTextGetStyle(), 0)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
self.ed.FoldDisplayTextSetStyle(self.ed.SC_FOLDDISPLAYTEXT_BOXED)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.FoldDisplayTextGetStyle(), self.ed.SC_FOLDDISPLAYTEXT_BOXED)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
|
|
|
|
|
def testDefaultFoldDisplayText(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetDefaultFoldDisplayText(), b"")
|
2019-07-21 15:26:02 +02:00
|
|
|
|
self.ed.SetDefaultFoldDisplayText(0, b"...")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetDefaultFoldDisplayText(), b"...")
|
2019-07-21 15:26:02 +02:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
def testFontQuality(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetFontQuality(), self.ed.SC_EFF_QUALITY_DEFAULT)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.SetFontQuality(self.ed.SC_EFF_QUALITY_LCD_OPTIMIZED)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetFontQuality(), self.ed.SC_EFF_QUALITY_LCD_OPTIMIZED)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testFontLocale(self):
|
|
|
|
|
initialLocale = "en-us".encode("UTF-8")
|
|
|
|
|
testLocale = "zh-Hans".encode("UTF-8")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetFontLocale(), initialLocale)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.FontLocale = testLocale
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetFontLocale(), testLocale)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testCheckMonospaced(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetCheckMonospaced(self.ed.STYLE_DEFAULT), 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.StyleSetCheckMonospaced(self.ed.STYLE_DEFAULT, 1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.StyleGetCheckMonospaced(self.ed.STYLE_DEFAULT), 1)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
class TestElements(unittest.TestCase):
|
|
|
|
|
""" These tests are just to ensure that the calls set and retrieve values.
|
|
|
|
|
They do not check the visual appearance of the style attributes.
|
|
|
|
|
"""
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.testColourAlpha = 0x18171615
|
|
|
|
|
self.opaque = 0xff000000
|
|
|
|
|
self.dropAlpha = 0x00ffffff
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def ElementColour(self, element):
|
|
|
|
|
# & 0xffffffff prevents sign extension issues
|
|
|
|
|
return self.ed.GetElementColour(element) & 0xffffffff
|
|
|
|
|
|
|
|
|
|
def RestoreCaretLine(self):
|
|
|
|
|
self.ed.CaretLineLayer = 0
|
|
|
|
|
self.ed.CaretLineFrame = 0
|
|
|
|
|
self.ed.ResetElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK)
|
|
|
|
|
self.ed.CaretLineVisibleAlways = False
|
|
|
|
|
|
|
|
|
|
def testIsSet(self):
|
|
|
|
|
self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_SELECTION_TEXT))
|
|
|
|
|
|
|
|
|
|
def testAllowsTranslucent(self):
|
|
|
|
|
self.assertFalse(self.ed.GetElementAllowsTranslucent(self.ed.SC_ELEMENT_LIST))
|
|
|
|
|
self.assertTrue(self.ed.GetElementAllowsTranslucent(self.ed.SC_ELEMENT_SELECTION_TEXT))
|
|
|
|
|
|
|
|
|
|
def testChanging(self):
|
|
|
|
|
self.ed.SetElementColour(self.ed.SC_ELEMENT_LIST_BACK, self.testColourAlpha)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_LIST_BACK), self.testColourAlpha)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_LIST_BACK))
|
|
|
|
|
|
|
|
|
|
def testSubline(self):
|
|
|
|
|
# Default is false
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineHighlightSubLine, False)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.CaretLineHighlightSubLine = True
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineHighlightSubLine, True)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.CaretLineHighlightSubLine = False
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineHighlightSubLine, False)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testReset(self):
|
|
|
|
|
self.ed.SetElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT, self.testColourAlpha)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT), self.testColourAlpha)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.ResetElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT), 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT))
|
|
|
|
|
|
|
|
|
|
def testBaseColour(self):
|
|
|
|
|
if sys.platform == "win32":
|
|
|
|
|
# SC_ELEMENT_LIST* base colours only currently implemented on Win32
|
|
|
|
|
text = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST)
|
|
|
|
|
back = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST_BACK)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(text & self.opaque, self.opaque)
|
|
|
|
|
self.assertEqual(back & self.opaque, self.opaque)
|
|
|
|
|
self.assertNotEqual(text & self.dropAlpha, back & self.dropAlpha)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
selText = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST_SELECTED)
|
|
|
|
|
selBack = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST_SELECTED_BACK)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(selText & self.opaque, self.opaque)
|
|
|
|
|
self.assertEqual(selBack & self.opaque, self.opaque)
|
|
|
|
|
self.assertNotEqual(selText & self.dropAlpha, selBack & self.dropAlpha)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testSelectionLayer(self):
|
|
|
|
|
self.ed.SelectionLayer = self.ed.SC_LAYER_OVER_TEXT
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionLayer, self.ed.SC_LAYER_OVER_TEXT)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.SelectionLayer = self.ed.SC_LAYER_BASE
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionLayer, self.ed.SC_LAYER_BASE)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testCaretLine(self):
|
|
|
|
|
# Newer Layer / ElementColour API
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineLayer, 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineFrame, 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.assertFalse(self.ed.CaretLineVisibleAlways)
|
|
|
|
|
|
|
|
|
|
self.ed.CaretLineLayer = 2
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineLayer, 2)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.CaretLineFrame = 2
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineFrame, 2)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.CaretLineVisibleAlways = True
|
|
|
|
|
self.assertTrue(self.ed.CaretLineVisibleAlways)
|
|
|
|
|
self.ed.SetElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK, self.testColourAlpha)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK), self.testColourAlpha)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.RestoreCaretLine()
|
|
|
|
|
|
|
|
|
|
def testCaretLineLayerDiscouraged(self):
|
|
|
|
|
# Check old discouraged APIs
|
|
|
|
|
# This is s bit tricky as there is no clean mapping: parts of the old state are distributed to
|
|
|
|
|
# sometimes-multiple parts of the new state.
|
|
|
|
|
backColour = 0x102030
|
|
|
|
|
backColourOpaque = backColour | self.opaque
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineVisible, 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.CaretLineVisible = 1
|
|
|
|
|
self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineVisible, 1)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.CaretLineBack = backColour
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineBack, backColour)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
# Check with newer API
|
|
|
|
|
self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK), backColourOpaque)
|
|
|
|
|
self.assertEqual(self.ed.CaretLineLayer, 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
alpha = 0x7f
|
|
|
|
|
self.ed.CaretLineBackAlpha = alpha
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineBackAlpha, alpha)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
backColourTranslucent = backColour | (alpha << 24)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK), backColourTranslucent)
|
|
|
|
|
self.assertEqual(self.ed.CaretLineLayer, 2)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.CaretLineBackAlpha = 0x100
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineBackAlpha, 0x100)
|
|
|
|
|
self.assertEqual(self.ed.CaretLineLayer, 0) # SC_ALPHA_NOALPHA moved to base layer
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.RestoreCaretLine()
|
|
|
|
|
|
|
|
|
|
# Try other orders
|
|
|
|
|
|
|
|
|
|
self.ed.CaretLineBackAlpha = 0x100
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CaretLineBackAlpha, 0x100)
|
|
|
|
|
self.assertEqual(self.ed.CaretLineLayer, 0) # SC_ALPHA_NOALPHA moved to base layer
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.CaretLineBack = backColour
|
|
|
|
|
self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
|
|
|
|
|
self.ed.CaretLineVisible = 0
|
|
|
|
|
self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
|
|
|
|
|
|
|
|
|
|
self.RestoreCaretLine()
|
|
|
|
|
|
|
|
|
|
def testMarkerLayer(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGetLayer(1), 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.MarkerSetAlpha(1, 23)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGetLayer(1), 2)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.MarkerSetAlpha(1, 0x100)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.MarkerGetLayer(1), 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
def testHotSpot(self):
|
|
|
|
|
self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE))
|
|
|
|
|
self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE_BACK))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.HotspotActiveFore, 0)
|
|
|
|
|
self.assertEqual(self.ed.HotspotActiveBack, 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
testColour = 0x804020
|
|
|
|
|
resetColour = 0x112233 # Doesn't get set
|
|
|
|
|
self.ed.SetHotspotActiveFore(1, testColour)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.HotspotActiveFore, testColour)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE), testColour | self.opaque)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.ed.SetHotspotActiveFore(0, resetColour)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.HotspotActiveFore, 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE), 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
translucentColour = 0x50403020
|
|
|
|
|
self.ed.SetElementColour(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE, translucentColour)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE), translucentColour)
|
|
|
|
|
self.assertEqual(self.ed.HotspotActiveFore, translucentColour & self.dropAlpha)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
backColour = 0x204080
|
|
|
|
|
self.ed.SetHotspotActiveBack(1, backColour)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.HotspotActiveBack, backColour)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE_BACK))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ElementColour(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE_BACK), backColour | self.opaque)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
# Restore
|
|
|
|
|
self.ed.ResetElementColour(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE)
|
|
|
|
|
self.ed.ResetElementColour(self.ed.SC_ELEMENT_HOT_SPOT_ACTIVE_BACK)
|
|
|
|
|
|
2022-08-27 09:35:52 +02:00
|
|
|
|
def testHideSelection(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionHidden, False)
|
2022-08-27 09:35:52 +02:00
|
|
|
|
self.ed.HideSelection(True)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionHidden, True)
|
2022-08-27 09:35:52 +02:00
|
|
|
|
self.ed.HideSelection(False) # Restore
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.SelectionHidden, False)
|
Update: Scintilla 5.3.6 and Lexilla 5.2.6
update to Scinitlla Release 5.3.6 (https://www.scintilla.org/scintilla536.zip)
Released 26 July 2023.
Redraw calltip after showing as didn't update when size of new text exactly same as previous. Feature #1486.
On Win32 fix reverse arrow cursor when scaled. Bug #2382.
On Win32 hide cursor when typing if that system preference has been chosen. Bug #2333.
On Win32 and Qt, stop aligning IME candidate window to target. It is now always aligned to start of composition string. This undoes part of feature #1300. Feature #1488, Bug #2391, Feature #1300.
On Qt, for IMEs, update micro focus when selection changes. This may move the location of IME popups to align with the caret.
On Qt, implement replacement for IMEs which may help with actions like reconversion. This is similar to delete-surrounding on GTK.
and Lexilla Release 5.2.6 (https://www.scintilla.org/lexilla526.zip)
Released 26 July 2023.
Include empty word list names in value returned by DescribeWordListSets and SCI_DESCRIBEKEYWORDSETS. Issue #175, Pull request #176.
Bash: style here-doc end delimiters as SCE_SH_HERE_DELIM instead of SCE_SH_HERE_Q. Issue #177.
Bash: allow '$' as last character in string. Issue #180, Pull request #181.
Bash: fix state after expansion. Highlight all numeric and file test operators. Don't highlight dash in long option as operator. Issue #182, Pull request #183.
Bash: strict checking of special parameters ($*, $@, $$, ...) with property lexer.bash.special.parameter to specify valid parameters. Issue #184, Pull request #186.
Bash: recognize keyword before redirection operators (< and >). Issue #188, Pull request #189.
Errorlist: recognize Bash diagnostic messages.
HTML: allow ASP block to terminate inside line comment. Issue #185.
HTML: fix folding with JSP/ASP.NET <%-- comment. Issue #191.
HTML: fix incremental styling of multi-line ASP.NET directive. Issue #191.
Matlab: improve arguments blocks. Add support for multiple arguments blocks. Prevent "arguments" from being keyword in function declaration line. Fix semicolon handling. Pull request #179.
Visual Prolog: add support for embedded syntax with SCE_VISUALPROLOG_EMBEDDED and SCE_VISUALPROLOG_PLACEHOLDER.
Styling of string literals changed with no differentiation between literals with quotes and those that are prefixed with "@". Quote characters are in a separate style (SCE_VISUALPROLOG_STRING_QUOTE) to contents (SCE_VISUALPROLOG_STRING).
SCE_VISUALPROLOG_CHARACTER, SCE_VISUALPROLOG_CHARACTER_TOO_MANY, SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR, SCE_VISUALPROLOG_STRING_EOL_OPEN, and SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL were removed (replaced with SCE_VISUALPROLOG_UNUSED[1-5]). Pull request #178.
Fix #13901, fix #13911, fix #13943, close #13940
2023-07-27 19:57:12 +02:00
|
|
|
|
|
2019-05-04 20:14:48 +02:00
|
|
|
|
class TestIndices(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
# Text includes one non-BMP character
|
|
|
|
|
t = "aå\U00010348flﬔ-\n"
|
|
|
|
|
self.tv = t.encode("UTF-8")
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.SetCodePage(0)
|
|
|
|
|
|
|
|
|
|
def testAllocation(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.AllocateLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_UTF32)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ReleaseLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
|
|
|
|
def testUTF32(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.SetContents(self.tv)
|
|
|
|
|
self.ed.AllocateLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF32), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(1, self.ed.SC_LINECHARACTERINDEX_UTF32), 7)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ReleaseLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
|
|
|
|
def testUTF16(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.SetContents(self.tv)
|
|
|
|
|
self.ed.AllocateLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF16)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF16), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(1, self.ed.SC_LINECHARACTERINDEX_UTF16), 8)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ReleaseLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF16)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
|
|
|
|
def testBoth(self):
|
|
|
|
|
# Set text before turning indices on
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.SetContents(self.tv)
|
|
|
|
|
self.ed.AllocateLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32+self.ed.SC_LINECHARACTERINDEX_UTF16)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF32), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(1, self.ed.SC_LINECHARACTERINDEX_UTF32), 7)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF16), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(1, self.ed.SC_LINECHARACTERINDEX_UTF16), 8)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
# Test the inverse: position->line
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.LineFromIndexPosition(0, self.ed.SC_LINECHARACTERINDEX_UTF32), 0)
|
|
|
|
|
self.assertEqual(self.ed.LineFromIndexPosition(7, self.ed.SC_LINECHARACTERINDEX_UTF32), 1)
|
|
|
|
|
self.assertEqual(self.ed.LineFromIndexPosition(0, self.ed.SC_LINECHARACTERINDEX_UTF16), 0)
|
|
|
|
|
self.assertEqual(self.ed.LineFromIndexPosition(8, self.ed.SC_LINECHARACTERINDEX_UTF16), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ReleaseLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32+self.ed.SC_LINECHARACTERINDEX_UTF16)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
|
|
|
|
def testMaintenance(self):
|
|
|
|
|
# Set text after turning indices on
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.AllocateLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32+self.ed.SC_LINECHARACTERINDEX_UTF16)
|
|
|
|
|
self.ed.SetContents(self.tv)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF32), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(1, self.ed.SC_LINECHARACTERINDEX_UTF32), 7)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF16), 0)
|
|
|
|
|
self.assertEqual(self.ed.IndexPositionFromLine(1, self.ed.SC_LINECHARACTERINDEX_UTF16), 8)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
self.ed.ReleaseLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF32+self.ed.SC_LINECHARACTERINDEX_UTF16)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
class TestCharacterNavigation(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.SetCodePage(0)
|
|
|
|
|
|
|
|
|
|
def testBeforeAfter(self):
|
|
|
|
|
t = "aåflﬔ-"
|
|
|
|
|
tv = t.encode("UTF-8")
|
|
|
|
|
self.ed.SetContents(tv)
|
|
|
|
|
pos = 0
|
|
|
|
|
for i in range(len(t)-1):
|
|
|
|
|
after = self.ed.PositionAfter(pos)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertTrue(after > i)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
back = self.ed.PositionBefore(after)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(pos, back)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
pos = after
|
|
|
|
|
|
|
|
|
|
def testRelative(self):
|
|
|
|
|
# \x61 \xc3\xa5 \xef\xac\x82 \xef\xac\x94 \x2d
|
|
|
|
|
t = "aåflﬔ-"
|
|
|
|
|
tv = t.encode("UTF-8")
|
|
|
|
|
self.ed.SetContents(tv)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.PositionRelative(1, 2), 6)
|
|
|
|
|
self.assertEqual(self.ed.CountCharacters(1, 6), 2)
|
|
|
|
|
self.assertEqual(self.ed.PositionRelative(6, -2), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
pos = 0
|
|
|
|
|
previous = 0
|
|
|
|
|
for i in range(1, len(t)):
|
|
|
|
|
after = self.ed.PositionRelative(pos, i)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertTrue(after > pos)
|
|
|
|
|
self.assertTrue(after > previous)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
previous = after
|
|
|
|
|
pos = len(t)
|
|
|
|
|
previous = pos
|
|
|
|
|
for i in range(1, len(t)-1):
|
|
|
|
|
after = self.ed.PositionRelative(pos, -i)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertTrue(after < pos)
|
|
|
|
|
self.assertTrue(after < previous)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
previous = after
|
|
|
|
|
|
2019-05-04 20:14:48 +02:00
|
|
|
|
def testRelativeNonBOM(self):
|
|
|
|
|
# \x61 \xF0\x90\x8D\x88 \xef\xac\x82 \xef\xac\x94 \x2d
|
|
|
|
|
t = "a\U00010348flﬔ-"
|
|
|
|
|
tv = t.encode("UTF-8")
|
|
|
|
|
self.ed.SetContents(tv)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.PositionRelative(1, 2), 8)
|
|
|
|
|
self.assertEqual(self.ed.CountCharacters(1, 8), 2)
|
|
|
|
|
self.assertEqual(self.ed.CountCodeUnits(1, 8), 3)
|
|
|
|
|
self.assertEqual(self.ed.PositionRelative(8, -2), 1)
|
|
|
|
|
self.assertEqual(self.ed.PositionRelativeCodeUnits(8, -3), 1)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
pos = 0
|
|
|
|
|
previous = 0
|
|
|
|
|
for i in range(1, len(t)):
|
|
|
|
|
after = self.ed.PositionRelative(pos, i)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertTrue(after > pos)
|
|
|
|
|
self.assertTrue(after > previous)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
previous = after
|
|
|
|
|
pos = len(t)
|
|
|
|
|
previous = pos
|
|
|
|
|
for i in range(1, len(t)-1):
|
|
|
|
|
after = self.ed.PositionRelative(pos, -i)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertTrue(after < pos)
|
|
|
|
|
self.assertTrue(after <= previous)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
previous = after
|
|
|
|
|
|
|
|
|
|
def testLineEnd(self):
|
|
|
|
|
t = "a\r\nb\nc"
|
|
|
|
|
tv = t.encode("UTF-8")
|
|
|
|
|
self.ed.SetContents(tv)
|
|
|
|
|
for i in range(0, len(t)):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CountCharacters(0, i), i)
|
2019-05-04 20:14:48 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestCaseMapping(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.SetCodePage(0)
|
|
|
|
|
self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_DEFAULT)
|
|
|
|
|
|
|
|
|
|
def testEmpty(self):
|
|
|
|
|
# Trying to upper case an empty string caused a crash at one stage
|
|
|
|
|
t = b"x"
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(t)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.UpperCase()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"x")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testASCII(self):
|
|
|
|
|
t = b"x"
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(t)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0,1)
|
|
|
|
|
self.ed.UpperCase()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"X")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testLatin1(self):
|
|
|
|
|
t = "å".encode("Latin-1")
|
|
|
|
|
r = "Å".encode("Latin-1")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(t)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0,1)
|
|
|
|
|
self.ed.UpperCase()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), r)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testRussian(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
if sys.platform == "win32":
|
|
|
|
|
self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_RUSSIAN)
|
|
|
|
|
else:
|
|
|
|
|
self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_CYRILLIC)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
t = "Б".encode("Windows-1251")
|
|
|
|
|
r = "б".encode("Windows-1251")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(t)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0,1)
|
|
|
|
|
self.ed.LowerCase()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), r)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testUTF(self):
|
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
t = "å".encode("UTF-8")
|
|
|
|
|
r = "Å".encode("UTF-8")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(t)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0,2)
|
|
|
|
|
self.ed.UpperCase()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), r)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testUTFDifferentLength(self):
|
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
t = "ı".encode("UTF-8")
|
|
|
|
|
r = "I".encode("UTF-8")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(t)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0,2)
|
|
|
|
|
self.ed.UpperCase()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 1)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), r)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testUTFGrows(self):
|
|
|
|
|
# This crashed at one point in debug builds due to looking past end of shorter string
|
|
|
|
|
self.ed.SetCodePage(65001)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# ﬖ is a single character ligature taking 3 bytes in UTF8: EF AC 96
|
2013-08-28 02:44:27 +02:00
|
|
|
|
t = 'ﬖﬖ'.encode("UTF-8")
|
|
|
|
|
self.ed.SetContents(t)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 6)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(0,self.ed.Length)
|
|
|
|
|
self.ed.UpperCase()
|
|
|
|
|
# To convert to upper case the ligature is separated into վ and ն then uppercased to Վ and Ն
|
|
|
|
|
# each of which takes 2 bytes in UTF-8: D5 8E D5 86
|
|
|
|
|
r = 'ՎՆՎՆ'.encode("UTF-8")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 8)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), r)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, self.ed.Length)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
|
|
|
|
def testUTFShrinks(self):
|
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
# fi is a single character ligature taking 3 bytes in UTF8: EF AC 81
|
|
|
|
|
t = 'fifi'.encode("UTF-8")
|
|
|
|
|
self.ed.SetContents(t)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 6)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetSel(0,self.ed.Length)
|
|
|
|
|
self.ed.UpperCase()
|
|
|
|
|
# To convert to upper case the ligature is separated into f and i then uppercased to F and I
|
|
|
|
|
# each of which takes 1 byte in UTF-8: 46 49
|
|
|
|
|
r = 'FIFI'.encode("UTF-8")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Length, 4)
|
|
|
|
|
self.assertEqual(self.ed.Contents(), r)
|
|
|
|
|
self.assertEqual(self.ed.SelectionEnd, self.ed.Length)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestCaseInsensitiveSearch(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.SetCodePage(0)
|
|
|
|
|
self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_DEFAULT)
|
|
|
|
|
|
|
|
|
|
def testEmpty(self):
|
|
|
|
|
text = b" x X"
|
|
|
|
|
searchString = b""
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 0
|
|
|
|
|
self.ed.TargetEnd = self.ed.Length-1
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
pos = self.ed.SearchInTarget(len(searchString), searchString)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(0, pos)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testASCII(self):
|
|
|
|
|
text = b" x X"
|
|
|
|
|
searchString = b"X"
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 0
|
|
|
|
|
self.ed.TargetEnd = self.ed.Length-1
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
pos = self.ed.SearchInTarget(len(searchString), searchString)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(1, pos)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testLatin1(self):
|
|
|
|
|
text = "Frånd Åå".encode("Latin-1")
|
|
|
|
|
searchString = "Å".encode("Latin-1")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 0
|
|
|
|
|
self.ed.TargetEnd = self.ed.Length-1
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
pos = self.ed.SearchInTarget(len(searchString), searchString)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(2, pos)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testRussian(self):
|
|
|
|
|
self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_RUSSIAN)
|
|
|
|
|
text = "=(Б tex б)".encode("Windows-1251")
|
|
|
|
|
searchString = "б".encode("Windows-1251")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 0
|
|
|
|
|
self.ed.TargetEnd = self.ed.Length-1
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
pos = self.ed.SearchInTarget(len(searchString), searchString)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(2, pos)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testUTF(self):
|
|
|
|
|
self.ed.SetCodePage(65001)
|
|
|
|
|
text = "Frånd Åå".encode("UTF-8")
|
|
|
|
|
searchString = "Å".encode("UTF-8")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 0
|
|
|
|
|
self.ed.TargetEnd = self.ed.Length-1
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
pos = self.ed.SearchInTarget(len(searchString), searchString)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(2, pos)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testUTFDifferentLength(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# Searching for a two byte string finds a single byte
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetCodePage(65001)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# two byte string "ſ" single byte "s"
|
|
|
|
|
text = "Frånds Ååſ $".encode("UTF-8")
|
|
|
|
|
searchString = "ſ".encode("UTF-8")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
firstPosition = len("Frånd".encode("UTF-8"))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(len(searchString), 2)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.TargetStart = 0
|
|
|
|
|
self.ed.TargetEnd = self.ed.Length-1
|
|
|
|
|
self.ed.SearchFlags = 0
|
|
|
|
|
pos = self.ed.SearchInTarget(len(searchString), searchString)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(firstPosition, pos)
|
|
|
|
|
self.assertEqual(firstPosition+1, self.ed.TargetEnd)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(lexersAvailable, "no lexers included")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestLexer(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def testLexerNumber(self):
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLexer(), self.ed.SCLEX_CPP)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testLexerName(self):
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetLexer(), self.ed.SCLEX_CPP)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
name = self.ed.GetLexerLanguage(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(name, b"cpp")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testPropertyNames(self):
|
|
|
|
|
propertyNames = self.ed.PropertyNames()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertNotEqual(propertyNames, b"")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# The cpp lexer has a boolean property named lexer.cpp.allow.dollars
|
|
|
|
|
propNameDollars = b"lexer.cpp.allow.dollars"
|
|
|
|
|
propertyType = self.ed.PropertyType(propNameDollars)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(propertyType, self.ed.SC_TYPE_BOOLEAN)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
propertyDescription = self.ed.DescribeProperty(propNameDollars)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertNotEqual(propertyDescription, b"")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
|
|
|
|
|
def testWordListDescriptions(self):
|
|
|
|
|
wordSet = self.ed.DescribeKeyWordSets()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertNotEqual(wordSet, b"")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
@unittest.skipUnless(lexersAvailable, "no lexers included")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
class TestSubStyles(unittest.TestCase):
|
|
|
|
|
''' These tests include knowledge of the current implementation in the cpp lexer
|
|
|
|
|
and may have to change when that implementation changes.
|
|
|
|
|
Currently supports subStyles for IDENTIFIER 11 and COMMENTDOCKEYWORD 17 '''
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def testInfo(self):
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
bases = self.ed.GetSubStyleBases()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(bases, b"\x0b\x11") # 11, 17
|
|
|
|
|
self.assertEqual(self.ed.DistanceToSecondaryStyles(), 0x40)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testAllocate(self):
|
|
|
|
|
firstSubStyle = 0x80 # Current implementation
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetStyleFromSubStyle(firstSubStyle), firstSubStyle)
|
|
|
|
|
self.assertEqual(self.ed.GetSubStylesStart(self.ed.SCE_C_IDENTIFIER), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSubStylesLength(self.ed.SCE_C_IDENTIFIER), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
numSubStyles = 5
|
|
|
|
|
subs = self.ed.AllocateSubStyles(self.ed.SCE_C_IDENTIFIER, numSubStyles)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(subs, firstSubStyle)
|
|
|
|
|
self.assertEqual(self.ed.GetSubStylesStart(self.ed.SCE_C_IDENTIFIER), firstSubStyle)
|
|
|
|
|
self.assertEqual(self.ed.GetSubStylesLength(self.ed.SCE_C_IDENTIFIER), numSubStyles)
|
|
|
|
|
self.assertEqual(self.ed.GetStyleFromSubStyle(subs), self.ed.SCE_C_IDENTIFIER)
|
|
|
|
|
self.assertEqual(self.ed.GetStyleFromSubStyle(subs+numSubStyles-1), self.ed.SCE_C_IDENTIFIER)
|
|
|
|
|
self.assertEqual(self.ed.GetStyleFromSubStyle(self.ed.SCE_C_IDENTIFIER), self.ed.SCE_C_IDENTIFIER)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# Now free and check same as start
|
|
|
|
|
self.ed.FreeSubStyles()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetStyleFromSubStyle(subs), subs)
|
|
|
|
|
self.assertEqual(self.ed.GetSubStylesStart(self.ed.SCE_C_IDENTIFIER), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetSubStylesLength(self.ed.SCE_C_IDENTIFIER), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testInactive(self):
|
|
|
|
|
firstSubStyle = 0x80 # Current implementation
|
|
|
|
|
inactiveDistance = self.ed.DistanceToSecondaryStyles()
|
2022-01-05 00:07:50 +01:00
|
|
|
|
self.xite.ChooseLexer(b"cpp")
|
2015-06-07 23:19:26 +02:00
|
|
|
|
numSubStyles = 5
|
|
|
|
|
subs = self.ed.AllocateSubStyles(self.ed.SCE_C_IDENTIFIER, numSubStyles)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(subs, firstSubStyle)
|
|
|
|
|
self.assertEqual(self.ed.GetStyleFromSubStyle(subs), self.ed.SCE_C_IDENTIFIER)
|
|
|
|
|
self.assertEqual(self.ed.GetStyleFromSubStyle(subs+inactiveDistance), self.ed.SCE_C_IDENTIFIER+inactiveDistance)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.FreeSubStyles()
|
|
|
|
|
|
|
|
|
|
def testSecondary(self):
|
|
|
|
|
inactiveDistance = self.ed.DistanceToSecondaryStyles()
|
2023-06-01 01:11:12 +02:00
|
|
|
|
inactiveIdentifier = self.ed.SCE_C_IDENTIFIER+inactiveDistance
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetPrimaryStyleFromStyle(inactiveIdentifier), self.ed.SCE_C_IDENTIFIER)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
class TestCallTip(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
# 1 line of 4 characters
|
|
|
|
|
t = b"fun("
|
|
|
|
|
self.ed.AddText(len(t), t)
|
|
|
|
|
|
|
|
|
|
def testBasics(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CallTipActive(), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.CallTipShow(1, "fun(int x)")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CallTipActive(), 1)
|
|
|
|
|
self.assertEqual(self.ed.CallTipPosStart(), 4)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.CallTipSetPosStart(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CallTipPosStart(), 1)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
self.ed.CallTipCancel()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CallTipActive(), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2021-02-21 05:53:09 +01:00
|
|
|
|
class TestEdge(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
|
|
|
|
|
def testBasics(self):
|
|
|
|
|
self.ed.EdgeColumn = 3
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.EdgeColumn, 3)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.ed.SetEdgeColour(0xA0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetEdgeColour(), 0xA0)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
def testMulti(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(-1), -1)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(0), -1)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.ed.MultiEdgeAddLine(5, 0x50)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(0), 5)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(1), -1)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.ed.MultiEdgeAddLine(6, 0x60)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(0), 5)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(1), 6)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(2), -1)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.ed.MultiEdgeAddLine(4, 0x40)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(0), 4)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(1), 5)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(2), 6)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(3), -1)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.ed.MultiEdgeClearAll()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(0), -1)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
|
|
|
|
|
def testSameTwice(self):
|
|
|
|
|
# Tests that adding a column twice retains both
|
|
|
|
|
self.ed.MultiEdgeAddLine(5, 0x50)
|
|
|
|
|
self.ed.MultiEdgeAddLine(5, 0x55)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(0), 5)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(1), 5)
|
|
|
|
|
self.assertEqual(self.ed.GetMultiEdgeColumn(2), -1)
|
2021-02-21 05:53:09 +01:00
|
|
|
|
self.ed.MultiEdgeClearAll()
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestAutoComplete(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
# 1 line of 3 characters
|
|
|
|
|
t = b"xxx\n"
|
|
|
|
|
self.ed.AddText(len(t), t)
|
|
|
|
|
|
|
|
|
|
def testDefaults(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetSeparator(), ord(' '))
|
|
|
|
|
self.assertEqual(self.ed.AutoCGetMaxHeight(), 5)
|
|
|
|
|
self.assertEqual(self.ed.AutoCGetMaxWidth(), 0)
|
|
|
|
|
self.assertEqual(self.ed.AutoCGetTypeSeparator(), ord('?'))
|
|
|
|
|
self.assertEqual(self.ed.AutoCGetIgnoreCase(), 0)
|
|
|
|
|
self.assertEqual(self.ed.AutoCGetAutoHide(), 1)
|
|
|
|
|
self.assertEqual(self.ed.AutoCGetDropRestOfWord(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testChangeDefaults(self):
|
|
|
|
|
self.ed.AutoCSetSeparator(ord('-'))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetSeparator(), ord('-'))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCSetSeparator(ord(' '))
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetMaxHeight(100)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetMaxHeight(), 100)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCSetMaxHeight(5)
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetMaxWidth(100)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetMaxWidth(), 100)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCSetMaxWidth(0)
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetTypeSeparator(ord('@'))
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetTypeSeparator(), ord('@'))
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCSetTypeSeparator(ord('?'))
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetIgnoreCase(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetIgnoreCase(), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCSetIgnoreCase(0)
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetAutoHide(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetAutoHide(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCSetAutoHide(1)
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetDropRestOfWord(1)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetDropRestOfWord(), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCSetDropRestOfWord(0)
|
|
|
|
|
|
|
|
|
|
def testAutoShow(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0, 0)
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"za defn ghi")
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 1)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
#~ time.sleep(2)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCPosStart(), 0)
|
|
|
|
|
self.assertEqual(self.ed.AutoCGetCurrent(), 0)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
t = self.ed.AutoCGetCurrentText(5)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
#~ self.assertEqual(l, 3)
|
|
|
|
|
self.assertEqual(t, b"za")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.AutoCCancel()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testAutoShowComplete(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0, 0)
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"za defn ghi")
|
|
|
|
|
self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"zaxxx\n")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testAutoShowSelect(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed.SetSel(0, 0)
|
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"za defn ghi")
|
|
|
|
|
self.ed.AutoCSelect(0, b"d")
|
|
|
|
|
self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"defnxxx\n")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 0)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2022-01-05 00:07:50 +01:00
|
|
|
|
def testAutoCustomSort(self):
|
|
|
|
|
# Checks bug #2294 where SC_ORDER_CUSTOM with an empty list asserts
|
|
|
|
|
# https://sourceforge.net/p/scintilla/bugs/2294/
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetOrder(), self.ed.SC_ORDER_PRESORTED)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetOrder(self.ed.SC_ORDER_CUSTOM)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetOrder(), self.ed.SC_ORDER_CUSTOM)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
#~ self.ed.AutoCShow(0, b"")
|
|
|
|
|
#~ self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
#~ self.assertEqual(self.ed.Contents(), b"xxx\n")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"a")
|
|
|
|
|
self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"xxx\na")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetOrder(self.ed.SC_ORDER_PERFORMSORT)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetOrder(), self.ed.SC_ORDER_PERFORMSORT)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"")
|
|
|
|
|
self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"xxx\na")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"b a")
|
|
|
|
|
self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"xxx\naa")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCSetOrder(self.ed.SC_ORDER_PRESORTED)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCGetOrder(), self.ed.SC_ORDER_PRESORTED)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"")
|
|
|
|
|
self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"xxx\naa")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
|
|
|
|
self.ed.AutoCShow(0, b"a b")
|
|
|
|
|
self.ed.AutoCComplete()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"xxx\naaa")
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.AutoCActive(), 0)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
def testWriteOnly(self):
|
|
|
|
|
""" Checks that setting attributes doesn't crash or change tested behaviour
|
|
|
|
|
but does not check that the changed attributes are effective. """
|
|
|
|
|
self.ed.AutoCStops(0, b"abcde")
|
|
|
|
|
self.ed.AutoCSetFillUps(0, b"1234")
|
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestDirectAccess(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testGapPosition(self):
|
|
|
|
|
text = b"abcd"
|
|
|
|
|
self.ed.SetContents(text)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GapPosition, 4)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.TargetStart = 1
|
|
|
|
|
self.ed.TargetEnd = 1
|
|
|
|
|
rep = b"-"
|
|
|
|
|
self.ed.ReplaceTarget(len(rep), rep)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GapPosition, 2)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
|
|
|
|
def testCharacterPointerAndRangePointer(self):
|
|
|
|
|
text = b"abcd"
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.ed.SetContents(text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
characterPointer = self.ed.CharacterPointer
|
2013-08-28 02:44:27 +02:00
|
|
|
|
rangePointer = self.ed.GetRangePointer(0,3)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(characterPointer, rangePointer)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
cpBuffer = ctypes.c_char_p(characterPointer)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(cpBuffer.value, text)
|
2013-01-25 01:46:29 +01:00
|
|
|
|
# Gap will not be moved as already moved for CharacterPointer call
|
2013-08-28 02:44:27 +02:00
|
|
|
|
rangePointer = self.ed.GetRangePointer(1,3)
|
|
|
|
|
cpBuffer = ctypes.c_char_p(rangePointer)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(cpBuffer.value, text[1:])
|
2013-01-25 01:46:29 +01:00
|
|
|
|
|
2023-02-09 17:57:24 +01:00
|
|
|
|
class TestJoin(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def testJoin(self):
|
|
|
|
|
text = b"a\r\nb\r\nc"
|
|
|
|
|
self.ed.SetContents(text)
|
|
|
|
|
self.ed.TargetWholeDocument()
|
|
|
|
|
self.ed.LinesJoin()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a b c")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
def testJoinEndLine(self):
|
|
|
|
|
text = b"a\r\nb\r\nc"
|
|
|
|
|
self.ed.SetContents(text)
|
|
|
|
|
# Select a..b
|
|
|
|
|
self.ed.SetTargetRange(0, 4)
|
|
|
|
|
self.ed.LinesJoin()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a b\r\nc")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
def testJoinSpace(self):
|
|
|
|
|
# Demonstration of bug #2372 which produced b"a \r"
|
|
|
|
|
text = b"a \r\n\r\n"
|
|
|
|
|
self.ed.SetContents(text)
|
|
|
|
|
self.ed.TargetWholeDocument()
|
|
|
|
|
self.ed.LinesJoin()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a ")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
|
|
|
|
def testJoinOutOfBounds(self):
|
|
|
|
|
text = b"a\r\nb\r\nc"
|
|
|
|
|
self.ed.SetContents(text)
|
|
|
|
|
# Setting end of target after document end encourages non-termination.
|
|
|
|
|
self.ed.SetTargetRange(-10, 16)
|
|
|
|
|
self.ed.LinesJoin()
|
|
|
|
|
# Out-of-bounds leaves extra space as 'c' is processed
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.Contents(), b"a b c ")
|
2023-02-09 17:57:24 +01:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
class TestWordChars(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.xite = Xite.xiteFrame
|
2013-01-25 01:46:29 +01:00
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.ed.SetCharsDefault()
|
|
|
|
|
|
|
|
|
|
def _setChars(self, charClass, chars):
|
|
|
|
|
""" Wrapper to call self.ed.Set*Chars with the right type
|
|
|
|
|
@param charClass {str} the character class, "word", "space", etc.
|
|
|
|
|
@param chars {iterable of int} characters to set
|
|
|
|
|
"""
|
|
|
|
|
if sys.version_info.major == 2:
|
|
|
|
|
# Python 2, use latin-1 encoded str
|
|
|
|
|
unichars = (unichr(x) for x in chars if x != 0)
|
|
|
|
|
# can't use literal u"", that's a syntax error in Py3k
|
|
|
|
|
# uncode() doesn't exist in Py3k, but we never run it there
|
|
|
|
|
result = unicode("").join(unichars).encode("latin-1")
|
|
|
|
|
else:
|
|
|
|
|
# Python 3, use bytes()
|
|
|
|
|
result = bytes(x for x in chars if x != 0)
|
|
|
|
|
meth = getattr(self.ed, "Set%sChars" % (charClass.capitalize()))
|
|
|
|
|
return meth(None, result)
|
|
|
|
|
|
|
|
|
|
def assertCharSetsEqual(self, first, second, *args, **kwargs):
|
|
|
|
|
""" Assert that the two character sets are equal.
|
|
|
|
|
If either set are an iterable of numbers, convert them to chars
|
|
|
|
|
first. """
|
|
|
|
|
first_set = set()
|
|
|
|
|
for c in first:
|
|
|
|
|
first_set.add(chr(c) if isinstance(c, int) else c)
|
|
|
|
|
second_set = set()
|
|
|
|
|
for c in second:
|
|
|
|
|
second_set.add(chr(c) if isinstance(c, int) else c)
|
|
|
|
|
return self.assertEqual(first_set, second_set, *args, **kwargs)
|
|
|
|
|
|
2013-08-28 02:44:27 +02:00
|
|
|
|
def testDefaultWordChars(self):
|
|
|
|
|
# check that the default word chars are as expected
|
|
|
|
|
data = self.ed.GetWordChars(None)
|
|
|
|
|
expected = set(string.digits + string.ascii_letters + '_') | \
|
|
|
|
|
set(chr(x) for x in range(0x80, 0x100))
|
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
|
|
|
|
|
def testDefaultWhitespaceChars(self):
|
|
|
|
|
# check that the default whitespace chars are as expected
|
|
|
|
|
data = self.ed.GetWhitespaceChars(None)
|
2022-01-05 00:07:50 +01:00
|
|
|
|
expected = (set(chr(x) for x in (range(0, 0x20))) | set(' ') | set('\x7f')) - \
|
2013-08-28 02:44:27 +02:00
|
|
|
|
set(['\r', '\n'])
|
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
|
|
|
|
|
def testDefaultPunctuationChars(self):
|
|
|
|
|
# check that the default punctuation chars are as expected
|
|
|
|
|
data = self.ed.GetPunctuationChars(None)
|
|
|
|
|
expected = set(chr(x) for x in range(0x20, 0x80)) - \
|
2022-01-05 00:07:50 +01:00
|
|
|
|
set(string.ascii_letters + string.digits + "\r\n\x7f_ ")
|
2013-08-28 02:44:27 +02:00
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
|
|
|
|
|
def testCustomWordChars(self):
|
|
|
|
|
# check that setting things to whitespace chars makes them not words
|
|
|
|
|
self._setChars("whitespace", range(1, 0x100))
|
|
|
|
|
data = self.ed.GetWordChars(None)
|
|
|
|
|
expected = set()
|
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
# and now set something to make sure that works too
|
|
|
|
|
expected = set(range(1, 0x100, 2))
|
|
|
|
|
self._setChars("word", expected)
|
|
|
|
|
data = self.ed.GetWordChars(None)
|
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
|
|
|
|
|
def testCustomWhitespaceChars(self):
|
|
|
|
|
# check setting whitespace chars to non-default values
|
|
|
|
|
self._setChars("word", range(1, 0x100))
|
|
|
|
|
# we can't change chr(0) from being anything but whitespace
|
|
|
|
|
expected = set([0])
|
|
|
|
|
data = self.ed.GetWhitespaceChars(None)
|
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
# now try to set it to something custom
|
|
|
|
|
expected = set(range(1, 0x100, 2)) | set([0])
|
|
|
|
|
self._setChars("whitespace", expected)
|
|
|
|
|
data = self.ed.GetWhitespaceChars(None)
|
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
|
|
|
|
|
def testCustomPunctuationChars(self):
|
|
|
|
|
# check setting punctuation chars to non-default values
|
|
|
|
|
self._setChars("word", range(1, 0x100))
|
|
|
|
|
expected = set()
|
|
|
|
|
data = self.ed.GetPunctuationChars(0)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(set(data), expected)
|
2013-08-28 02:44:27 +02:00
|
|
|
|
# now try to set it to something custom
|
|
|
|
|
expected = set(range(1, 0x100, 1))
|
|
|
|
|
self._setChars("punctuation", expected)
|
|
|
|
|
data = self.ed.GetPunctuationChars(None)
|
|
|
|
|
self.assertCharSetsEqual(data, expected)
|
|
|
|
|
|
2019-07-21 15:26:02 +02:00
|
|
|
|
def testCharacterCategoryOptimization(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CharacterCategoryOptimization, 0x100)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
self.ed.CharacterCategoryOptimization = 0x1000
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.CharacterCategoryOptimization, 0x1000)
|
2019-07-21 15:26:02 +02:00
|
|
|
|
|
2015-06-07 23:19:26 +02:00
|
|
|
|
class TestExplicitTabStops(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.xite = Xite.xiteFrame
|
|
|
|
|
self.ed = self.xite.ed
|
|
|
|
|
self.ed.ClearAll()
|
|
|
|
|
self.ed.EmptyUndoBuffer()
|
|
|
|
|
# 2 lines of 4 characters
|
|
|
|
|
self.t = b"fun(\nint)"
|
|
|
|
|
self.ed.AddText(len(self.t), self.t)
|
|
|
|
|
|
|
|
|
|
def testAddingAndClearing(self):
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
# Add a tab stop at 7
|
|
|
|
|
self.ed.AddTabStop(0, 7)
|
|
|
|
|
# Check added
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 7)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# Check does not affect line 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,0), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
# Add a tab stop at 18
|
|
|
|
|
self.ed.AddTabStop(0, 18)
|
|
|
|
|
# Check added
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 7)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,7), 18)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# Check does not affect line 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,7), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
# Add a tab stop between others at 13
|
|
|
|
|
self.ed.AddTabStop(0, 13)
|
|
|
|
|
# Check added
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 7)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,7), 13)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,13), 18)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
# Check does not affect line 1
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,7), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
self.ed.ClearTabStops(0)
|
|
|
|
|
# Check back to original state
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
def testLineInsertionDeletion(self):
|
|
|
|
|
# Add a tab stop at 7 on line 1
|
|
|
|
|
self.ed.AddTabStop(1, 7)
|
|
|
|
|
# Check added
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,0), 7)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
# More text at end
|
|
|
|
|
self.ed.AddText(len(self.t), self.t)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,0), 7)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(2,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(3,0), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
# Another 2 lines before explicit line moves the explicit tab stop
|
|
|
|
|
data = b"x\ny\n"
|
|
|
|
|
self.ed.InsertText(4, data)
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(2,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(3,0), 7)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(4,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(5,0), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
|
|
|
|
# Undo moves the explicit tab stop back
|
|
|
|
|
self.ed.Undo()
|
2023-11-05 18:24:41 +01:00
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(0,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(1,0), 7)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(2,0), 0)
|
|
|
|
|
self.assertEqual(self.ed.GetNextTabStop(3,0), 0)
|
2015-06-07 23:19:26 +02:00
|
|
|
|
|
2013-01-25 01:46:29 +01:00
|
|
|
|
if __name__ == '__main__':
|
2013-08-28 02:44:27 +02:00
|
|
|
|
uu = Xite.main("simpleTests")
|
2013-01-25 01:46:29 +01:00
|
|
|
|
#~ for x in sorted(uu.keys()):
|
|
|
|
|
#~ print(x, uu[x])
|
|
|
|
|
#~ print()
|