public String toHtml(String input) {

        String output = null;
        
        // match both background and foreground
        Pattern match_1 = Pattern.compile(0x03 + "(\\d\\d?),(\\d\\d?)(.*?)(?:(?="+ 0x03 +")|$)");
        Matcher matcher_1 = match_1.matcher(input);

        while (matcher_1.find()) {
            int fgColorIndex = Integer.parseInt(matcher_1.group(1));
            int bgColorIndex = Integer.parseInt(matcher_1.group(2));
            if (fgColorIndex < colors.length && bgColorIndex < colors.length) {
                output = matcher_1.replaceFirst(
                        "</span><span style=\"color: #"
                        + colors[fgColorIndex]
                        + "; background-color: #"
                        + colors[bgColorIndex]
                        + ";\">" + matcher_1.group(3));
                input = output;
                matcher_1 = match_1.matcher(input);
            }
        }

        // match foreground
        Pattern match_2 = Pattern.compile(0x03 + "(\\d\\d?)(.*?)(?:(?=" + 0x03 + ")|$)");
        Matcher matcher_2 = match_2.matcher(input);

        while (matcher_2.find()) {
            int colorIndex = Integer.parseInt(matcher_2.group(1));
            if (colorIndex < colors.length) {

                output = matcher_2.replaceFirst(
                        "</span><span style=\"color: #"
                        + colors[colorIndex]
                + ";\">"
                + matcher_2.group(2));

                input = output;
                matcher_2 = match_2.matcher(input);
            }
        }

        // match no color
        Pattern match_6 = Pattern.compile(0x03 + "(\\D?)");
        Matcher matcher_6 = match_6.matcher(input);

        while (matcher_6.find()) {
            output = matcher_6.replaceFirst("</span> ");
            input = output;
            matcher_6 = match_6.matcher(input);
        }
        
        // match bold text
        Pattern match_4 = Pattern.compile(0x02 + "(.*?)(?:(?=" + 0x02 + ")" + 0x02 + "|$)");
        Matcher matcher_4 = match_4.matcher(input);

        while (matcher_4.find()) {

            output = matcher_4.replaceFirst("<b>"
                                            + matcher_4.group(1)
                                            + "</b>");
            input = output;
            matcher_4 = match_4.matcher(input);
        }

        // match underline text
        Pattern match_5 = Pattern.compile("\\x1F(.*?)(?:(?=\\x1F)\\x1F|$)");
        Matcher matcher_5 = match_5.matcher(input);

        while (matcher_5.find()) {

            output = matcher_5.replaceFirst(
                    "<u>"
                    + matcher_5.group(1)
                    + "</u>");
            input = output;
            matcher_5 = match_5.matcher(input);
        }

        if (output == null) {
            output = input;
        }

        return "<span>" + output.trim() + "</span></span><br/>";
    }