Ciao Sandro,
Can you run the tests with debug on (hint: change setting in “build.properties” 
file) to see the specific failure in VersionTest, please?!  It works fine on my 
laptop with Java 11+28

Thanks,
~Roger

> On Oct 31, 2023, at 12:15 PM, smart...@apache.org wrote:
> 
> Modified: pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java
> URL: 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_serialization_MacroReader.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=ciFvnfAumCmyGtAjZc8B1orUjkLV7Rx6BdJyk5LK39Y&e=
> ==============================================================================
> --- pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java 
> (original)
> +++ pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java Tue 
> Oct 31 19:15:47 2023
> @@ -1,249 +1,249 @@
> -/*
> - * Licensed to the Apache Software Foundation (ASF) under one or more
> - * contributor license agreements.  See the NOTICE file distributed with
> - * this work for additional information regarding copyright ownership.
> - * The ASF licenses this file to you under the Apache License,
> - * Version 2.0 (the "License"); you may not use this file except in
> - * compliance with the License.  You may obtain a copy of the License at
> - *
> - *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -package org.apache.pivot.serialization;
> -
> -import java.io.IOException;
> -import java.io.Reader;
> -import java.util.ArrayDeque;
> -import java.util.HashMap;
> -import java.util.Map;
> -import java.util.Queue;
> -
> -
> -/**
> - * This is a {@link Reader} that can be instantiated inline with any other
> - * {@code Reader} to provide macro capabilities.
> - * <p> We recognize <code>#define <i>NAME value</i></code> as definitions
> - * as well as <code>#undef <i>NAME</i></code> to remove a previous 
> definition.
> - * <p> The macro name must correspond to the Unicode naming conventions (see
> - * {@link Character#isUnicodeIdentifierStart} and {@link 
> Character#isUnicodeIdentifierPart}).
> - * <p> Macro substitutions are recognized as <code>${<i>NAME</i>}</code> 
> anywhere
> - * in the underlying stream. Nested macros are supported, and are expanded 
> at the
> - * point of definition, if defined, or at the point of expansion if defined 
> later.
> - */
> -public final class MacroReader extends Reader {
> -    /** The input reader we are mapping. */
> -    private Reader in;
> -
> -    /** The map of our defined variables and their values. */
> -    private Map<String, String> variableMap = new HashMap<>();
> -
> -    /** The lookahead queue, set either by one-character lookahead (such as
> -     * while recognizing "$NAME") or from macro expansion.
> -     */
> -    private Queue<Integer> lookaheadQueue = new ArrayDeque<>();
> -
> -    /** The previous character read. */
> -    private int lastCh = -1;
> -
> -    /**
> -     * Construct a new macro reader on top of the given reader.
> -     * @param reader The input reader we are going to wrap.
> -     */
> -    public MacroReader(final Reader reader) {
> -        
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.in&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=tCqtw4Zer173jvAQ7R3582iktLGQSj7DhNxuOBhQHgs&e=
>  = reader;
> -    }
> -
> -    @Override
> -    public void close() throws IOException {
> -        in.close();
> -    }
> -
> -    /**
> -     * Add the given character to the lookahead queue for reprocessing.
> -     * @param ch The character to queue.
> -     */
> -    private void queue(final int ch) {
> -        if (ch != -1) {
> -            lookaheadQueue.add(ch);
> -        }
> -    }
> -
> -    /**
> -     * Add all the characters of the given character sequence to the
> -     * lookahead queue for reprocessing.
> -     * @param seq The character sequence to be queued up again.
> -     */
> -    private void queue(final CharSequence seq) {
> -        for (int i = 0; i < seq.length(); i++) {
> -           
> https://urldefense.proofpoint.com/v2/url?u=http-3A__lookaheadQueue.ad&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=pYi5v2-hMn6hIVIK_DM3utri2qzyhPFrezlcvGYEbDc&e=d((int)https://urldefense.proofpoint.com/v2/url?u=http-3A__seq.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JFNS-28y5JdxsMAhVt_9dTHtoCZNnTwZvNNe5ZHKA4o&e=arAt(i));
> -        }
> -    }
> -
> -    /**
> -     * Parse out the next word in the stream (according to Unicode
> -     * Identifier semantics) as the macro name, skipping leading whitespace.
> -     * @return The next parsed "word" string.
> -     * @throws IOException for errors reading the stream.
> -     */
> -    private String getNextWord() throws IOException {
> -        StringBuilder buf = new StringBuilder();
> -        int ch;
> -        do {
> -            ch = getNextChar(true);
> -        } while (ch != -1 
> &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=Whitespace(ch));
> -
> -        if (ch != -1) {
> -            buf.append((char) ch);
> -            while ((ch = getNextChar(true)) != -1
> -                   && ((buf.length() == 0 
> &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=UnicodeIdentifierStart(ch))
> -                    || (buf.length() > 0 && 
> Character.isUnicodeIdentifierPart(ch)))) {
> -                buf.append((char) ch);
> -            }
> -
> -            // Re-queue the character that terminated the word
> -            queue(ch);
> -        }
> -        return buf.toString();
> -    }
> -
> -    /**
> -     * Get the next character in the input stream, either from the
> -     * {@link #lookaheadQueue} if anything is queued, or by reading
> -     * from the underlying {@link Reader}.
> -     * <p> This is the heart of the processing that handles both
> -     * macro definition and expansion.
> -     * @param   handleMacros   set to {@code false} only when
> -     *                         invoking this method recursively
> -     *                         to ignore unknown macro commands
> -     *                         or undefined macros
> -     * @return  The next character in the stream.
> -     * @throws IOException if there are errors reading the stream.
> -     */
> -    private int getNextChar(final boolean handleMacros) throws IOException {
> -        int ret = -1;
> -        Integer queuedChar = lookaheadQueue.poll();
> -        if (queuedChar != null) {
> -            ret = queuedChar.intValue();
> -        } else {
> -            ret = in.read();
> -        }
> -
> -        if (handleMacros) {
> -            int ch;
> -
> -            // Check for macro define or undefine (starting with "#"
> -            // at the beginning of a line) (unless we're recursing to
> -            // skip an unknown declaration keyword).
> -            if (ret == '#' && lastCh == '\n') {
> -                String keyword = getNextWord();
> -
> -                if (keyword.equalsIgnoreCase("undef")) {
> -                    String name = getNextWord();
> -
> -                    do {
> -                        ch = getNextChar(false);
> -                    } while (ch != -1 && ch != '\n');
> -
> -                    variableMap.remove(name);
> -
> -                    return getNextChar(true);
> -                } else if (!keyword.equalsIgnoreCase("define")) {
> -                    // Basically ignore any commands we don't understand
> -                    // by simply queueing the text back to be read again
> -                    // but with the flag set to ignore this command (so
> -                    // we don't get into infinite recursion!)
> -                    ch = getNextChar(false);
> -                    queue(ret);
> -                    queue(keyword);
> -                    queue(ch);
> -
> -                    return getNextChar(false);
> -                }
> -
> -                // Define a macro
> -                String name = getNextWord();
> -                StringBuilder buf = new StringBuilder();
> -
> -                // Skip whitespace after the macro name
> -                do {
> -                    ch = getNextChar(true);
> -                } while (ch != -1 && Character.isWhitespace(ch) && ch != 
> '\\' && ch != '\n');
> -
> -                queue(ch);
> -
> -                do {
> -                    while ((ch = getNextChar(true)) != -1 && ch != '\\' && 
> ch != '\n') {
> -                        buf.append((char) ch);
> -                    }
> -
> -                    // Check for line continuation character
> -                    if (ch == '\\') {
> -                        int next = getNextChar(true);
> -                        if (next == '\n') {
> -                            buf.append((char) next);
> -                        } else {
> -                            buf.append((char) ch);
> -                            buf.append((char) next);
> -                        }
> -                    }
> -                } while (ch != -1 && ch != '\n');
> -
> -                variableMap.put(name, buf.toString());
> -
> -                return getNextChar(true);
> -            } else if (ret == '$') {
> -                // Check for macro expansion
> -                // Note: this allows for nested expansion
> -                int next = getNextChar(true);
> -                if (next == '{') {
> -                    StringBuilder buf = new StringBuilder();
> -
> -                    while ((ch = getNextChar(true)) != -1 && ch != '}') {
> -                        buf.append((char) ch);
> -                    }
> -
> -                    String expansion = variableMap.get(buf.toString());
> -                    if (expansion == null) {
> -                        // If the macro is undefined, then we put back the
> -                        // original text to be read again, but without 
> expansion
> -                        queue(ret);
> -                        queue(next);
> -                        queue(buf);
> -                        queue(ch);
> -
> -                        ret = getNextChar(false);
> -                    } else {
> -                        queue(expansion);
> -
> -                        // By allowing expansion here, we get recursive 
> expansion
> -                        ret = getNextChar(true);
> -                    }
> -                } else {
> -                    queue(next);
> -                }
> -            }
> -        }
> -
> -        return (lastCh = ret);
> -    }
> -
> -    @Override
> -    public int read(final char[] cbuf, final int off, final int len) throws 
> IOException {
> -        int read = -1;
> -        for (int i = 0; i < len; i++) {
> -            int ch = getNextChar(true);
> -            if (ch == -1) {
> -                break;
> -            }
> -            read = i;
> -            cbuf[off + i] = (char) ch;
> -        }
> -        return (read == -1) ? read : read + 1;
> -    }
> -
> -}
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License,
> + * Version 2.0 (the "License"); you may not use this file except in
> + * compliance with the License.  You may obtain a copy of the License at
> + *
> + *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +packagehttps://urldefense.proofpoint.com/v2/url?u=http-3A__org.apache.pivot.se&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=ATZhVF6ad-EMaY4FguU2C3Dplmho6Hh1ij2eFjO8OFY&e=rialization;
> +
> +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.io.IO&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=oeYi21_yPbOgOr5G2F7K7QwTFgsercN2xlzdkFMDFUQ&e=Exception;
> +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.io.Re&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=PYI6xIIo5tlzwqhaxpg8a56bGh3pI0TectedoYgkq4o&e=ader;
> +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Ar&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=joMa2RR4U6PRS84V6VJPewd6_XNoEH0q6NFXTHG2qIk&e=rayDeque;
> +import java.util.HashMap;
> +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Ma&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=mR7BaSdU-ZSpplp62NWG2zbcuyfYZYpPEGWLtGSl7Y4&e=p;
> +import java.util.Queue;
> +
> +
> +/**
> + * This is a {@link Reader} that can be instantiated inline with any other
> + * {@code Reader} to provide macro capabilities.
> + * <p> We recognize <code>#define <i>NAME value</i></code> as definitions
> + * as well as <code>#undef <i>NAME</i></code> to remove a previous 
> definition.
> + * <p> The macro name must correspond to the Unicode naming conventions (see
> + * {@link Character#isUnicodeIdentifierStart} and {@link 
> Character#isUnicodeIdentifierPart}).
> + * <p> Macro substitutions are recognized as <code>${<i>NAME</i>}</code> 
> anywhere
> + * in the underlying stream. Nested macros are supported, and are expanded 
> at the
> + * point of definition, if defined, or at the point of expansion if defined 
> later.
> + */
> +public final class MacroReader extends Reader {
> +    /** The input reader we are mapping. */
> +    private Reader in;
> +
> +    /** The map of our defined variables and their values. */
> +    private Map<String, String> variableMap = new HashMap<>();
> +
> +    /** The lookahead queue, set either by one-character lookahead (such as
> +     * while recognizing "$NAME") or from macro expansion.
> +     */
> +    private Queue<Integer> lookaheadQueue = new ArrayDeque<>();
> +
> +    /** The previous character read. */
> +    private int lastCh = -1;
> +
> +    /**
> +     * Construct a new macro reader on top of the given reader.
> +     * @param reader The input reader we are going to wrap.
> +     */
> +    public MacroReader(final Reader reader) {
> +        
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.in&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=tCqtw4Zer173jvAQ7R3582iktLGQSj7DhNxuOBhQHgs&e=
>  = reader;
> +    }
> +
> +    @Override
> +    public void close() throws IOException {
> +        in.close();
> +    }
> +
> +    /**
> +     * Add the given character to the lookahead queue for reprocessing.
> +     * @param ch The character to queue.
> +     */
> +    private void queue(final int ch) {
> +        if (ch != -1) {
> +            lookaheadQueue.add(ch);
> +        }
> +    }
> +
> +    /**
> +     * Add all the characters of the given character sequence to the
> +     * lookahead queue for reprocessing.
> +     * @param seq The character sequence to be queued up again.
> +     */
> +    private void queue(final CharSequence seq) {
> +        for (int i = 0; i < seq.length(); i++) {
> +           
> https://urldefense.proofpoint.com/v2/url?u=http-3A__lookaheadQueue.ad&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=pYi5v2-hMn6hIVIK_DM3utri2qzyhPFrezlcvGYEbDc&e=d((int)https://urldefense.proofpoint.com/v2/url?u=http-3A__seq.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JFNS-28y5JdxsMAhVt_9dTHtoCZNnTwZvNNe5ZHKA4o&e=arAt(i));
> +        }
> +    }
> +
> +    /**
> +     * Parse out the next word in the stream (according to Unicode
> +     * Identifier semantics) as the macro name, skipping leading whitespace.
> +     * @return The next parsed "word" string.
> +     * @throws IOException for errors reading the stream.
> +     */
> +    private String getNextWord() throws IOException {
> +        StringBuilder buf = new StringBuilder();
> +        int ch;
> +        do {
> +            ch = getNextChar(true);
> +        } while (ch != -1 
> &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=Whitespace(ch));
> +
> +        if (ch != -1) {
> +            buf.append((char) ch);
> +            while ((ch = getNextChar(true)) != -1
> +                   && ((buf.length() == 0 
> &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=UnicodeIdentifierStart(ch))
> +                    || (buf.length() > 0 && 
> Character.isUnicodeIdentifierPart(ch)))) {
> +                buf.append((char) ch);
> +            }
> +
> +            // Re-queue the character that terminated the word
> +            queue(ch);
> +        }
> +        return buf.toString();
> +    }
> +
> +    /**
> +     * Get the next character in the input stream, either from the
> +     * {@link #lookaheadQueue} if anything is queued, or by reading
> +     * from the underlying {@link Reader}.
> +     * <p> This is the heart of the processing that handles both
> +     * macro definition and expansion.
> +     * @param   handleMacros   set to {@code false} only when
> +     *                         invoking this method recursively
> +     *                         to ignore unknown macro commands
> +     *                         or undefined macros
> +     * @return  The next character in the stream.
> +     * @throws IOException if there are errors reading the stream.
> +     */
> +    private int getNextChar(final boolean handleMacros) throws IOException {
> +        int ret = -1;
> +        Integer queuedChar = lookaheadQueue.poll();
> +        if (queuedChar != null) {
> +            ret = queuedChar.intValue();
> +        } else {
> +            ret = in.read();
> +        }
> +
> +        if (handleMacros) {
> +            int ch;
> +
> +            // Check for macro define or undefine (starting with "#"
> +            // at the beginning of a line) (unless we're recursing to
> +            // skip an unknown declaration keyword).
> +            if (ret == '#' && lastCh == '\n') {
> +                String keyword = getNextWord();
> +
> +                if (keyword.equalsIgnoreCase("undef")) {
> +                    String name = getNextWord();
> +
> +                    do {
> +                        ch = getNextChar(false);
> +                    } while (ch != -1 && ch != '\n');
> +
> +                    variableMap.remove(name);
> +
> +                    return getNextChar(true);
> +                } else if (!keyword.equalsIgnoreCase("define")) {
> +                    // Basically ignore any commands we don't understand
> +                    // by simply queueing the text back to be read again
> +                    // but with the flag set to ignore this command (so
> +                    // we don't get into infinite recursion!)
> +                    ch = getNextChar(false);
> +                    queue(ret);
> +                    queue(keyword);
> +                    queue(ch);
> +
> +                    return getNextChar(false);
> +                }
> +
> +                // Define a macro
> +                String name = getNextWord();
> +                StringBuilder buf = new StringBuilder();
> +
> +                // Skip whitespace after the macro name
> +                do {
> +                    ch = getNextChar(true);
> +                } while (ch != -1 && Character.isWhitespace(ch) && ch != 
> '\\' && ch != '\n');
> +
> +                queue(ch);
> +
> +                do {
> +                    while ((ch = getNextChar(true)) != -1 && ch != '\\' && 
> ch != '\n') {
> +                        buf.append((char) ch);
> +                    }
> +
> +                    // Check for line continuation character
> +                    if (ch == '\\') {
> +                        int next = getNextChar(true);
> +                        if (next == '\n') {
> +                            buf.append((char) next);
> +                        } else {
> +                            buf.append((char) ch);
> +                            buf.append((char) next);
> +                        }
> +                    }
> +                } while (ch != -1 && ch != '\n');
> +
> +                variableMap.put(name, buf.toString());
> +
> +                return getNextChar(true);
> +            } else if (ret == '$') {
> +                // Check for macro expansion
> +                // Note: this allows for nested expansion
> +                int next = getNextChar(true);
> +                if (next == '{') {
> +                    StringBuilder buf = new StringBuilder();
> +
> +                    while ((ch = getNextChar(true)) != -1 && ch != '}') {
> +                        buf.append((char) ch);
> +                    }
> +
> +                    String expansion = variableMap.get(buf.toString());
> +                    if (expansion == null) {
> +                        // If the macro is undefined, then we put back the
> +                        // original text to be read again, but without 
> expansion
> +                        queue(ret);
> +                        queue(next);
> +                        queue(buf);
> +                        queue(ch);
> +
> +                        ret = getNextChar(false);
> +                    } else {
> +                        queue(expansion);
> +
> +                        // By allowing expansion here, we get recursive 
> expansion
> +                        ret = getNextChar(true);
> +                    }
> +                } else {
> +                    queue(next);
> +                }
> +            }
> +        }
> +
> +        return (lastCh = ret);
> +    }
> +
> +    @Override
> +    public int read(final char[] cbuf, final int off, final int len) throws 
> IOException {
> +        int read = -1;
> +        for (int i = 0; i < len; i++) {
> +            int ch = getNextChar(true);
> +            if (ch == -1) {
> +                break;
> +            }
> +            read = i;
> +            cbuf[off + i] = (char) ch;
> +        }
> +        return (read == -1) ? read : read + 1;
> +    }
> +
> +}
> 
> Propchange: 
> pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> Modified: 
> pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java
> URL: 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_text_AttributedStringCharacterIterator.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=iuKbUu0Mv7cmgUXHAkVEc88Rk4y7x51cOesTA0Bsw40&e=
> ==============================================================================
> --- 
> pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java
>  (original)
> +++ 
> pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java
>  Tue Oct 31 19:15:47 2023
> @@ -1,243 +1,243 @@
> -/*
> - * Licensed to the Apache Software Foundation (ASF) under one or more
> - * contributor license agreements.  See the NOTICE file distributed with
> - * this work for additional information regarding copyright ownership.
> - * The ASF licenses this file to you under the Apache License,
> - * Version 2.0 (the "License"); you may not use this file except in
> - * compliance with the License.  You may obtain a copy of the License at
> - *
> - *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -package org.apache.pivot.text;
> -
> -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.awt.Fo&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=OZxVZJZl4H19qbUs6rikjbOkM8DTkgSDJnEzyjP0rtM&e=nt;
> -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.awt.fo&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=IV_PjRYqtWpHqeIg5Cc6ZMTspNotn1khu_P89K5R7ag&e=nt.TextAttribute;
> -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.text.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=EWntGXPIZXe03Lvd5lwSge_1FACdz_K7jowKGcK_6k0&e=tributedCharacterIterator;
> -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.text.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=EWntGXPIZXe03Lvd5lwSge_1FACdz_K7jowKGcK_6k0&e=tributedString;
> -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Ma&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=mR7BaSdU-ZSpplp62NWG2zbcuyfYZYpPEGWLtGSl7Y4&e=p;
> -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Se&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=vUJKWMT0ARE8Fhtigxy__s6M3MgRl_loNn8HbKDnCJE&e=t;
> -import org.apache.pivot.util.Utils;
> -
> -
> -/**
> - * A sequence of text along with associated attributes, backed by a
> - * {@link AttributedString}, which itself implements all of these
> - * methods.
> - */
> -public class AttributedStringCharacterIterator implements 
> AttributedCharacterIterator {
> -    private AttributedString storage = null;
> -    private int length = 0;
> -    
> privatehttps://urldefense.proofpoint.com/v2/url?u=http-3A__AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=2j7YAIPlD2vCpGlxfw8IECIrWpSpFevu2PwwtpPS1X4&e=tribute[]
>  attributes = null;
> -    private AttributedCharacterIterator iterator = null;
> -
> -    public AttributedStringCharacterIterator() {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new AttributedString("");
> -        this.length = 0;
> -    }
> -
> -    public AttributedStringCharacterIterator(String text) {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text,
>  "text");
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new AttributedString(text);
> -    }
> -
> -    private void 
> addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=WQSrUgEBJAAEbZNRZ7qzXQYhOY9bR4phaqX_XHR_H7I&e=tribute
>  attribute, Object value) {
> -        if (this.length != 0) {
> -           
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.storage.ad&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=t6uaygZpGv2GwPqtAA5TulyKI1QdTYLUs4b9wMt6ux8&e=dAttribute(attribute,
>  value);
> -        }
> -    }
> -
> -    public AttributedStringCharacterIterator(CharSequence charSequence, Font 
> font) {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new 
> AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28charSequence.to&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=Lqzp9pfFFvnGYGOZ88tKAFaCVJS7C5c52QXIfp8DexM&e=String());
> -        this.length = charSequence.length();
> -        
> addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28TextAttribute.FO&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=UCDykGntgw4piBQmy8GMqGpzwx9enf0hBQThj8i68us&e=NT,
>  font);
> -    }
> -
> -    public AttributedStringCharacterIterator(CharSequence charSequence, int 
> beginIndex, Font font) {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new 
> AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28charSequence.su&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=-aGsRPgU4CeucABgu4cGzpPKshQcp8-B6EUazZGfBMk&e=bSequence(beginIndex,
>  charSequence.length()).toString());
> -        this.length = charSequence.length() - beginIndex;
> -        
> addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28TextAttribute.FO&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=UCDykGntgw4piBQmy8GMqGpzwx9enf0hBQThj8i68us&e=NT,
>  font);
> -    }
> -
> -    public AttributedStringCharacterIterator(String text, int beginIndex, 
> int endIndex) {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text,
>  "text");
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new 
> AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28text.su&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=Dfr-4za8tjnHQxVkvzud-HKgzv6yz8Df9RsBJvVmras&e=bstring(beginIndex,
>  endIndex));
> -        this.length = endIndex - beginIndex;
> -    }
> -
> -    public AttributedStringCharacterIterator(AttributedCharacterIterator 
> iter, int beginIndex, int endIndex) {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new AttributedString(iter, beginIndex, endIndex);
> -        this.length = endIndex - beginIndex;
> -    }
> -
> -    public AttributedStringCharacterIterator(String 
> text,https://urldefense.proofpoint.com/v2/url?u=http-3A__AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=2j7YAIPlD2vCpGlxfw8IECIrWpSpFevu2PwwtpPS1X4&e=tribute[]
>  attributes) {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text,
>  "text");
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new AttributedString(text);
> -        this.length = text.length();
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.at&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=nDodAvEl6NSdE3I9mS5x2mS-D8_ArWHAsLM6ywwHmV8&e=tributes
>  = attributes;
> -    }
> -
> -    public AttributedStringCharacterIterator(String text, int beginIndex, 
> int endIndex,
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=2j7YAIPlD2vCpGlxfw8IECIrWpSpFevu2PwwtpPS1X4&e=tribute[]
>  attributes) {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text,
>  "text");
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = new 
> AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28text.su&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=Dfr-4za8tjnHQxVkvzud-HKgzv6yz8Df9RsBJvVmras&e=bstring(beginIndex,
>  endIndex));
> -        this.length = endIndex - beginIndex;
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.at&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=nDodAvEl6NSdE3I9mS5x2mS-D8_ArWHAsLM6ywwHmV8&e=tributes
>  = attributes;
> -    }
> -
> -    private AttributedStringCharacterIterator(AttributedString 
> attributedString) {
> -        // TODO: maybe we should make a copy? instead of adding the 
> reference???
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage
>  = attributedString;
> -    }
> -
> -    // TODO: many more constructors needed, esp. those with attributes 
> already in place
> -
> -    public void addUnderlineAttribute(boolean underline) {
> -        addAttribute(TextAttribute.UNDERLINE,
> -            underline ? TextAttribute.UNDERLINE_ON 
> :https://urldefense.proofpoint.com/v2/url?u=http-3A__Integer.va&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=OMFuaAuw4os_NyXtfuol3MutMqvMbSyI6MMhcRLbIi0&e=lueOf(-1));
> -    }
> -
> -    public void addStrikethroughAttribute(boolean strikethrough) {
> -        
> addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28TextAttribute.ST&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=g8fV2gPPr-Adpj5t4oWbzb3pJvss9OOd5h0R0-10wH8&e=RIKETHROUGH,
> -            strikethrough 
> ?https://urldefense.proofpoint.com/v2/url?u=http-3A__TextAttribute.ST&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=lyG54zwCRtPo_FKazc4zyVxVPMG9_U0-E13opJbXt54&e=RIKETHROUGH_ON
>  : Boolean.FALSE);
> -    }
> -
> -    // TODO: do we need more parameters here?  for start position or 
> anything else?
> -    private AttributedCharacterIterator getIter() {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNullhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=YpZLlx-6xKGiLBeUZ7vPT-wTS_RI2MCek8N5rtfENxk&e=orage,
>  "source text");
> -
> -        if 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__-28this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=7OzRIXxxgBoK5dZiMzDIKsRPIuyp_E42POHSEk5ummo&e=erator
>  == null) {
> -            if 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__-28this.at&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=7sjC0OZiCj1d3yQWuVjYnJ70zpLnHF_7u0GBjgVx9sg&e=tributes
>  != null) {
> -               
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator
>  
> =https://urldefense.proofpoint.com/v2/url?u=http-3A__storage.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=B262-Lu3b45JYiq8JTQUUxRxxcQUV-HY_K0ExJ-3_QA&e=tIterator(attributes);
> -            } else {
> -               
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator
>  
> =https://urldefense.proofpoint.com/v2/url?u=http-3A__storage.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=B262-Lu3b45JYiq8JTQUUxRxxcQUV-HY_K0ExJ-3_QA&e=tIterator();
> -            }
> -        }
> -        
> returnhttps://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator;
> -    }
> -
> -    /**
> -     * Reset this iterator, meaning recreate the underlying iterator
> -     * on the next call.
> -     */
> -    public void reset() {
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator
>  = null;
> -    }
> -
> -    @Override
> -    public Set<Attribute> getAllAttributeKeys() {
> -        return getIter().getAllAttributeKeys();
> -    }
> -
> -    @Override
> -    public Object getAttribute(Attribute attribute) {
> -        return getIter().getAttribute(attribute);
> -    }
> -
> -    @Override
> -    public Map<Attribute, Object> getAttributes() {
> -        return getIter().getAttributes();
> -    }
> -
> -    @Override
> -    public int getRunLimit() {
> -        return getIter().getRunLimit();
> -    }
> -
> -    @Override
> -    public int getRunLimit(Attribute attribute) {
> -        return getIter().getRunLimit(attribute);
> -    }
> -
> -    @Override
> -    public int getRunLimit(Set<? extends Attribute> attributes) {
> -        return getIter().getRunLimit(attributes);
> -    }
> -
> -    @Override
> -    public int getRunStart() {
> -        return getIter().getRunStart();
> -    }
> -
> -    @Override
> -    public int getRunStart(Attribute attribute) {
> -        return getIter().getRunStart(attribute);
> -    }
> -
> -    @Override
> -    public int getRunStart(Set<? extends Attribute> attributes) {
> -        return getIter().getRunStart(attributes);
> -    }
> -
> -    @Override
> -    public char first() {
> -        return getIter().first();
> -    }
> -
> -    @Override
> -    public char last() {
> -        return getIter().last();
> -    }
> -
> -    @Override
> -    public char current() {
> -        return getIter().current();
> -    }
> -
> -    @Override
> -    public char next() {
> -        return getIter().next();
> -    }
> -
> -    @Override
> -    public char previous() {
> -        return getIter().previous();
> -    }
> -
> -    @Override
> -    public char setIndex(int position) {
> -        return getIter().setIndex(position);
> -    }
> -
> -    @Override
> -    public int getBeginIndex() {
> -        return getIter().getBeginIndex();
> -    }
> -
> -    @Override
> -    public int getEndIndex() {
> -        return getIter().getEndIndex();
> -    }
> -
> -    @Override
> -    public int getIndex() {
> -        return getIter().getIndex();
> -    }
> -
> -    @Override
> -    public Object clone() {
> -        AttributedStringCharacterIterator obj = new 
> AttributedStringCharacterIterator(this.storage);
> -        // Copy over the other fields
> -        obj.length = this.length;
> -        obj.attributes = this.attributes;
> -        return obj;
> -    }
> -
> -    @Override
> -    public String toString() {
> -        AttributedCharacterIterator iter = storage.getIterator();
> -        StringBuilder buf = new StringBuilder(iter.getEndIndex());
> -        char ch = iter.first();
> -        while (ch != DONE) {
> -            buf.append(ch);
> -            ch = iter.next();
> -        }
> -        return buf.toString();
> -    }
> -
> -}
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License,
> + * Version 2.0 (the "License"); you may not use this file except in
> + * compliance with the License.  You may obtain a copy of the License at
> + *
> + *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.pivot.text;
> +
> +import java.awt.Font;
> +import java.awt.font.TextAttribute;
> +import java.text.AttributedCharacterIterator;
> +import java.text.AttributedString;
> +import java.util.Map;
> +import java.util.Set;
> +import org.apache.pivot.util.Utils;
> +
> +
> +/**
> + * A sequence of text along with associated attributes, backed by a
> + * {@link AttributedString}, which itself implements all of these
> + * methods.
> + */
> +public class AttributedStringCharacterIterator implements 
> AttributedCharacterIterator {
> +    private AttributedString storage = null;
> +    private int length = 0;
> +    private AttributedCharacterIterator.Attribute[] attributes = null;
> +    private AttributedCharacterIterator iterator = null;
> +
> +    public AttributedStringCharacterIterator() {
> +        this.storage = new AttributedString("");
> +        this.length = 0;
> +    }
> +
> +    public AttributedStringCharacterIterator(String text) {
> +        Utils.checkNull(text, "text");
> +        this.storage = new AttributedString(text);
> +    }
> +
> +    private void addAttribute(AttributedCharacterIterator.Attribute 
> attribute, Object value) {
> +        if (this.length != 0) {
> +            this.storage.addAttribute(attribute, value);
> +        }
> +    }
> +
> +    public AttributedStringCharacterIterator(CharSequence charSequence, Font 
> font) {
> +        this.storage = new AttributedString(charSequence.toString());
> +        this.length = charSequence.length();
> +        addAttribute(TextAttribute.FONT, font);
> +    }
> +
> +    public AttributedStringCharacterIterator(CharSequence charSequence, int 
> beginIndex, Font font) {
> +        this.storage = new 
> AttributedString(charSequence.subSequence(beginIndex, 
> charSequence.length()).toString());
> +        this.length = charSequence.length() - beginIndex;
> +        addAttribute(TextAttribute.FONT, font);
> +    }
> +
> +    public AttributedStringCharacterIterator(String text, int beginIndex, 
> int endIndex) {
> +        Utils.checkNull(text, "text");
> +        this.storage = new AttributedString(text.substring(beginIndex, 
> endIndex));
> +        this.length = endIndex - beginIndex;
> +    }
> +
> +    public AttributedStringCharacterIterator(AttributedCharacterIterator 
> iter, int beginIndex, int endIndex) {
> +        this.storage = new AttributedString(iter, beginIndex, endIndex);
> +        this.length = endIndex - beginIndex;
> +    }
> +
> +    public AttributedStringCharacterIterator(String text, 
> AttributedCharacterIterator.Attribute[] attributes) {
> +        Utils.checkNull(text, "text");
> +        this.storage = new AttributedString(text);
> +        this.length = text.length();
> +        this.attributes = attributes;
> +    }
> +
> +    public AttributedStringCharacterIterator(String text, int beginIndex, 
> int endIndex,
> +        AttributedCharacterIterator.Attribute[] attributes) {
> +        Utils.checkNull(text, "text");
> +        this.storage = new AttributedString(text.substring(beginIndex, 
> endIndex));
> +        this.length = endIndex - beginIndex;
> +        this.attributes = attributes;
> +    }
> +
> +    private AttributedStringCharacterIterator(AttributedString 
> attributedString) {
> +        // TODO: maybe we should make a copy? instead of adding the 
> reference???
> +        this.storage = attributedString;
> +    }
> +
> +    // TODO: many more constructors needed, esp. those with attributes 
> already in place
> +
> +    public void addUnderlineAttribute(boolean underline) {
> +        addAttribute(TextAttribute.UNDERLINE,
> +            underline ? TextAttribute.UNDERLINE_ON : Integer.valueOf(-1));
> +    }
> +
> +    public void addStrikethroughAttribute(boolean strikethrough) {
> +        addAttribute(TextAttribute.STRIKETHROUGH,
> +            strikethrough ? TextAttribute.STRIKETHROUGH_ON : Boolean.FALSE);
> +    }
> +
> +    // TODO: do we need more parameters here?  for start position or 
> anything else?
> +    private AttributedCharacterIterator getIter() {
> +        Utils.checkNull(this.storage, "source text");
> +
> +        if (this.iterator == null) {
> +            if (this.attributes != null) {
> +                this.iterator = storage.getIterator(attributes);
> +            } else {
> +                this.iterator = storage.getIterator();
> +            }
> +        }
> +        return this.iterator;
> +    }
> +
> +    /**
> +     * Reset this iterator, meaning recreate the underlying iterator
> +     * on the next call.
> +     */
> +    public void reset() {
> +        this.iterator = null;
> +    }
> +
> +    @Override
> +    public Set<Attribute> getAllAttributeKeys() {
> +        return getIter().getAllAttributeKeys();
> +    }
> +
> +    @Override
> +    public Object getAttribute(Attribute attribute) {
> +        return getIter().getAttribute(attribute);
> +    }
> +
> +    @Override
> +    public Map<Attribute, Object> getAttributes() {
> +        return getIter().getAttributes();
> +    }
> +
> +    @Override
> +    public int getRunLimit() {
> +        return getIter().getRunLimit();
> +    }
> +
> +    @Override
> +    public int getRunLimit(Attribute attribute) {
> +        return getIter().getRunLimit(attribute);
> +    }
> +
> +    @Override
> +    public int getRunLimit(Set<? extends Attribute> attributes) {
> +        return getIter().getRunLimit(attributes);
> +    }
> +
> +    @Override
> +    public int getRunStart() {
> +        return getIter().getRunStart();
> +    }
> +
> +    @Override
> +    public int getRunStart(Attribute attribute) {
> +        return getIter().getRunStart(attribute);
> +    }
> +
> +    @Override
> +    public int getRunStart(Set<? extends Attribute> attributes) {
> +        return getIter().getRunStart(attributes);
> +    }
> +
> +    @Override
> +    public char first() {
> +        return getIter().first();
> +    }
> +
> +    @Override
> +    public char last() {
> +        return getIter().last();
> +    }
> +
> +    @Override
> +    public char current() {
> +        return getIter().current();
> +    }
> +
> +    @Override
> +    public char next() {
> +        return getIter().next();
> +    }
> +
> +    @Override
> +    public char previous() {
> +        return getIter().previous();
> +    }
> +
> +    @Override
> +    public char setIndex(int position) {
> +        return getIter().setIndex(position);
> +    }
> +
> +    @Override
> +    public int getBeginIndex() {
> +        return getIter().getBeginIndex();
> +    }
> +
> +    @Override
> +    public int getEndIndex() {
> +        return getIter().getEndIndex();
> +    }
> +
> +    @Override
> +    public int getIndex() {
> +        return getIter().getIndex();
> +    }
> +
> +    @Override
> +    public Object clone() {
> +        AttributedStringCharacterIterator obj = new 
> AttributedStringCharacterIterator(this.storage);
> +        // Copy over the other fields
> +        obj.length = this.length;
> +        obj.attributes = this.attributes;
> +        return obj;
> +    }
> +
> +    @Override
> +    public String toString() {
> +        AttributedCharacterIterator iter = storage.getIterator();
> +        StringBuilder buf = new StringBuilder(iter.getEndIndex());
> +        char ch = iter.first();
> +        while (ch != DONE) {
> +            buf.append(ch);
> +            ch = iter.next();
> +        }
> +        return buf.toString();
> +    }
> +
> +}
> 
> Propchange: 
> pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> Modified: pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java
> URL: 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_text_CharSpan.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=T7Qy0W3lp_zLJ3pp6AVKblacM8dpaWW6orjDZFoTPdI&e=
> ==============================================================================
> --- pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java (original)
> +++ pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java Tue Oct 31 
> 19:15:47 2023
> @@ -1,276 +1,276 @@
> -/*
> - * Licensed to the Apache Software Foundation (ASF) under one or more
> - * contributor license agreements.  See the NOTICE file distributed with
> - * this work for additional information regarding copyright ownership.
> - * The ASF licenses this file to you under the Apache License,
> - * Version 2.0 (the "License"); you may not use this file except in
> - * compliance with the License.  You may obtain a copy of the License at
> - *
> - *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -package org.apache.pivot.text;
> -
> -import org.apache.pivot.collections.Dictionary;
> -import org.apache.pivot.collections.Sequence;
> -import org.apache.pivot.json.JSONSerializer;
> -import org.apache.pivot.serialization.SerializationException;
> -import org.apache.pivot.util.Utils;
> -
> -/**
> - * Immutable class representing a span of characters. The range includes all 
> values
> - * in the interval <i><code>[start, start+length-1]</code></i> inclusive.  
> This is
> - * the paradigm used in a lot of places (notably the text controls) to 
> indicate a selection.
> - * <p> A zero-length span indicates a single caret position at the given 
> start.
> - * <p> Negative lengths are not supported and will throw exceptions, as will
> - * negative start positions.
> - */
> -public final class CharSpan {
> -    /** The starting location of this span (zero-based). */
> -    public final int start;
> -    /** The length of this span (non-negative). */
> -    public final int length;
> -
> -    /** The dictionary key used to retrieve the start location. */
> -    public static final String START_KEY = "start";
> -    /** The dictionary key used to retrieve the length. */
> -    public static final String LENGTH_KEY = "length";
> -
> -    /**
> -     * A span of length zero, starting at position zero.
> -     */
> -    public static final CharSpan ZERO = new CharSpan();
> -
> -
> -    /**
> -     * Construct a default span of length zero at location zero.
> -     */
> -    public CharSpan() {
> -        this(0);
> -    }
> -
> -    /**
> -     * Construct a new char span of length zero at the given location.
> -     *
> -     * @param startValue The start of this char span.
> -     * @throws IllegalArgumentException if the value is negative.
> -     */
> -    public CharSpan(final int startValue) {
> -        this(startValue, 0);
> -    }
> -
> -    /**
> -     * Construct a new char span with the given values.
> -     *
> -     * @param startValue The start of this char span.
> -     * @param lengthValue The length of this char span.
> -     * @throws IllegalArgumentException if either value is negative.
> -     */
> -    public CharSpan(final int startValue, final int lengthValue) {
> -        Utils.checkNonNegative(startValue, "start");
> -        Utils.checkNonNegative(lengthValue, "length");
> -
> -        start = startValue;
> -        length = lengthValue;
> -    }
> -
> -    /**
> -     * Construct a new char span from another one (a "copy constructor").
> -     *
> -     * @param existingCharSpan An existing char span (which must not be 
> {@code null}).
> -     * @throws IllegalArgumentException if the given char span is {@code 
> null}.
> -     */
> -    public CharSpan(final CharSpan existingCharSpan) {
> -        Utils.checkNull(existingCharSpan, "existingCharSpan");
> -
> -        start = existingCharSpan.start;
> -        length = existingCharSpan.length;
> -    }
> -
> -    /**
> -     * Construct a new char span from the given dictionary which must contain
> -     * the {@link #START_KEY} and can also contain the {@link #LENGTH_KEY} 
> key.
> -     *
> -     * @param charSpanDictionary A dictionary containing start and length 
> values.
> -     * @throws IllegalArgumentException if the given char span is {@code 
> null},
> -     * if the dictionary does not contain at least the start key, or if 
> either of
> -     * the dictionary values is negative.
> -     */
> -    public CharSpan(final Dictionary<String, ?> charSpanDictionary) {
> -        Utils.checkNull(charSpanDictionary, "charSpanDictionary");
> -
> -        int startValue;
> -        int lengthValue = 0;
> -
> -        if (charSpanDictionary.containsKey(START_KEY)) {
> -            startValue = charSpanDictionary.getInt(START_KEY);
> -            Utils.checkNonNegative(startValue, "start");
> -        } else {
> -            throw new IllegalArgumentException(START_KEY + " is required.");
> -        }
> -
> -        if (charSpanDictionary.containsKey(LENGTH_KEY)) {
> -            lengthValue = charSpanDictionary.getInt(LENGTH_KEY);
> -            Utils.checkNonNegative(lengthValue, "length");
> -        }
> -
> -        start = startValue;
> -        length = lengthValue;
> -    }
> -
> -    /**
> -     * Construct a new char span from the given sequence with two
> -     * numeric values corresponding to the start and length values
> -     * respectively, or one numeric value corresponding to the start
> -     * value (length 0).
> -     *
> -     * @param charSpanSequence A sequence containing the start and length 
> values.
> -     * @throws IllegalArgumentException if the given char span is {@code 
> null}, or
> -     * zero length, or length is greater than two.
> -     */
> -    public CharSpan(final Sequence<?> charSpanSequence) {
> -        Utils.checkNull(charSpanSequence, "charSpanSequence");
> -
> -        int startValue;
> -        int lengthValue = 0;
> -        int seqLength = charSpanSequence.getLength();
> -
> -        if (seqLength < 1 || seqLength > 2) {
> -            throw new IllegalArgumentException("CharSpan needs one or two 
> values in the sequence to construct.");
> -        }
> -
> -        startValue = ((Number) charSpanSequence.get(0)).intValue();
> -        Utils.checkNonNegative(startValue, "start");
> -
> -        if (seqLength == 2) {
> -            lengthValue = ((Number) charSpanSequence.get(1)).intValue();
> -            Utils.checkNonNegative(lengthValue, "length");
> -        }
> -
> -
> -        start = startValue;
> -        length = lengthValue;
> -    }
> -
> -    /**
> -     * Returns the inclusive end value of this char span, which is the
> -     * <code>start + length - 1</code>.  So, if the length is zero,
> -     * then the end will be less that the start.
> -     *
> -     * @return The computed inclusive end value of this char span.
> -     */
> -    public int getEnd() {
> -        return start + length - 1;
> -    }
> -
> -    /**
> -     * Returns a new {@link CharSpan} with the start value offset by the 
> given amount.
> -     *
> -     * @param offset The positive or negative amount by which to "move" this
> -     * char span (the start value).
> -     * @return A new {@link CharSpan} with the updated value.
> -     * @throws IllegalArgumentException if the updated start value goes 
> negative.
> -     */
> -    public CharSpan offset(final int offset) {
> -        return (offset == 0) ? this : new CharSpan(this.start + offset, 
> this.length);
> -    }
> -
> -    /**
> -     * Returns a new {@link CharSpan} with the length value offset by the 
> given amount
> -     * (either positive to lengthen the span or negative to shorten the 
> span).
> -     *
> -     * @param offset The positive or negative amount by which to "lengthen" 
> this
> -     * char span (the length value).
> -     * @return A new {@link CharSpan} with the updated value.
> -     * @throws IllegalArgumentException if the updated length value goes 
> negative.
> -     */
> -    public CharSpan lengthen(final int offset) {
> -        return (offset == 0) ? this : new CharSpan(this.start, this.length + 
> offset);
> -    }
> -
> -    @Override
> -    public boolean equals(final Object o) {
> -        boolean equal = false;
> -
> -        if (o == this) {
> -            return true;
> -        }
> -
> -        if (o instanceof CharSpan) {
> -            CharSpan span = (CharSpan) o;
> -            equal = (start == span.start && length == span.length);
> -        }
> -
> -        return equal;
> -    }
> -
> -    @Override
> -    public int hashCode() {
> -        return 31 * start + length;
> -    }
> -
> -    @Override
> -    public String toString() {
> -        return getClass().getSimpleName() + " {start:" + start + ", length:" 
> + length + "}";
> -    }
> -
> -    /**
> -     * Convert a string into a char span.
> -     * <p> If the string value is a JSON map, then parse the map
> -     * and construct using the {@link #CharSpan(Dictionary)} method.
> -     * <p> If the string value is a JSON list, then parse the list
> -     * and construct using the first two values as start and end
> -     * respectively, using the {@link #CharSpan(int, int)} constructor.
> -     * <p> Also accepted is a simple list of two integer values
> -     * separated by comma or semicolon.
> -     * <p> Otherwise the string should be a single integer value
> -     * that will be used to construct the char span using the {@link 
> #CharSpan(int)}
> -     * constructor (just the start value, with a zero length).
> -     *
> -     * @param value The string value to decode into a new char span.
> -     * @return The decoded char span.
> -     * @throws IllegalArgumentException if the value is {@code null} or 
> empty,
> -     * if the string starts with <code>"{"</code> but it cannot be parsed as
> -     * a JSON map, if it starts with <code>"["</code> but cannot be parsed
> -     * as a JSON list, or cannot be recognized as a simple list of one or
> -     * two integers.
> -     */
> -    public static CharSpan decode(final String value) {
> -        Utils.checkNullOrEmpty(value, "value");
> -
> -        CharSpan charSpan;
> -        if (value.startsWith("{")) {
> -            try {
> -                charSpan = new CharSpan(JSONSerializer.parseMap(value));
> -            } catch (SerializationException exception) {
> -                throw new IllegalArgumentException(exception);
> -            }
> -        } else if (value.startsWith("[")) {
> -            try {
> -                charSpan = new CharSpan(JSONSerializer.parseList(value));
> -            } catch (SerializationException exception) {
> -                throw new IllegalArgumentException(exception);
> -            }
> -        } else {
> -            String[] parts = value.split("\\s*[,;]\\s*");
> -            try {
> -                if (parts.length == 2) {
> -                    charSpan = new CharSpan(Integer.parseInt(parts[0]), 
> Integer.parseInt(parts[1]));
> -                } else if (parts.length == 1) {
> -                    charSpan = new CharSpan(Integer.parseInt(value));
> -                } else {
> -                    throw new IllegalArgumentException("Unknown format for 
> CharSpan: " + value);
> -                }
> -            } catch (NumberFormatException ex) {
> -                throw new IllegalArgumentException(ex);
> -            }
> -        }
> -
> -        return charSpan;
> -    }
> -}
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License,
> + * Version 2.0 (the "License"); you may not use this file except in
> + * compliance with the License.  You may obtain a copy of the License at
> + *
> + *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.pivot.text;
> +
> +import org.apache.pivot.collections.Dictionary;
> +import org.apache.pivot.collections.Sequence;
> +import org.apache.pivot.json.JSONSerializer;
> +import org.apache.pivot.serialization.SerializationException;
> +import org.apache.pivot.util.Utils;
> +
> +/**
> + * Immutable class representing a span of characters. The range includes all 
> values
> + * in the interval <i><code>[start, start+length-1]</code></i> inclusive.  
> This is
> + * the paradigm used in a lot of places (notably the text controls) to 
> indicate a selection.
> + * <p> A zero-length span indicates a single caret position at the given 
> start.
> + * <p> Negative lengths are not supported and will throw exceptions, as will
> + * negative start positions.
> + */
> +public final class CharSpan {
> +    /** The starting location of this span (zero-based). */
> +    public final int start;
> +    /** The length of this span (non-negative). */
> +    public final int length;
> +
> +    /** The dictionary key used to retrieve the start location. */
> +    public static final String START_KEY = "start";
> +    /** The dictionary key used to retrieve the length. */
> +    public static final String LENGTH_KEY = "length";
> +
> +    /**
> +     * A span of length zero, starting at position zero.
> +     */
> +    public static final CharSpan ZERO = new CharSpan();
> +
> +
> +    /**
> +     * Construct a default span of length zero at location zero.
> +     */
> +    public CharSpan() {
> +        this(0);
> +    }
> +
> +    /**
> +     * Construct a new char span of length zero at the given location.
> +     *
> +     * @param startValue The start of this char span.
> +     * @throws IllegalArgumentException if the value is negative.
> +     */
> +    public CharSpan(final int startValue) {
> +        this(startValue, 0);
> +    }
> +
> +    /**
> +     * Construct a new char span with the given values.
> +     *
> +     * @param startValue The start of this char span.
> +     * @param lengthValue The length of this char span.
> +     * @throws IllegalArgumentException if either value is negative.
> +     */
> +    public CharSpan(final int startValue, final int lengthValue) {
> +        Utils.checkNonNegative(startValue, "start");
> +        Utils.checkNonNegative(lengthValue, "length");
> +
> +        start = startValue;
> +        length = lengthValue;
> +    }
> +
> +    /**
> +     * Construct a new char span from another one (a "copy constructor").
> +     *
> +     * @param existingCharSpan An existing char span (which must not be 
> {@code null}).
> +     * @throws IllegalArgumentException if the given char span is {@code 
> null}.
> +     */
> +    public CharSpan(final CharSpan existingCharSpan) {
> +        Utils.checkNull(existingCharSpan, "existingCharSpan");
> +
> +        start = existingCharSpan.start;
> +        length = existingCharSpan.length;
> +    }
> +
> +    /**
> +     * Construct a new char span from the given dictionary which must contain
> +     * the {@link #START_KEY} and can also contain the {@link #LENGTH_KEY} 
> key.
> +     *
> +     * @param charSpanDictionary A dictionary containing start and length 
> values.
> +     * @throws IllegalArgumentException if the given char span is {@code 
> null},
> +     * if the dictionary does not contain at least the start key, or if 
> either of
> +     * the dictionary values is negative.
> +     */
> +    public CharSpan(final Dictionary<String, ?> charSpanDictionary) {
> +        Utils.checkNull(charSpanDictionary, "charSpanDictionary");
> +
> +        int startValue;
> +        int lengthValue = 0;
> +
> +        if (charSpanDictionary.containsKey(START_KEY)) {
> +            startValue = charSpanDictionary.getInt(START_KEY);
> +            Utils.checkNonNegative(startValue, "start");
> +        } else {
> +            throw new IllegalArgumentException(START_KEY + " is required.");
> +        }
> +
> +        if (charSpanDictionary.containsKey(LENGTH_KEY)) {
> +            lengthValue = charSpanDictionary.getInt(LENGTH_KEY);
> +            Utils.checkNonNegative(lengthValue, "length");
> +        }
> +
> +        start = startValue;
> +        length = lengthValue;
> +    }
> +
> +    /**
> +     * Construct a new char span from the given sequence with two
> +     * numeric values corresponding to the start and length values
> +     * respectively, or one numeric value corresponding to the start
> +     * value (length 0).
> +     *
> +     * @param charSpanSequence A sequence containing the start and length 
> values.
> +     * @throws IllegalArgumentException if the given char span is {@code 
> null}, or
> +     * zero length, or length is greater than two.
> +     */
> +    public CharSpan(final Sequence<?> charSpanSequence) {
> +        Utils.checkNull(charSpanSequence, "charSpanSequence");
> +
> +        int startValue;
> +        int lengthValue = 0;
> +        int seqLength = charSpanSequence.getLength();
> +
> +        if (seqLength < 1 || seqLength > 2) {
> +            throw new IllegalArgumentException("CharSpan needs one or two 
> values in the sequence to construct.");
> +        }
> +
> +        startValue = ((Number) charSpanSequence.get(0)).intValue();
> +        Utils.checkNonNegative(startValue, "start");
> +
> +        if (seqLength == 2) {
> +            lengthValue = ((Number) charSpanSequence.get(1)).intValue();
> +            Utils.checkNonNegative(lengthValue, "length");
> +        }
> +
> +
> +        start = startValue;
> +        length = lengthValue;
> +    }
> +
> +    /**
> +     * Returns the inclusive end value of this char span, which is the
> +     * <code>start + length - 1</code>.  So, if the length is zero,
> +     * then the end will be less that the start.
> +     *
> +     * @return The computed inclusive end value of this char span.
> +     */
> +    public int getEnd() {
> +        return start + length - 1;
> +    }
> +
> +    /**
> +     * Returns a new {@link CharSpan} with the start value offset by the 
> given amount.
> +     *
> +     * @param offset The positive or negative amount by which to "move" this
> +     * char span (the start value).
> +     * @return A new {@link CharSpan} with the updated value.
> +     * @throws IllegalArgumentException if the updated start value goes 
> negative.
> +     */
> +    public CharSpan offset(final int offset) {
> +        return (offset == 0) ? this : new CharSpan(this.start + offset, 
> this.length);
> +    }
> +
> +    /**
> +     * Returns a new {@link CharSpan} with the length value offset by the 
> given amount
> +     * (either positive to lengthen the span or negative to shorten the 
> span).
> +     *
> +     * @param offset The positive or negative amount by which to "lengthen" 
> this
> +     * char span (the length value).
> +     * @return A new {@link CharSpan} with the updated value.
> +     * @throws IllegalArgumentException if the updated length value goes 
> negative.
> +     */
> +    public CharSpan lengthen(final int offset) {
> +        return (offset == 0) ? this : new CharSpan(this.start, this.length + 
> offset);
> +    }
> +
> +    @Override
> +    public boolean equals(final Object o) {
> +        boolean equal = false;
> +
> +        if (o == this) {
> +            return true;
> +        }
> +
> +        if (o instanceof CharSpan) {
> +            CharSpan span = (CharSpan) o;
> +            equal = (start == span.start && length == span.length);
> +        }
> +
> +        return equal;
> +    }
> +
> +    @Override
> +    public int hashCode() {
> +        return 31 * start + length;
> +    }
> +
> +    @Override
> +    public String toString() {
> +        return getClass().getSimpleName() + " {start:" + start + ", length:" 
> + length + "}";
> +    }
> +
> +    /**
> +     * Convert a string into a char span.
> +     * <p> If the string value is a JSON map, then parse the map
> +     * and construct using the {@link #CharSpan(Dictionary)} method.
> +     * <p> If the string value is a JSON list, then parse the list
> +     * and construct using the first two values as start and end
> +     * respectively, using the {@link #CharSpan(int, int)} constructor.
> +     * <p> Also accepted is a simple list of two integer values
> +     * separated by comma or semicolon.
> +     * <p> Otherwise the string should be a single integer value
> +     * that will be used to construct the char span using the {@link 
> #CharSpan(int)}
> +     * constructor (just the start value, with a zero length).
> +     *
> +     * @param value The string value to decode into a new char span.
> +     * @return The decoded char span.
> +     * @throws IllegalArgumentException if the value is {@code null} or 
> empty,
> +     * if the string starts with <code>"{"</code> but it cannot be parsed as
> +     * a JSON map, if it starts with <code>"["</code> but cannot be parsed
> +     * as a JSON list, or cannot be recognized as a simple list of one or
> +     * two integers.
> +     */
> +    public static CharSpan decode(final String value) {
> +        Utils.checkNullOrEmpty(value, "value");
> +
> +        CharSpan charSpan;
> +        if (value.startsWith("{")) {
> +            try {
> +                charSpan = new CharSpan(JSONSerializer.parseMap(value));
> +            } catch (SerializationException exception) {
> +                throw new IllegalArgumentException(exception);
> +            }
> +        } else if (value.startsWith("[")) {
> +            try {
> +                charSpan = new CharSpan(JSONSerializer.parseList(value));
> +            } catch (SerializationException exception) {
> +                throw new IllegalArgumentException(exception);
> +            }
> +        } else {
> +            String[] parts = value.split("\\s*[,;]\\s*");
> +            try {
> +                if (parts.length == 2) {
> +                    charSpan = new CharSpan(Integer.parseInt(parts[0]), 
> Integer.parseInt(parts[1]));
> +                } else if (parts.length == 1) {
> +                    charSpan = new CharSpan(Integer.parseInt(value));
> +                } else {
> +                    throw new IllegalArgumentException("Unknown format for 
> CharSpan: " + value);
> +                }
> +            } catch (NumberFormatException ex) {
> +                throw new IllegalArgumentException(ex);
> +            }
> +        }
> +
> +        return charSpan;
> +    }
> +}
> 
> Propchange: pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> Modified: pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java
> URL: 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_text_CompositeIterator.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=w5owCLsGtIHES9QK3uXCyAjUMFfOde0zJhf1TPWOHE4&e=
> ==============================================================================
> --- pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java 
> (original)
> +++ pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java Tue Oct 
> 31 19:15:47 2023
> @@ -1,185 +1,185 @@
> -/*
> - * Licensed to the Apache Software Foundation (ASF) under one or more
> - * contributor license agreements.  See the NOTICE file distributed with
> - * this work for additional information regarding copyright ownership.
> - * The ASF licenses this file to you under the Apache License,
> - * Version 2.0 (the "License"); you may not use this file except in
> - * compliance with the License.  You may obtain a copy of the License at
> - *
> - *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -package org.apache.pivot.text;
> -
> -import java.text.AttributedCharacterIterator;
> -import java.util.HashSet;
> -import java.util.Map;
> -import java.util.Set;
> -import org.apache.pivot.collections.ArrayList;
> -import org.apache.pivot.collections.List;
> -import org.apache.pivot.util.Utils;
> -
> -
> -/**
> - * An {@link AttributedCharacterIterator} that implements iterating over
> - * several (typically two or three) underlying iterators.  The assumption
> - * is that no attributes will ever cross the underlying iterator boundaries
> - * (which is always the case for insertion of composed but uncommitted text
> - * in the middle of two pieces of committed text (for instance).
> - */
> -public class CompositeIterator implements AttributedCharacterIterator {
> -
> -    private List<AttributedCharacterIterator> iterators = new ArrayList<>();
> -    private int endIndex;
> -    private int currentIndex;
> -    private AttributedCharacterIterator currentIterator;
> -    private int currentIteratorDelta;
> -
> -    /**
> -     * Constructs a CompositeIterator that iterates over the concatenation
> -     * of one or more iterators.
> -     * @param iterators The base iterators that this composite iterator 
> concatenates.
> -     */
> -    public CompositeIterator(AttributedCharacterIterator... iterators) {
> -        int fullLength = 0;
> -        for (AttributedCharacterIterator iter : iterators) {
> -            int beginIndex = iter.getBeginIndex();    // inclusive
> -            int endIndex   = iter.getEndIndex();      // exclusive
> -            int range = (endIndex - beginIndex);
> -            this.iterators.add(iter);
> -            fullLength += range;
> -        }
> -        this.endIndex = fullLength;
> -        setIndex0(0);
> -    }
> -
> -    // CharacterIterator implementations
> -
> -    public char first() {
> -        return setIndex0(0);
> -    }
> -
> -    public char last() {
> -        if (endIndex == 0) {
> -            return setIndex0(endIndex);
> -        } else {
> -            return setIndex0(endIndex - 1);
> -        }
> -    }
> -
> -    public char next() {
> -        if (currentIndex < endIndex) {
> -            return setIndex0(currentIndex + 1);
> -        } else {
> -            return DONE;
> -        }
> -    }
> -
> -    public char previous() {
> -        if (currentIndex > 0) {
> -            return setIndex0(currentIndex - 1);
> -        } else {
> -            return DONE;
> -        }
> -    }
> -
> -    public char current() {
> -        return currentIterator.setIndex(currentIndex - currentIteratorDelta);
> -    }
> -
> -    public char setIndex(int position) {
> -        // Note: this is a (0 < position <= endIndex) check, since 
> "endIndex" is a valid value here
> -       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckIndexBounds(position,
>  0, endIndex);
> -
> -        return setIndex0(position);
> -    }
> -
> -    private char setIndex0(int position) {
> -        currentIndex = position;
> -        int cumLength = 0;
> -        for (AttributedCharacterIterator iter : iterators) {
> -            int beginIndex 
> =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tBeginIndex();
> -            int endIndex   
> =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tEndIndex();
> -            int range = endIndex - beginIndex;
> -            if (currentIndex < endIndex + cumLength) {
> -                currentIterator = iter;
> -                currentIteratorDelta = beginIndex + cumLength;
> -                // TODO: not sure this is going to be correct for > 2 
> iterators
> -                return currentIterator.setIndex(currentIndex - 
> currentIteratorDelta);
> -            }
> -            cumLength += range;
> -        }
> -        return DONE;
> -    }
> -
> -    public int getBeginIndex() {
> -        return 0;
> -    }
> -
> -    public int getEndIndex() {
> -        return endIndex;
> -    }
> -
> -    public int getIndex() {
> -        return currentIndex;
> -    }
> -
> -    // AttributedCharacterIterator implementations
> -
> -    public int getRunStart() {
> -        return currentIterator.getRunStart() + currentIteratorDelta;
> -    }
> -
> -    public int getRunLimit() {
> -        return currentIterator.getRunLimit() + currentIteratorDelta;
> -    }
> -
> -    public int getRunStart(Attribute attribute) {
> -        return currentIterator.getRunStart(attribute) + currentIteratorDelta;
> -    }
> -
> -    public int getRunLimit(Attribute attribute) {
> -        return currentIterator.getRunLimit(attribute) + currentIteratorDelta;
> -    }
> -
> -    public int getRunStart(Set<? extends Attribute> attributes) {
> -        return currentIterator.getRunStart(attributes) + 
> currentIteratorDelta;
> -    }
> -
> -    public int getRunLimit(Set<? extends Attribute> attributes) {
> -        return currentIterator.getRunLimit(attributes) + 
> currentIteratorDelta;
> -    }
> -
> -    public Map<Attribute, Object> getAttributes() {
> -        return currentIterator.getAttributes();
> -    }
> -
> -    public Set<Attribute> getAllAttributeKeys() {
> -        Set<Attribute> keys = new HashSet<>();
> -        for (AttributedCharacterIterator iter : iterators) {
> -            keys.addAll(iter.getAllAttributeKeys());
> -        }
> -        return keys;
> -    }
> -
> -    public Object getAttribute(Attribute attribute) {
> -        return currentIterator.getAttribute(attribute);
> -    }
> -
> -    // Object implementations
> -
> -    public Object clone() {
> -        try {
> -            CompositeIterator other = (CompositeIterator) super.clone();
> -            return other;
> -        } catch (CloneNotSupportedException e) {
> -            throw new InternalError();
> -        }
> -    }
> -
> -}
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License,
> + * Version 2.0 (the "License"); you may not use this file except in
> + * compliance with the License.  You may obtain a copy of the License at
> + *
> + *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.pivot.text;
> +
> +import java.text.AttributedCharacterIterator;
> +import java.util.HashSet;
> +import java.util.Map;
> +import java.util.Set;
> +import org.apache.pivot.collections.ArrayList;
> +import org.apache.pivot.collections.List;
> +import org.apache.pivot.util.Utils;
> +
> +
> +/**
> + * An {@link AttributedCharacterIterator} that implements iterating over
> + * several (typically two or three) underlying iterators.  The assumption
> + * is that no attributes will ever cross the underlying iterator boundaries
> + * (which is always the case for insertion of composed but uncommitted text
> + * in the middle of two pieces of committed text (for instance).
> + */
> +public class CompositeIterator implements AttributedCharacterIterator {
> +
> +    private List<AttributedCharacterIterator> iterators = new ArrayList<>();
> +    private int endIndex;
> +    private int currentIndex;
> +    private AttributedCharacterIterator currentIterator;
> +    private int currentIteratorDelta;
> +
> +    /**
> +     * Constructs a CompositeIterator that iterates over the concatenation
> +     * of one or more iterators.
> +     * @param iterators The base iterators that this composite iterator 
> concatenates.
> +     */
> +    public CompositeIterator(AttributedCharacterIterator... iterators) {
> +        int fullLength = 0;
> +        for (AttributedCharacterIterator iter : iterators) {
> +            int beginIndex = iter.getBeginIndex();    // inclusive
> +            int endIndex   = iter.getEndIndex();      // exclusive
> +            int range = (endIndex - beginIndex);
> +            this.iterators.add(iter);
> +            fullLength += range;
> +        }
> +        this.endIndex = fullLength;
> +        setIndex0(0);
> +    }
> +
> +    // CharacterIterator implementations
> +
> +    public char first() {
> +        return setIndex0(0);
> +    }
> +
> +    public char last() {
> +        if (endIndex == 0) {
> +            return setIndex0(endIndex);
> +        } else {
> +            return setIndex0(endIndex - 1);
> +        }
> +    }
> +
> +    public char next() {
> +        if (currentIndex < endIndex) {
> +            return setIndex0(currentIndex + 1);
> +        } else {
> +            return DONE;
> +        }
> +    }
> +
> +    public char previous() {
> +        if (currentIndex > 0) {
> +            return setIndex0(currentIndex - 1);
> +        } else {
> +            return DONE;
> +        }
> +    }
> +
> +    public char current() {
> +        return currentIterator.setIndex(currentIndex - currentIteratorDelta);
> +    }
> +
> +    public char setIndex(int position) {
> +        // Note: this is a (0 < position <= endIndex) check, since 
> "endIndex" is a valid value here
> +       
> https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckIndexBounds(position,
>  0, endIndex);
> +
> +        return setIndex0(position);
> +    }
> +
> +    private char setIndex0(int position) {
> +        currentIndex = position;
> +        int cumLength = 0;
> +        for (AttributedCharacterIterator iter : iterators) {
> +            int beginIndex 
> =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tBeginIndex();
> +            int endIndex   
> =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tEndIndex();
> +            int range = endIndex - beginIndex;
> +            if (currentIndex < endIndex + cumLength) {
> +                currentIterator = iter;
> +                currentIteratorDelta = beginIndex + cumLength;
> +                // TODO: not sure this is going to be correct for > 2 
> iterators
> +                return currentIterator.setIndex(currentIndex - 
> currentIteratorDelta);
> +            }
> +            cumLength += range;
> +        }
> +        return DONE;
> +    }
> +
> +    public int getBeginIndex() {
> +        return 0;
> +    }
> +
> +    public int getEndIndex() {
> +        return endIndex;
> +    }
> +
> +    public int getIndex() {
> +        return currentIndex;
> +    }
> +
> +    // AttributedCharacterIterator implementations
> +
> +    public int getRunStart() {
> +        return currentIterator.getRunStart() + currentIteratorDelta;
> +    }
> +
> +    public int getRunLimit() {
> +        return currentIterator.getRunLimit() + currentIteratorDelta;
> +    }
> +
> +    public int getRunStart(Attribute attribute) {
> +        return currentIterator.getRunStart(attribute) + currentIteratorDelta;
> +    }
> +
> +    public int getRunLimit(Attribute attribute) {
> +        return currentIterator.getRunLimit(attribute) + currentIteratorDelta;
> +    }
> +
> +    public int getRunStart(Set<? extends Attribute> attributes) {
> +        return currentIterator.getRunStart(attributes) + 
> currentIteratorDelta;
> +    }
> +
> +    public int getRunLimit(Set<? extends Attribute> attributes) {
> +        return currentIterator.getRunLimit(attributes) + 
> currentIteratorDelta;
> +    }
> +
> +    public Map<Attribute, Object> getAttributes() {
> +        return currentIterator.getAttributes();
> +    }
> +
> +    public Set<Attribute> getAllAttributeKeys() {
> +        Set<Attribute> keys = new HashSet<>();
> +        for (AttributedCharacterIterator iter : iterators) {
> +            keys.addAll(iter.getAllAttributeKeys());
> +        }
> +        return keys;
> +    }
> +
> +    public Object getAttribute(Attribute attribute) {
> +        return currentIterator.getAttribute(attribute);
> +    }
> +
> +    // Object implementations
> +
> +    public Object clone() {
> +        try {
> +            CompositeIterator other = (CompositeIterator) super.clone();
> +            return other;
> +        } catch (CloneNotSupportedException e) {
> +            throw new InternalError();
> +        }
> +    }
> +
> +}
> 
> Propchange: pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> Modified: pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java
> URL: 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_util_BooleanResult.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gH8zl1jumjR4HHfUldD3HkLa_CByMFcE1oWzv77YYfk&e=
> ==============================================================================
> --- pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java (original)
> +++ pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java Tue Oct 31 
> 19:15:47 2023
> @@ -1,108 +1,108 @@
> -/*
> - * Licensed to the Apache Software Foundation (ASF) under one or more
> - * contributor license agreements.  See the NOTICE file distributed with
> - * this work for additional information regarding copyright ownership.
> - * The ASF licenses this file to you under the Apache License,
> - * Version 2.0 (the "License"); you may not use this file except in
> - * compliance with the License.  You may obtain a copy of the License at
> - *
> - *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -package org.apache.pivot.util;
> -
> -/**
> - * An object holding a boolean value that can be used with a {@code forEach}
> - * or lambda expressionm, where the value used during the iteration must be
> - * final or effectively final.
> - */
> -public class BooleanResult {
> -    /**
> -     * The current boolean value.
> -     */
> -    private boolean result;
> -
> -    /**
> -     * Construct one of these and set the initial value to the given value.
> -     *
> -     * @param initialValue The initial boolean value.
> -     */
> -    public BooleanResult(final boolean initialValue) {
> -        result = initialValue;
> -    }
> -
> -    /**
> -     * Construct one of these and set the initial boolean value to
> -     * {@code false}.
> -     */
> -    public BooleanResult() {
> -        this(false);
> -    }
> -
> -    /**
> -     * Update the saved value by <code>OR</code>ing this new value
> -     * with the saved value.
> -     *
> -     * @param value The new value to OR into the saved one.
> -     */
> -    public void or(final boolean value) {
> -        result |= value;
> -    }
> -
> -    /**
> -     * Update the saved value by <code>AND</code>ing this new value
> -     * with the saved value.
> -     *
> -     * @param value The new value to AND into the saved one.
> -     */
> -    public void and(final boolean value) {
> -        result &= value;
> -    }
> -
> -    /**
> -     * Update the saved value by <code>XOR</code>ing this new value
> -     * with the saved value.
> -     *
> -     * @param value The new value to XOR into the saved one.
> -     */
> -    public void xor(final boolean value) {
> -        result ^= value;
> -    }
> -
> -    /**
> -     * Negate the saved value.
> -     */
> -    public void not() {
> -        result = !result;
> -    }
> -
> -    /**
> -     * Clear the boolean result to the default value
> -     * of {@code false}.
> -     */
> -    public void clear() {
> -        result = false;
> -    }
> -
> -    /**
> -     * Set the result value to the given value.
> -     *
> -     * @param value The new value to set.
> -     */
> -    public void set(final boolean value) {
> -        result = value;
> -    }
> -
> -    /**
> -     * @return The final boolean value.
> -     */
> -    public boolean get() {
> -        return result;
> -    }
> -
> -}
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License,
> + * Version 2.0 (the "License"); you may not use this file except in
> + * compliance with the License.  You may obtain a copy of the License at
> + *
> + *     
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e=
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.pivot.util;
> +
> +/**
> + * An object holding a boolean value that can be used with a {@code forEach}
> + * or lambda expressionm, where the value used during the iteration must be
> + * final or effectively final.
> + */
> +public class BooleanResult {
> +    /**
> +     * The current boolean value.
> +     */
> +    private boolean result;
> +
> +    /**
> +     * Construct one of these and set the initial value to the given value.
> +     *
> +     * @param initialValue The initial boolean value.
> +     */
> +    public BooleanResult(final boolean initialValue) {
> +        result = initialValue;
> +    }
> +
> +    /**
> +     * Construct one of these and set the initial boolean value to
> +     * {@code false}.
> +     */
> +    public BooleanResult() {
> +        this(false);
> +    }
> +
> +    /**
> +     * Update the saved value by <code>OR</code>ing this new value
> +     * with the saved value.
> +     *
> +     * @param value The new value to OR into the saved one.
> +     */
> +    public void or(final boolean value) {
> +        result |= value;
> +    }
> +
> +    /**
> +     * Update the saved value by <code>AND</code>ing this new value
> +     * with the saved value.
> +     *
> +     * @param value The new value to AND into the saved one.
> +     */
> +    public void and(final boolean value) {
> +        result &= value;
> +    }
> +
> +    /**
> +     * Update the saved value by <code>XOR</code>ing this new value
> +     * with the saved value.
> +     *
> +     * @param value The new value to XOR into the saved one.
> +     */
> +    public void xor(final boolean value) {
> +        result ^= value;
> +    }
> +
> +    /**
> +     * Negate the saved value.
> +     */
> +    public void not() {
> +        result = !result;
> +    }
> +
> +    /**
> +     * Clear the boolean result to the default value
> +     * of {@code false}.
> +     */
> +    public void clear() {
> +        result = false;
> +    }
> +
> +    /**
> +     * Set the result value to the given value.
> +     *
> +     * @param value The new value to set.
> +     */
> +    public void set(final boolean value) {
> +        result = value;
> +    }
> +
> +    /**
> +     * @return The final boolean value.
> +     */
> +    public boolean get() {
> +        return result;
> +    }
> +
> +}
> 
> Propchange: pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> 

Reply via email to