/* * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * @test * @bug 6850113 8032446 8255242 * @summary confirm the behavior of new Bidi implementation. (Backward compatibility) * @modules java.desktop
*/
try {
bidi = new Bidi(null);
errorHandling("Bidi((AttributedCharacterIterator)null) " + "should throw an IAE.");
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
errorHandling("Bidi((AttributedCharacterIterator)null) " + "should not throw an NPE but an IAE.");
}
String paragraph = data4Constructor1[1][0]; int start = paragraph.indexOf('<')+1; int limit = paragraph.indexOf('>');
AttributedString astr = new AttributedString(paragraph);
astr.addAttribute(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL);
astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-MAX_EXPLICIT_LEVEL),
start, limit); try {
bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) {
errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
i + ") should not be " + bidi.getLevelAt(i) + " but MAX_EXPLICIT_LEVEL-1 when BIDI_EMBEDDING is -MAX_EXPLICIT_LEVEL.");
}
}
} catch (Exception e) {
errorHandling(" Unexpected exception: " + e);
}
astr = new AttributedString(paragraph);
astr.addAttribute(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL);
astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-(MAX_EXPLICIT_LEVEL+1)),
start, limit); try {
bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != 1) {
errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " + "should be 1 when BIDI_EMBEDDING is -(MAX_EXPLICIT_LEVEL+1).");
}
}
} catch (Exception e) {
errorHandling(" Unexpected exception: " + e);
}
astr = new AttributedString(paragraph);
astr.addAttribute(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL);
astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL-1),
start, limit); try {
bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) {
errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " + "should be MAX_EXPLICIT_LEVEL when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL-1.");
}
}
} catch (Exception e) {
errorHandling(" Unexpected exception: " + e);
}
astr = new AttributedString(paragraph);
astr.addAttribute(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL);
astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL),
start, limit); try {
bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) {
errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
i + ") should not be " + bidi.getLevelAt(i) + " but MAX_EXPLICIT_LEVEL when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL.");
}
}
} catch (Exception e) {
errorHandling(" Unexpected exception: " + e);
}
astr = new AttributedString(paragraph);
astr.addAttribute(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL);
astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL+1),
start, limit); try {
bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != 1) {
errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
i + ") should not be " + bidi.getLevelAt(i) + " but 1 when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL+1.");
}
}
} catch (Exception e) {
errorHandling(" Unexpected exception: " + e);
}
}
privatevoid testConstructor2() {
Bidi bidi;
try {
bidi = new Bidi(null, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT)" + " should throw an IAE.");
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT) " + "should not throw an NPE but an IAE.");
}
try {
bidi = new Bidi("abc", -3);
} catch (Exception e) {
errorHandling("Bidi(\"abc\", -3) should not throw an exception: " +
e);
}
try {
bidi = new Bidi("abc", 2);
} catch (Exception e) {
errorHandling("Bidi(\"abc\", 2) should not throw an exception: " +
e);
}
}
try {
bidi = new Bidi(null, 0, embeddings, 0, 5,
Bidi.DIRECTION_LEFT_TO_RIGHT);
errorHandling("Bidi(char[], ...) should throw an IAE " + "when text=null.");
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
errorHandling("Bidi(char[], ...) should not throw an NPE " + "but an IAE when text=null.");
}
try {
bidi = new Bidi(text, -1, embeddings, 0, 5,
Bidi.DIRECTION_LEFT_TO_RIGHT);
errorHandling("Bidi(char[], ...) should throw an IAE " + "when textStart is incorrect(-1: too small).");
} catch (IllegalArgumentException e) {
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("Bidi(char[], ...) should not throw an NPE " + "but an IAE when textStart is incorrect(-1: too small).");
}
try {
bidi = new Bidi(text, 4, embeddings, 0, 2,
Bidi.DIRECTION_LEFT_TO_RIGHT);
errorHandling("Bidi(char[], ...) should throw an IAE " + "when textStart is incorrect(4: too large).");
} catch (IllegalArgumentException e) {
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("Bidi(char[], ...) should not throw an NPE " + "but an IAE when textStart is incorrect(4: too large).");
}
byte[] actualLevels = newbyte[text.length]; byte[] validEmbeddings1 = {0, -MAX_EXPLICIT_LEVEL, -(MAX_EXPLICIT_LEVEL-1), -2, -1}; byte[] expectedLevels1 = {0, MAX_EXPLICIT_LEVEL, MAX_EXPLICIT_LEVEL-1, 2, 1}; try {
bidi = new Bidi(text, 0, validEmbeddings1, 0, 5,
Bidi.DIRECTION_LEFT_TO_RIGHT); for (int i = 0; i < text.length; i++) {
actualLevels[i] = (byte)bidi.getLevelAt(i);
} if (!Arrays.equals(expectedLevels1, actualLevels)) {
errorHandling("Bidi(char[], ...).getLevelAt()" + " should be {" + toString(actualLevels) + "} when embeddings are {" +
toString(expectedLevels1) + "}.");
}
} catch (Exception e) {
errorHandling("Bidi(char[], ...) should not throw an exception " + "when embeddings is valid(-MAX_EXPLICIT_LEVEL).");
}
byte[] validEmbeddings2 = {0, MAX_EXPLICIT_LEVEL, MAX_EXPLICIT_LEVEL-1, 2, 1}; byte[] expectedLevels2 = {0, MAX_EXPLICIT_LEVEL+1, MAX_EXPLICIT_LEVEL-1, 2, 2}; try {
bidi = new Bidi(text, 0, validEmbeddings2, 0, 5,
Bidi.DIRECTION_LEFT_TO_RIGHT); for (int i = 0; i < text.length; i++) {
actualLevels[i] = (byte)bidi.getLevelAt(i);
} if (!Arrays.equals(expectedLevels2, actualLevels)) {
errorHandling("Bidi(char[], ...).getLevelAt()" + " should be {" + toString(actualLevels) + "} when embeddings are {" +
toString(expectedLevels2) + "}.");
}
} catch (Exception e) {
errorHandling("Bidi(char[], ...) should not throw an exception " + "when embeddings is valid(MAX_EXPLICIT_LEVEL).");
}
byte[] invalidEmbeddings1 = {0, -(MAX_EXPLICIT_LEVEL+1), 0, 0, 0}; try {
bidi = new Bidi(text, 0, invalidEmbeddings1, 0, 5,
Bidi.DIRECTION_LEFT_TO_RIGHT); if (bidi.getLevelAt(1) != 0) {
errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " + "when embeddings[1] is -(MAX_EXPLICIT_LEVEL+1).");
}
} catch (Exception e) {
errorHandling("Bidi(char[], ...) should not throw an exception " + "even when embeddings includes -(MAX_EXPLICIT_LEVEL+1).");
}
byte[] invalidEmbeddings2 = {0, MAX_EXPLICIT_LEVEL+1, 0, 0, 0}; try {
bidi = new Bidi(text, 0, invalidEmbeddings2, 0, 5,
Bidi.DIRECTION_LEFT_TO_RIGHT); if (bidi.getLevelAt(1) != 0) {
errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " + "when embeddings[1] is MAX_EXPLICIT_LEVEL+1.");
}
} catch (Exception e) {
errorHandling("Bidi(char[], ...) should not throw an exception " + "even when embeddings includes MAX_EXPLICIT_LEVEL+1.");
}
try {
bidi = new Bidi(text, 0, embeddings, 0, -1,
Bidi.DIRECTION_LEFT_TO_RIGHT);
errorHandling("Bidi(char[], ...) should throw an IAE " + "when paragraphLength=-1(too small).");
} catch (IllegalArgumentException e) {
} catch (NegativeArraySizeException e) {
errorHandling("Bidi(char[], ...) should not throw an NASE " + "but an IAE when paragraphLength=-1(too small).");
}
try {
bidi = new Bidi(text, 0, embeddings, 0, 6,
Bidi.DIRECTION_LEFT_TO_RIGHT);
errorHandling("Bidi(char[], ...) should throw an IAE " + "when paragraphLength=6(too large).");
} catch (IllegalArgumentException e) {
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("Bidi(char[], ...) should not throw an AIOoBE " + "but an IAE when paragraphLength=6(too large).");
}
try {
bidi = new Bidi(text, 0, embeddings, 0, 4, -3);
} catch (Exception e) {
errorHandling("Bidi(char[], ...) should not throw an exception " + "even when flag=-3(too small).");
}
try {
bidi = new Bidi(text, 0, embeddings, 0, 5, 2);
} catch (Exception e) {
errorHandling("Bidi(char[], ...) should not throw an exception " + "even when flag=2(too large).");
}
}
/* Test getLevelAt() */
sb.setLength(0); for (int i = 0; i < text.length(); i++) {
sb.append(bidi.getLevelAt(i));
}
checkResult("getLevelAt()", expectedLevels, sb.toString());
privateint getRunCount(String levels) { int len = levels.length(); char c = levels.charAt(0); int runCount = 1;
for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) {
runCount++;
c = levels.charAt(index);
}
}
return runCount;
}
privateint[] getRunLevels_int(int runCount, String levels) { int[] array = newint[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 0;
array[i++] = c - '0';
for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) {
c = levels.charAt(index);
array[i++] = c - '0';
}
}
return array;
}
privatebyte[] getRunLevels_byte(int runCount, String levels) { byte[] array = newbyte[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 0;
array[i++] = (byte)(c - '0');
for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) {
c = levels.charAt(index);
array[i++] = (byte)(c - '0');
}
}
return array;
}
privateint[] getRunLimits(int runCount, String levels) { int[] array = newint[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 0;
for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) {
c = levels.charAt(index);
array[i++] = index;
}
}
array[i] = len;
return array;
}
privateint[] getRunStarts(int runCount, String levels) { int[] array = newint[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 1;
for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) {
c = levels.charAt(index);
array[i++] = index;
}
}
try {
bidi.getRunLimit(-1);
errorHandling("getRunLimit() should throw an AIOoBE " + "when run is -1(too small).");
} catch (ArrayIndexOutOfBoundsException e) {
} catch (IllegalArgumentException e) {
errorHandling("getRunLimit() should not throw an IAE " + "but an AIOoBE when run is -1(too small).");
}
try {
bidi.getRunLimit(0);
bidi.getRunLimit(1);
bidi.getRunLimit(2);
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("getRunLimit() should not throw an AIOOBE " + "when run is from 0 to 2(runCount-1).");
}
try {
bidi.getRunLimit(3);
errorHandling("getRunLimit() should throw an AIOoBE " + "when run is 3(same as runCount).");
} catch (ArrayIndexOutOfBoundsException e) {
} catch (IllegalArgumentException e) {
errorHandling("getRunLimit() should not throw an IAE " + "but an AIOoBE when run is 3(same as runCount).");
}
}
privatevoid testMethod_getRunStart() {
System.out.println("*** Test getRunStart()");
String str = "ABC 123"; int length = str.length();
Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
try { if (bidi.getRunStart(-1) != 0 || // runCount - 2
bidi.getRunStart(0) != 0 || // runCount - 1
bidi.getRunStart(1) != 0 || // runCount
bidi.getRunStart(2) != 0) { // runCount + 1
errorHandling("getRunStart() should return 0" + " when getRunCount() is 1.");
}
} catch (Exception e) {
errorHandling("getRunLimit() should not throw an exception" + " when getRunCount() is 1.");
}
try {
bidi.getRunStart(-1);
errorHandling("getRunStart() should throw an AIOoBE" + " when run is -1(too small).");
} catch (ArrayIndexOutOfBoundsException e) {
} catch (IllegalArgumentException e) {
errorHandling("getRunStart() should not throw an IAE " + "but an AIOoBE when run is -1(too small).");
}
try {
bidi.getRunStart(0);
bidi.getRunStart(1);
bidi.getRunStart(2);
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("getRunStart() should not throw an AIOOBE " + "when run is from 0 to 2(runCount-1).");
}
try { if (bidi.getRunStart(3) != length) {
errorHandling("getRunStart() should return " + length + " when run is 3(same as runCount).");
}
} catch (Exception e) {
errorHandling("getRunStart() should not throw an exception " + "when run is 3(same as runCount).");
}
try {
bidi.getRunStart(4);
errorHandling("getRunStart() should throw an AIOoBE " + "when run is runCount+1(too large).");
} catch (ArrayIndexOutOfBoundsException e) {
} catch (IllegalArgumentException e) {
errorHandling("getRunStart() should not throw an IAE " + "but an AIOoBE when run is runCount+1(too large).");
}
}
privatevoid testMethod_reorderVisually1() {
System.out.println("*** Test reorderVisually() 1");
privatevoid testMethod_reorderVisually2() {
System.out.println("*** Test reorderVisually() 2");
Object[] objects = data4reorderVisually[0][0]; byte[] levels = getLevels(data4reorderVisually[0]); int count = objects.length; int llen = levels.length; int olen = objects.length;
try {
Bidi.reorderVisually(null, 0, objects, 0, count);
errorHandling("reorderVisually() should throw a NPE " + "when levels is null.");
} catch (NullPointerException e) {
}
try {
Bidi.reorderVisually(levels, -1, objects, 0, count);
errorHandling("reorderVisually() should throw an IAE " + "when levelStart is -1.");
} catch (IllegalArgumentException e) { if (!e.getMessage().equals( "Value levelStart -1 is out of range 0 to " + (llen - 1))) {
errorHandling("reorderVisually() should throw an IAE" + " mentioning levelStart is beyond the levels range. Message: " + e.getMessage());
}
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when levelStart is -1.");
}
try {
Bidi.reorderVisually(levels, llen, objects, 0, count);
errorHandling("reorderVisually() should throw an IAE " + "when levelStart is 6(levels.length).");
} catch (IllegalArgumentException e) { if (!e.getMessage().equals( "Value levelStart " + llen + " is out of range 0 to " + (llen - 1))) {
errorHandling("reorderVisually() should throw an IAE" + " mentioning levelStart is beyond the levels range. Message: " + e.getMessage());
}
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when levelStart is 6(levels.length).");
}
try {
Bidi.reorderVisually(levels, 0, null, 0, count);
errorHandling("reorderVisually() should throw a NPE" + " when objects is null.");
} catch (NullPointerException e) {
}
try {
Bidi.reorderVisually(levels, 0, objects, -1, count);
errorHandling("reorderVisually() should throw an IAE" + " when objectStart is -1.");
} catch (IllegalArgumentException e) { if (!e.getMessage().equals( "Value objectStart -1 is out of range 0 to " + (olen - 1))) {
errorHandling("reorderVisually() should throw an IAE" + " mentioning objectStart is beyond the objects range. Message: " + e.getMessage());
}
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when objectStart is -1.");
}
try {
Bidi.reorderVisually(levels, 0, objects, 6, objects.length);
errorHandling("reorderVisually() should throw an IAE " + "when objectStart is 6(objects.length).");
} catch (IllegalArgumentException e) { if (!e.getMessage().equals( "Value objectStart 6 is out of range 0 to " + (olen - 1))) {
errorHandling("reorderVisually() should throw an IAE" + " mentioning objectStart is beyond the objects range. Message: " + e.getMessage());
}
}
try {
Bidi.reorderVisually(levels, 0, objects, 0, -1);
errorHandling("reorderVisually() should throw an IAE " + "when count is -1.");
} catch (IllegalArgumentException e) { if (!e.getMessage().equals( "Value count -1 is less than zero, or objectStart + count " + "is beyond objects length " + olen)) {
errorHandling("reorderVisually() should throw an IAE" + " mentioning objectStart/count is beyond the objects range. Message: " + e.getMessage());
}
} catch (NegativeArraySizeException e) {
errorHandling("reorderVisually() should not throw an NASE " + "but an IAE when count is -1.");
}
try {
Bidi.reorderVisually(levels, 0, objects, 0, count+1);
errorHandling("reorderVisually() should throw an IAE " + "when count is 7(objects.length+1).");
} catch (IllegalArgumentException e) { if (!e.getMessage().equals( "Value count " + (count + 1) + " is less than zero, or objectStart + count " + "is beyond objects length " + olen)) {
errorHandling("reorderVisually() should throw an IAE" + " mentioning objectStart/count is beyond the objects range. Message: " + e.getMessage());
}
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when count is 7(objects.length+1).");
}
try {
Bidi.reorderVisually(levels, 0, objects, 0, 0);
checkResult("reorderVisually(count=0)",
data4reorderVisually[0][0], objects);
} catch (Exception e) {
errorHandling("reorderVisually() should not throw an exception" + " when count is 0.");
}
}
privatevoid testMethod_requiresBidi() {
System.out.println("*** Test requiresBidi()");
try {
Bidi.requiresBidi(txt, -1, textLength);
errorHandling("requiresBidi() should throw an IAE" + " when start is -1(too small).");
} catch (IllegalArgumentException e) {
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("requiresBidi() should not throw an AIOoBE " + "but an IAE when start is -1(too small).");
}
try {
Bidi.requiresBidi(txt, textLength, textLength);
} catch (Exception e) {
errorHandling("requiresBidi() should not throw an exception " + "when start is textLength.");
}
try {
Bidi.requiresBidi(txt, textLength+1, textLength);
errorHandling("requiresBidi() should throw an IAE" + " when start is textLength+1(too large).");
} catch (IllegalArgumentException e) {
}
try {
Bidi.requiresBidi(txt, 0, -1);
errorHandling("requiresBidi() should throw an IAE" + " when limit is -1(too small).");
} catch (IllegalArgumentException e) {
}
try {
Bidi.requiresBidi(txt, 0, textLength+1);
errorHandling("requiresBidi() should throw an IAE" + " when limit is textLength+1(too large).");
} catch (IllegalArgumentException e) { if (!e.getMessage().equals( "Value start 0 is out of range 0 to " + (textLength + 1) + ", or limit " + (textLength + 1) + " is beyond the text length " + textLength)) {
errorHandling("requiresBidi() should throw an IAE" + " mentioning limit is beyond the text length. Message: " + e.getMessage());
}
} catch (ArrayIndexOutOfBoundsException e) {
errorHandling("requiresBidi() should not throw an AIOoBE " + "but an IAE when limit is textLength+1(too large).");
}
}
privatevoid checkResult(String name, int expectedValue, int actualValue) { if (expectedValue != actualValue) {
errorHandling("Unexpected " + name + " value." + " Expected: " + expectedValue + " Got: " + actualValue);
} elseif (verbose) {
System.out.println(" Okay : " + name + " = " + actualValue);
}
}
private String toReadableString(String str) {
String s = str;
s = s.replaceAll(ArabicABC, "ArabicABC");
s = s.replaceAll(Arabic123, "Arabic123");
s = s.replaceAll(PArabicABC, "ArabicABC(Presentation form)");
s = s.replaceAll(HebrewABC, "HebrewABC");
s = s.replaceAll(KharoshthiABC, "KharoshthiABC");
s = s.replaceAll(Kharoshthi123, "Kharoshthi123");
s = s.replaceAll(NKoABC, "NKoABC");
s = s.replaceAll(NKo123, "NKo123");
s = s.replaceAll(OsmanyaABC, "OsmanyaABC");
s = s.replaceAll(Osmanya123, "Osmanya123");
return s;
}
privatebyte[] getLevels(Object[][] data) { int levelLength = data[0].length; byte[] array = newbyte[levelLength]; int textIndex = 0;
for (int i = 0; i < levelLength; i++) {
array[i] = (byte)(((String)data[1][0]).charAt(textIndex) - '0');
textIndex += ((String)data[0][i]).length();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.