/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

package com.pullenti.unitext.internal.rtf;

/**
 * Простейший элемент структуры файла RTF
 */
public class RtfItem {

    public RftItemTyp typ = RftItemTyp.UNDEFINED;

    public String text;

    public byte[] codes;

    public int level;

    @Override
    public String toString() {
        if (typ == RftItemTyp.BRACKETOPEN) 
            return (((Integer)level).toString() + ": {");
        if (typ == RftItemTyp.BRACKETCLOSE) 
            return (((Integer)level).toString() + ": }");
        if (typ == RftItemTyp.COMMAND) 
            return (((Integer)level).toString() + ": \\" + ((text != null ? text : "")));
        if (typ == RftItemTyp.IMAGE) 
            return (((Integer)level).toString() + ": Image " + ((text != null ? text : "")) + ": Len=" + codes.length);
        if (typ == RftItemTyp.TEXT) {
            if (text != null) 
                return (((Integer)level).toString() + ": [" + text.length() + "] '" + (text.length() > 200 ? text.substring(0, 0 + 200) : text) + "'");
            if (codes != null) {
                StringBuilder tmp = new StringBuilder();
                tmp.append(level).append(": [").append(codes.length).append("]");
                for (byte c : codes) {
                    tmp.append("'").append(String.format("%02X", Byte.toUnsignedInt(c))).append("' ");
                    if (tmp.length() > 200) {
                        tmp.append("...");
                        break;
                    }
                }
                return tmp.toString();
            }
        }
        return "?";
    }

    public static class RftCommand {
    
        public String command;
    
        public byte charCode;
    
        public char pureChar;
    
        public byte[] pictContent;
    
        public int picWidth;
    
        public int picHeight;
    
        private RftCommand m_TempCmd;
    
        public boolean parse(com.pullenti.unisharp.Stream stream) throws java.io.IOException {
            command = null;
            charCode = (byte)0;
            pureChar = (char)0;
            pictContent = null;
            int i = stream.read();
            if (i < 0) 
                return false;
            char ch = (char)i;
            if (ch == '\'') {
                byte[] buf = new byte[2];
                if (stream.read(buf, 0, 2) != 2) 
                    return false;
                for (i = 0; i < 2; i++) {
                    ch = (char)buf[i];
                    if (ch >= '0' && ch <= '9') 
                        buf[i] = (byte)((((int)ch) - ((int)'0')));
                    else if (ch >= 'a' && ch <= 'f') 
                        buf[i] = (byte)(((((int)ch) - ((int)'a')) + 10));
                    else if (ch >= 'A' && ch <= 'F') 
                        buf[i] = (byte)(((((int)ch) - ((int)'A')) + 10));
                    else 
                        return false;
                }
                charCode = (byte)((((Byte.toUnsignedInt(buf[0])) << 4) | (Byte.toUnsignedInt(buf[1]))));
                return true;
            }
            if (ch == 'u') {
                int cod = 0;
                i = stream.read();
                if (i < 0) 
                    return false;
                char ch1 = (char)i;
                if (Character.isDigit(ch1)) {
                    cod = (((int)ch1) - ((int)'0'));
                    while (true) {
                        i = stream.read();
                        if (i < 0) 
                            break;
                        ch1 = (char)i;
                        if (Character.isDigit(ch1)) 
                            cod = (cod * 10) + ((((int)ch1) - ((int)'0')));
                        else {
                            if (ch1 == '\\') 
                                stream.setPosition(stream.getPosition() - (1L));
                            break;
                        }
                    }
                    pureChar = (char)cod;
                    if (m_TempCmd == null) 
                        m_TempCmd = new RftCommand();
                    if (ch1 == '\\') {
                        long pos = stream.getPosition();
                        stream.setPosition(stream.getPosition() + (1L));
                        m_TempCmd.parse(stream);
                        if (m_TempCmd.charCode != ((byte)0)) {
                        }
                        else 
                            stream.setPosition(pos);
                    }
                    return true;
                }
                else 
                    stream.setPosition(stream.getPosition() - (1L));
            }
            if ("{}\\".indexOf(ch) >= 0) {
                pureChar = ch;
                return true;
            }
            if (((int)ch) == 0xD || ((int)ch) == 0xA) {
                pureChar = '\n';
                return true;
            }
            StringBuilder cmd = new StringBuilder();
            cmd.append(ch);
            if (ch != '*') {
                while (true) {
                    if (cmd.length() == 1) {
                        if (ch == '~' || ch == '_') 
                            break;
                    }
                    i = stream.read();
                    if (i < 0) 
                        break;
                    ch = (char)i;
                    if ((ch == '\\' || ch == '}' || ch == '{') || i >= 0x80) {
                        stream.setPosition(stream.getPosition() - (1L));
                        break;
                    }
                    if (com.pullenti.unisharp.Utils.isWhitespace(ch)) 
                        break;
                    cmd.append(ch);
                }
            }
            command = cmd.toString();
            if (com.pullenti.unisharp.Utils.stringsEq(command, "tab")) 
                pureChar = '\t';
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "emdash")) 
                pureChar = (char)0x2014;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "endash")) 
                pureChar = (char)0x2013;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "emspace") || com.pullenti.unisharp.Utils.stringsEq(command, "enspace") || com.pullenti.unisharp.Utils.stringsEq(command, "~")) 
                pureChar = ' ';
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "bullet")) 
                pureChar = (char)0x2022;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "lquote")) 
                pureChar = (char)0x2018;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "rquote")) 
                pureChar = (char)0x2019;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "ldblquote")) 
                pureChar = (char)0x201C;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "rdblquote")) 
                pureChar = (char)0x201D;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "lquote")) 
                pureChar = (char)0x2018;
            else if (com.pullenti.unisharp.Utils.stringsEq(command, "_")) 
                pureChar = '-';
            else if (command.length() > 2 && command.charAt(0) == 'u' && Character.isDigit(command.charAt(1))) {
                com.pullenti.unisharp.Outargwrapper<Integer> wrapi290 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                boolean inoutres291 = com.pullenti.unisharp.Utils.parseInteger(command.substring(1), 0, null, wrapi290);
                i = (wrapi290.value != null ? wrapi290.value : 0);
                if (inoutres291) {
                    pureChar = (char)i;
                    return true;
                }
            }
            if ((command.startsWith("colortbl") || command.startsWith("info") || command.startsWith("object")) || command.startsWith("pict") || command.startsWith("themedata")) {
                int lev = 0;
                boolean isPict = command.startsWith("pict") || command.startsWith("object");
                RftCommand pictComm = new RftCommand();
                StringBuilder hexVal = new StringBuilder();
                int picW = 0;
                int picGoalW = 0;
                int picH = 0;
                int picGoalH = 0;
                int scalx = 100;
                int scaly = 100;
                while (true) {
                    i = stream.read();
                    if (i < 0) 
                        break;
                    ch = (char)i;
                    if (ch == '}') {
                        if (lev == 0) {
                            stream.setPosition(stream.getPosition() - (1L));
                            break;
                        }
                        else 
                            lev--;
                    }
                    else if (ch == '{') 
                        lev++;
                    else if (ch == '\\') {
                        if (pictComm.parse(stream)) {
                            if (pictComm.command != null) {
                                if (pictComm.command.startsWith("picwgoal")) {
                                    com.pullenti.unisharp.Outargwrapper<Integer> wrappicGoalW292 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                                    com.pullenti.unisharp.Utils.parseInteger(pictComm.command.substring(8), 0, null, wrappicGoalW292);
                                    picGoalW = (wrappicGoalW292.value != null ? wrappicGoalW292.value : 0);
                                }
                                else if (pictComm.command.startsWith("pichgoal")) {
                                    com.pullenti.unisharp.Outargwrapper<Integer> wrappicGoalH293 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                                    com.pullenti.unisharp.Utils.parseInteger(pictComm.command.substring(8), 0, null, wrappicGoalH293);
                                    picGoalH = (wrappicGoalH293.value != null ? wrappicGoalH293.value : 0);
                                }
                                else if (pictComm.command.startsWith("picw") || pictComm.command.startsWith("objw")) {
                                    com.pullenti.unisharp.Outargwrapper<Integer> wrappicW294 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                                    com.pullenti.unisharp.Utils.parseInteger(pictComm.command.substring(4), 0, null, wrappicW294);
                                    picW = (wrappicW294.value != null ? wrappicW294.value : 0);
                                }
                                else if (pictComm.command.startsWith("pich") || pictComm.command.startsWith("objh")) {
                                    com.pullenti.unisharp.Outargwrapper<Integer> wrappicH295 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                                    com.pullenti.unisharp.Utils.parseInteger(pictComm.command.substring(4), 0, null, wrappicH295);
                                    picH = (wrappicH295.value != null ? wrappicH295.value : 0);
                                }
                                else if (pictComm.command.startsWith("picscalex")) {
                                    com.pullenti.unisharp.Outargwrapper<Integer> wrapscalx296 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                                    com.pullenti.unisharp.Utils.parseInteger(pictComm.command.substring(9), 0, null, wrapscalx296);
                                    scalx = (wrapscalx296.value != null ? wrapscalx296.value : 0);
                                }
                                else if (pictComm.command.startsWith("picscaley")) {
                                    com.pullenti.unisharp.Outargwrapper<Integer> wrapscaly297 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                                    com.pullenti.unisharp.Utils.parseInteger(pictComm.command.substring(9), 0, null, wrapscaly297);
                                    scaly = (wrapscaly297.value != null ? wrapscaly297.value : 0);
                                }
                                else if (pictComm.command.startsWith("bin")) {
                                    int blen;
                                    com.pullenti.unisharp.Outargwrapper<Integer> wrapblen298 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                                    boolean inoutres299 = com.pullenti.unisharp.Utils.parseInteger(pictComm.command.substring(3), 0, null, wrapblen298);
                                    blen = (wrapblen298.value != null ? wrapblen298.value : 0);
                                    if (inoutres299) {
                                        if ((stream.getPosition() + ((long)blen)) <= stream.length()) {
                                            if (isPict) {
                                                pictContent = new byte[blen];
                                                stream.read(pictContent, 0, blen);
                                            }
                                            else 
                                                stream.setPosition(stream.getPosition() + ((long)blen));
                                        }
                                    }
                                }
                                if (isPict && pictComm.pictContent != null) 
                                    pictContent = pictComm.pictContent;
                            }
                        }
                    }
                    else if (lev == 0 && isPict && Character.isLetterOrDigit(ch)) 
                        hexVal.append(ch);
                }
                if (isPict && hexVal.length() > 10 && pictContent == null) {
                    pictContent = new byte[hexVal.length() / 2];
                    String str = hexVal.toString();
                    for (int ii = 0, p = 0; ii < (hexVal.length() - 1); ii += 2,p++) {
                        byte bb = (byte)0;
                        for (int jj = 0; jj < 2; jj++) {
                            char chh = str.charAt(ii + jj);
                            int v = 0;
                            if (chh >= '0' && chh <= '9') 
                                v = ((int)chh) - ((int)'0');
                            else if (chh >= 'a' && chh <= 'f') 
                                v = 10 + ((((int)chh) - ((int)'a')));
                            else if (chh >= 'A' && chh <= 'F') 
                                v = 10 + ((((int)chh) - ((int)'A')));
                            else 
                                break;
                            bb = (byte)((((Byte.toUnsignedInt(bb)) << 4) | v));
                        }
                        pictContent[p] = bb;
                    }
                }
                if (isPict && ((picW > 0 || picGoalW > 0)) && ((picH > 0 || picGoalH > 0))) {
                    if (picGoalW <= 0 || picGoalH <= 0) {
                        picWidth = (int)((0.75 * ((double)picWidth)));
                        picHeight = (int)((0.75 * ((double)picHeight)));
                    }
                    else {
                        picWidth = picGoalW / 20;
                        picHeight = picGoalH / 20;
                    }
                    if (scalx > 0) 
                        picWidth = (picWidth * scalx) / 100;
                    if (scaly > 0) 
                        picHeight = (picHeight * scaly) / 100;
                }
                return true;
            }
            return true;
        }
        public RftCommand() {
        }
    }


    public static java.util.ArrayList<RtfItem> parseList(com.pullenti.unisharp.Stream stream) throws java.io.IOException {
        java.util.ArrayList<RtfItem> res = new java.util.ArrayList<RtfItem>();
        StringBuilder txtBuf = new StringBuilder();
        java.util.ArrayList<Byte> codBuf = new java.util.ArrayList<Byte>();
        RftCommand command = new RftCommand();
        while (stream.getPosition() < stream.length()) {
            int i = stream.read();
            if (i < 0) 
                break;
            char ch = (char)i;
            RtfItem newItem = null;
            byte newCode = (byte)0;
            char newChar = (char)0;
            if (ch == '{') 
                newItem = _new300(RftItemTyp.BRACKETOPEN);
            else if (ch == '}') 
                newItem = _new300(RftItemTyp.BRACKETCLOSE);
            else if (ch == '\\') {
                if (!command.parse(stream)) 
                    continue;
                if (command.charCode != ((byte)0)) 
                    newCode = command.charCode;
                else if (((int)command.pureChar) != 0) 
                    newChar = command.pureChar;
                else if (command.pictContent != null) 
                    newItem = RtfItemImage._new302(RftItemTyp.IMAGE, command.picWidth, command.picHeight, command.command, command.pictContent);
                else if (command.command != null) 
                    newItem = _new303(RftItemTyp.COMMAND, command.command);
            }
            else {
                if (((int)ch) == 0xD || ((int)ch) == 0xA) 
                    continue;
                if (((int)ch) < 0x80) 
                    newChar = ch;
                else 
                    newCode = (byte)ch;
            }
            if (newItem != null || newCode != ((byte)0)) {
                if (txtBuf.length() > 0) {
                    res.add(_new303(RftItemTyp.TEXT, txtBuf.toString()));
                    txtBuf.setLength(0);
                }
            }
            if (newItem != null || ((int)newChar) != 0) {
                if (codBuf.size() > 0) {
                    res.add(_new305(RftItemTyp.TEXT, com.pullenti.unisharp.Utils.toBytesArray(codBuf.toArray(new Byte[codBuf.size()]))));
                    codBuf.clear();
                }
            }
            if (newItem != null) 
                res.add(newItem);
            if (newCode != ((byte)0)) 
                codBuf.add(newCode);
            if (((int)newChar) != 0) 
                txtBuf.append(newChar);
        }
        if (txtBuf.length() > 0) {
            res.add(_new303(RftItemTyp.TEXT, txtBuf.toString()));
            txtBuf.setLength(0);
        }
        if (codBuf.size() > 0) {
            res.add(_new305(RftItemTyp.TEXT, com.pullenti.unisharp.Utils.toBytesArray(codBuf.toArray(new Byte[codBuf.size()]))));
            codBuf.clear();
        }
        int lev = 0;
        for (RtfItem it : res) {
            it.level = lev;
            if (it.typ == RftItemTyp.BRACKETOPEN) 
                lev++;
            else if (it.typ == RftItemTyp.BRACKETCLOSE) {
                lev--;
                it.level = lev;
            }
        }
        return res;
    }

    public static RtfItem _new300(RftItemTyp _arg1) {
        RtfItem res = new RtfItem();
        res.typ = _arg1;
        return res;
    }

    public static RtfItem _new303(RftItemTyp _arg1, String _arg2) {
        RtfItem res = new RtfItem();
        res.typ = _arg1;
        res.text = _arg2;
        return res;
    }

    public static RtfItem _new305(RftItemTyp _arg1, byte[] _arg2) {
        RtfItem res = new RtfItem();
        res.typ = _arg1;
        res.codes = _arg2;
        return res;
    }
    public RtfItem() {
    }
    public static RtfItem _globalInstance;
    
    static {
        try { _globalInstance = new RtfItem(); } 
        catch(Exception e) { }
    }
}
