// HTML5_Trafo.java
// Versucht, ein HTML-Dokument nach HTML5 zu transformieren; Schwerpunkt hin zu CSS
// Am Ende muss aber noch ein visueller Text gemacht werden !
// Netz-Verweise:
// W3-Konsortium http://www.w3.org/TR/html5
// WHATWG http://www.whatwg.org/specs/web-apps/current-work/multipage, http://whatwg.org/html5
// Validierung bei Einkopieren: http://validator.w3.org/#validate_by_input

// zu tun: gültige Werte für meta-->name, link-->rel, <style>...</style> nur in head, nicht in body


import java.io.*;
import java.util.List;
import java.util.ArrayList;

public class html5_trafo
{
  final static boolean DEBUG = false;


  public static void main (String [] args)
  {
    if (args.length != 1)
    {
      System.out.println ("Aufruf: java html5_trafo <Datei>"); return;
    }
    new html5_trafo().run(args[0]);
  }

  public void run(String eing)
  {
    final String htmlK = "<!DOCTYPE html>";
    File f = new File(eing);
    if (! (eing.indexOf(".html") >= 0 || eing.indexOf(".htm") >= 0))
    {
      System.out.println ("Es ist keine HTML-Datei"); return;
    }

    try
    {
      BufferedReader dat = new BufferedReader (new FileReader(f));
      String zeile = ""; int ab = 0; String einr = ""; int laenge; String tag=""; boolean istSkript = false; int i;
      String markeEnde; int markeLaenge; String letztes_offen = ""; int letztesIstEnde = 1; boolean DEBUG = false;
      String neu, suche; boolean ersteZeile = true;
      while ((neu = dat.readLine()) != null)
      {
        zeile = zeile + neu + System.getProperty("line.separator"); laenge = zeile.length();
        // Sonderfall DOCTYPE 1.Zeile
        if (ersteZeile)
        {
          System.out.print(htmlK + System.getProperty("line.separator"));
          int st = zeile.indexOf("<!DOCTYPE");
          if (st >= 0)
          {
            int end = zeile.lastIndexOf(">");
            if (end < 0) { System.out.println ("DOCTYPE nicht abgeschlossen"); System.exit(1); }
            zeile = zeile.substring(end+1);
          }
          ersteZeile = false;
        }

        // System.out.println (zeile);
        while ((ab >= 0) && (ab < laenge))
        {
          if (istSkript) suche ="</" + tag;
          else suche = "<";
          // suche Tag
          int ziel = zeile.indexOf(suche, ab); if (ziel < 0) break;
          if ((ziel+3) >= zeile.length()) break;  // nochmals lesen, um entscheiden zu können

          if (zeile.substring(ziel, ziel+4).equals("<!--")) { markeEnde = "-->"; markeLaenge = 3; }  // Sonderfall Kommentar
          else { markeEnde = ">"; markeLaenge = 1; }

          boolean neuladen = false; int vergl = ziel; int bis = -1;
          do
          {
            bis = zeile.indexOf(markeEnde, vergl); if (bis < 0) { neuladen = true; break; }
            // ggf. liegt dies in Anführungszeichen, z.B. Attributen

            int zielAnf = zeile.indexOf("\"", vergl); // suche das nächste Anführungszeichen
            if (zielAnf >= 0 && zielAnf < bis)
            {
              int danach = zeile.indexOf("\"", zielAnf+1);
              if (danach < 0) { neuladen = true; break; } // neu laden
              vergl = danach + 1; continue;  // weitersuchen
            }
            else break;
          } 
          while (true);
          if (neuladen) break;  // Ende nicht gefunden, neu laden
          System.out.print (zeile.substring(ab, ziel)); // das vor dem Tag
            
          // Tag bestimmen, mit evt. beginnenden/endenden /; immer Kleinbuchstaben.
          tag = zeile.substring(ziel+1, bis + 1 - markeLaenge); char anf = tag.charAt(0);
          // Optionale Attribute wegnehmen, sind durch Leerzeichen getrennt
          String tag_ganz = tag;
          int leer = tag.indexOf(" "); if (leer >= 0) tag = tag.substring(0, leer);
          tag = tag.toLowerCase();
              
          // Sonderfall im HTML: Skript
          if (tag.equals("script")) istSkript = true; else istSkript = false;
               
          /*
            tag_ganz enthält element und eine Liste von Attributen.
          */
          if ((anf == '!') || (anf == '?'))
          {
            if ((zeile.indexOf("<!DOCTYPE") >= 0) && (zeile.indexOf("xhtml") >= 0))
            {
              System.out.println ("Es ist ein XHTML-Dokument, das anderer Verarbeitung bedarf"); System.exit(1);
            }
            // Sonderfall: Kommentar, DocType
          }
          else if (anf == '/')
          {
            // Elemente ersetzen
            String weiter = endelement_holen(tag);
            System.out.print (weiter);  // Ende-Tag ausgeben
          }
          else // normales Starttag
          {
            // 1) Attribute testen
            List attribute = null;
            if (leer >= 0)
            {
              // Gehe die Attribute durch. Der StringTokenizer kann nicht verwendet werden, weil Leerzeichen keine
              // wirklichen Trenner sind, vgl. "name1 = wert1 name2 = "wert2" name3"
              attribute = new ArrayList();
              String weiter = tag_ganz.substring(leer);
              // ... Attribute untersuchen
              attribute = attributliste_holen(weiter);
              // alte Attribute raus
              for (int lauf = 0; lauf < attribute.size(); ++lauf)
              {
                String rueck = attribut_obsolet(tag, (String) attribute.get(lauf));
                attribute.set(lauf, rueck);
              }
            }
            // 2) Tag testen
            String weiter = element_obsolet(tag, attribute);
            // mehrere style-Attribute zusammenfassen
            weiter = verdichten (weiter);
            System.out.print(weiter);  // Tag ausgeben
          }
          ab = bis + markeLaenge;
        }
        zeile = zeile.substring(ab); ab = 0;  // verkleiner
      }   
      dat.close();
    } catch (IOException ex) { System.out.println (ex); }
  }



  // ---------------------------- behandelt obsolete Elemente -------------------------

  // transformiert verworfene Elemente
  public String element_obsolet (String element, List attribute)
  {
    String rueck = null;
    if (element.equals("acronym"))
    {
      // acronym --> Aussprechbare Abkürzung, ?
      rueck = "abbr";
    }
    // applet --> object-Element, embed
    else if (element.equals("basefont") || element.equals("font"))
    {
      // basefont: Attribut size --> CSS font-size, face --> CSS font-family, color --> CSS color
      // font --> Attribut size --> CSS font-size, face --> CSS font-family, color --> CSS color
      // ist leeres Element, solange gültig, bis aufgehoben
      // zu tun: bei basefont die Größen 1-6 richtig abbilden
      int standard = 10;
      String attrneu = "";
      for (int i = 0; (attribute != null) && (i < attribute.size()); ++i)
      {
        String eintr = (String) attribute.get(i);
        int trenn = eintr.indexOf("=");
        String links = eintr.substring(0,trenn);
        String rechts = attrWert(eintr);
        // zu tun: bei basefont noch eine der 7 Stufen richtig umsetzen
        if (rechts.charAt(0) == '-')
        {
          rechts = new Integer(standard - new Integer(rechts.substring(1)).intValue()).toString();
        }
        else if (rechts.charAt(0) == '+')
        {
          rechts = new Integer(standard + new Integer(rechts.substring(1)).intValue()).toString();
        }
        if (links.equals("size")) attrneu += ("font-size:" + rechts + "pt; ");
        else if (links.equals("face")) attrneu += (" font-family:" + rechts + ";");
        else if (links.equals("color")) attrneu += (" color:" + rechts + ";");
      }
      rueck = "span style=\"" + attrneu + "\"";
    }
    else if (element.equals("big"))
    {
      // big --> CSS font-size:large
      rueck = "span style=\"font-size:large\"";
    }
    else if (element.equals("center"))
    {
      // center --> CSS text-align:center
      rueck = "span style=\"text-align:center\"";
    }
    // frame --> CSS position:fixed in Verbindung mit größeren Bereichen
    // frameset --> CSS position:fixed in ""
    else if (element.equals("isindex"))
    {
      // isindex --> <input type="search">
      String attrneu = "Sie können diesen Index durchsuchen. Geben Sie Stichwörter ein, nach denen Sie suchen möchten:";
      if (attribute != null)
      {
        String eintr = (String) attribute.get(0);
        int trenn = eintr.indexOf("=");
        String links = eintr.substring(0,trenn);
        String rechts = attrWert(eintr);
        if (links.equals("prompt")) { attrneu = rechts; }
      }
      rueck = "hr>" + attrneu + "<input type=\"search\"" + "><hr";
    }
    // noframe --> ?
    else if (element.equals("s") || element.equals("strike"))
    {
      // s --> CSS text-decoration:line-through
      // strike --> CSS text-decoration:line-through
      rueck = "span style=\"text-decoration:line-through\"";
    }
    else if (element.equals("small"))
    {
      // small --> CSS font-size:small
      rueck = "span style=\"font-size:small\"";
    }
    else if (element.equals("tt") || element.equals("xmp") || element.equals("plaintext") || element.equals("listing") )
    {
      // tt --> CSS font-family:courier
      // xmp --> CSS font-family:courier
      // plaintext --> CSS font-family:courier
      // listing --> CSS font-family:courier
      rueck = "span style=\"font-family:courier\"";
    }
    else if (element.equals("u"))
    {
      // u --> CSS text-decoration:underline
      rueck = "span style=\"text-decoration:underline\"";
    }
    else  // wichtig: alle anderen Tags mit Attributen weiterreichen
    {
      rueck = element;
      for (int i = 0; (attribute != null) && (i < attribute.size()); ++i)
      {
        rueck += " " + (String) attribute.get(i);
      }
    }

    return "<" + rueck + ">";  // damit auch /> von xhtml beseitigt
  }

  // gibt Ende-Elemente zurück
  public String endelement_holen(String element)
  {
    String rueck = null;
    if (element.equals("/big") || element.equals("/small") || element.equals("/center") || element.equals("/strike") ||
        element.equals("/s") || element.equals("/font") || element.equals("/tt") || element.equals("/u") || element.equals("/xmp") 
        || element.equals("/plaintext") )
    {
      rueck = "/span";
    }
    else if (element.equals("/acronym"))
    {
      rueck = "/abbr";
    }
    else if (element.equals("/basefont"))  // eigentl. leere Elemente löschen
    {
      return "";
    }
    else
    {
      rueck = element;
    }

    return "<" + rueck + ">";
  }

  // zerlegt die Attribute, gibt eine Liste davon zurück
  List attributliste_holen (String eingabe)
  {
    // String tokenizer kann nicht verwendet werden, weil Leerzeichen auch in style-Angaben vorkommen können
    List erg = new ArrayList();
    // Normalisieren
    for (int i = 0; i < eingabe.length(); /* s.u. */)
    {
      char aktuell = eingabe.charAt(i); boolean weg = false;
      if ((aktuell == ' ') && (i == 0 || i == eingabe.length()-1)) weg = true; // am Anfang und Ende
      else if ((aktuell == ' ') && (eingabe.charAt(i-1) == '=')) weg = true;  // hinter gleich
      else if ((aktuell == ' ') && (i < eingabe.length() - 1))
      {
        char danach = eingabe.charAt(i+1);
        if ((danach == ' ') || (danach == '=')) weg = true; // doppelte Leerzeichen, vor gleich
      }
      else if (aktuell == '\"')
      {
        int weiter = eingabe.indexOf("\"", i+1); // Sonderfall z.B. style in "..."
        if (weiter < 0) { System.out.println ("Kein Anf.zeichen-Ende gefunden in " + eingabe + " ab " + i); System.exit(1); }
        i = weiter + 1; continue;
      }
      if (weg)
      {
        eingabe = eingabe.substring(0,i) + eingabe.substring(i+1);
      }
      else i++;
    }
    // System.out.println ("DEBUG: Attribute-Kette ist " + eingabe);

    // nach Leerzeichen(Trenner) unter Beachtung von Anführungszeichen suchen
    int ab = 0; if (eingabe.length() == 0) return erg;  // leer
    while ((ab >= 0) && (ab < eingabe.length()))
    {
      int suche1 = eingabe.indexOf(" ", ab); int ab_sicher = ab;
      int suche2 = eingabe.indexOf("\"", ab);
      if ((suche1 < 0) && (suche2 < 0)) { erg.add(eingabe.substring(ab)); break; }
      if ((suche2 >= 0) && (suche1 < 0 || suche1 > suche2))  // Anf.zeichen ist entscheidend
      {
        int bis = eingabe.indexOf("\"", suche2+1);
        erg.add(eingabe.substring(ab, bis+1)); ab = bis+2;
      }
      else if ((suche1 >= 0) && (suche2 < 0 || suche2 > suche1))  // Leerzeichen ist entscheidend
      {
        erg.add(eingabe.substring(ab, suche1)); ab = suche1+1; 
      }
      if (ab == ab_sicher) { System.out.println ("Bei " + ab + " mit " + eingabe); System.exit(1); }
    }

    if (DEBUG)
    {
      System.out.println ("Ausgabe der Liste mit Größe " + erg.size());
      for (int i = 0; i < erg.size(); ++i)
      {
        String was = (String) erg.get(i); System.out.println(was);
      }
      System.out.println ("Ende der Liste");
      warten();
    }

    return erg; // Liste zurückliefern
  }

  // transformiert verworfene Attribute
  // noch zu tun: Unterscheidung Attribute mit "=" und ohne dessen; mit und ohne Anführungszeichen
  // mehrere Style später zu einem zusammenpacken, sonst mag der IE nur das erste.
  public String attribut_obsolet (String element, String attribut)
  {
    // Fuer Vergleich auf Kleinschreibung umschalten
    int tr = attribut.indexOf("=");
    if (tr < 0) attribut = attribut.toLowerCase();
    else attribut = attribut.substring(0,tr).toLowerCase() + attribut.substring(tr);

    if (false)
    {}
    else if (attribut.startsWith("align"))
    {
      // align --> CSS: text-align:center
      return "style=\"text-align:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("alink"))
    {
      // alink --> in body, CSS a:hover und a:active
      return "style=\"a:active {color:" + attrWert(attribut) + "}\"";
    }
    // archive --> in applet, object, Liste für jar/uri
    else if (attribut.startsWith("background"))
    {
      // background --> CSS background-image; ggf. durch background-repeat ergänzt
      return "style=\"background-image:url(" + attrWert(attribut) + ")\"";
    }
    else if (attribut.startsWith("bgcolor"))
    {
      // bgcolor --> CSS background-color
      return "style=\"background-color:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("border"))  // z.B. bei table
    {
      // border --> CSS border
      return "style=\"border:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("cellpadding"))  // z.B. bei table; Abstand in Zellen
    {
      // cellpadding --> in table Elementen, CSS padding in th und td-elementen verwenden
      return "style=\"padding:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("cellspacing"))  // z.B. bei table; Abstand außerhalb Zellen
    {
      // cellspacing --> CSS border-spacing
      return "style=\"border-spacing:" + attrWert(attribut) + "\"";
    }
    // classid --> Eindeutige Bez. im object, ?
    else if (attribut.startsWith("clear"))
    {
      // clear --> im br, CSS clear
      return "style=\"clear:" + attrWert(attribut) + "\"";
    }
    // color --> in basefont, font, CSS color; Elemente sind obsolet !!
    else if (attribut.startsWith("compact"))
    {
      // compact --> bei dir,dl und pre, CSS letter-spacing
      return "style=\"letter-spacing:1\"";
    }
    // event --> in srcript, mit event-listening gelöst
    // for --> in script
    // face --> in font, base-font, CSS font-family; font ist obsolet !
    // frame --> in table, CSS border-left, border-right, border-top, border-bottom
    else if (attribut.startsWith("frameborder"))
    {
      // frameborder --> in frameset, frame, bei iframe mit CSS border
      return "style=\"border:" + attrWert(attribut) + "\"";
    }
    else if (!element.equals("img") && attribut.startsWith("height"))  // zu tun: wann genau
    {
      // height --> bei td und th
      return "style=\"height:" + attrWert(attribut) + "\"";
    }
    // href: darf keine Leerzeichen haben, %20 stattdessen
    else if (attribut.startsWith("hspace"))
    {
      // hspace --> CSS margin-left, margin-right
      return "style=\"margin-left:" + attrWert(attribut) + "; " +
          "margin-right:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("link"))
    {
      // link --> im body, CSS a:link
      return "style=\"a:link:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("marginheight"))
    {
      // marginheight --> in frameset und frame, bei iframe CSS padding
      return "style=\"padding:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("marginwidth"))
    {
      // marginwidth  --> in frameset und frame, bei iframe CSS padding
      return "style=\"padding:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("name") && element.equals("a"))
    {
      // name bei a --> es soll Id verwendet werden
      return "id=\"" + attrWert(attribut) + "\"";  // zu tun: schaue, ob es schon ein id gibt
    }
    // noresize --> in frameset, frame, ?
    else if (attribut.startsWith("noshade"))
    {
      // noshade --> CSS height:2px, border-width:0, color:gray, background-color:gray
      return "style=\"height:2px; border-width:0; color:gray; background-color:gray\"";
    }
    else if (attribut.startsWith("nowrap"))
    {
      // nowrap --> CSS white-space:nowrap auf td-Elemente
      return "style=\"white-space:nowrap\"";
    }
    // prompt --> bei isindex, ?
    // rules --> in table-Elemente, CSS border auf Elemente wie col, colgroup, tr, thead, tbody oder tfoot
    else if (attribut.startsWith("scrolling"))
    {
      // scrolling --> in frames, bei iframe CSS overflow
      return "style=\"overflow:" + attrWert(attribut) + "\"";
    }
    // shape, coords bei a
    else if ((attribut.startsWith("shape") || attribut.startsWith("coords")) && (element.equals("a")))
    {
      return "";
    }
    else if (attribut.startsWith("size") && element.equals("hr"))
    {
      // size --> in basefont oder font, CSS font-size; Elemente obsolet. Bei hr zu behandeln
      return "style=\"font-size:" + attrWert(attribut) + "\"";
    }
    // standby --> in object, ?
    // summary bei table --> auf caption Element zugreifen
    else if (attribut.startsWith("target") && element.equals("link"))
    {
      return "";
    }
    else if (attribut.startsWith("text"))
    {
      // text --> in body, CSS color auf body
      return "style=\"color:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("type") && (element.equals("li") || element.equals("ol") || element.equals("ul") ))
    {
      // type --> bei li, ol und ul
      String kompl = attrWert(attribut);
      char art = kompl.charAt(0);
      String neu;
      if (kompl.equalsIgnoreCase("disc")) neu = "disc";
      else if (art == 'a') neu = "lower-alpha";
      else if (art == 'A') neu = "upper-alpha";
      else if (art == 'i') neu = "lower-roman";
      else if (art == 'I') neu = "upper-roman";
      else neu = "decimal";  // zu tun: was ist mit none, square, circle ?
      return "style=\"list-style-type:" + neu + "\"";
    }
    else if (attribut.startsWith("valign"))
    {
      // valign --> bei col, colgroup, tbody, td, tfoot, th, thead und tr
      return "style=\"vertical-align:" + attrWert(attribut) + "\"";
    }
    // valuetype --> in object, ?
    else if (attribut.startsWith("vlink"))
    {
      // vlink --> in body, CSS a:visited
      return "style=\"a:visited:" + attrWert(attribut) + "\"";
    }
    else if (attribut.startsWith("vspace"))
    {
      // vspace --> CSS margin-top und margin-bottom
      return "style=\"margin-top:" + attrWert(attribut) + "; " +
          "margin-bottom:" + attrWert(attribut) + "\"";
    }
    else if (!element.equals("img") && attribut.startsWith("width"))
    {
      // width --> bei hr, table, td, th, col, colgroup und pre
      return "style=\"width:" + attrWert(attribut) + "\"";
    }

    // Hier die ersatzlos weggefallenen elemente
    else if (attribut.startsWith("version") || attribut.startsWith("axis") || attribut.startsWith("abbr") ||
         attribut.startsWith("scheme") || attribut.startsWith("profile") || attribut.startsWith("rev") ||
         attribut.startsWith("char") || attribut.startsWith("code") || attribut.startsWith("declare") ||
         attribut.startsWith("longdesc") || attribut.startsWith("scope") || attribut.startsWith("nohref") ||
         attribut.startsWith("language") )
    {
      // axis --> in td, wegen mangel. Praxisrel. gestrichen
      // abbr in td-Elementen, --> ?
      // char --> momentan kein Ersatz
      // charoff --> kein Ersatz
      // charset --> bei a und link; entfernt
      // code --> im applet, entfernt
      // codebase --> im applet, entfernt
      // codetype --> im object, entfernt
      // declare --> in object, entfernt
      // nohref --> nur in area, keinen Bereich notieren
      // language --> bei script, kann entfallen; nimmt dann Javascript an
      // longdesc --> ?
      // profile --> in head, RDF, Microformat etc.
      // rev --> in link, a, area, Validator sagt, mit rel und ungekehrter Bedeutung
      // scheme --> in meta-Element
      // scope --> bei td, th ?
      // version --> in html

      return "";
    }

    return attribut;
  }  


  // holt Attributwert, nimmt linke und rechte Anführungszeichen weg
  private static String attrWert(String eingabe)
  {
    int su = eingabe.indexOf("="); 
    if (su < 0) { System.out.println("Kein Attributwert gefunden"); System.exit(1); }
    eingabe = eingabe.substring(su+1); // hinter '='

    if (eingabe.charAt(0) == '\"') eingabe = eingabe.substring(1);
    if (eingabe.charAt(eingabe.length()-1) == '\"') eingabe = eingabe.substring(0, eingabe.length()-1);
    return eingabe;
  }

  // ----------------------------------------------------
  // Abschnitt 2: Proprietaere Elemente der Hersteller

  // transformiert proprietäre Elemente
  void element_proprietaer(String element)
  {
    // bgsound --> mit Flash
    // blink --> CSS text-blink:blink
    // ilayer --> CSS position:absolute position:relative
    // layer --> CSS position:absolute position:relative
    // marquee --> CSS overflow-style, marquee-direction, marquee-play-count, marquee-speed, marquee-style
    // multicol --> CSS column-count, column-width, column-gap, column-rule
    // nobr --> CSS white-space:nowrap
    // spacer --> CSS margin, padding
  }

  // transformiert proprietäre Attribute
  void attribut_proprietaer (String attribut)
  {
    // above --> in layer, CSS z-index
    // behavior --> in marquee, ?
    // below --> in CSS z-index
    // bgproperties --> in body, CSS background-attachment:fixed auf body
    // bordercolor --> ?
    // bordercolordark, bordercolorlight --> ?
    // clip --> CSS clip
    // controls --> in img, ?
    // direction --> in marquee, ?
    // framespacing --> ?
    // dynsrc --> in img, ?
    // gutter --> in multicol, CSS padding-left, padding-right
    // internal --> in img, ?
    // left --> in layer, CSS left
    // leftmargin --> in body, CSS padding-left, padding-right auf body
    // loop --> in embed, ?
    // lowsrc --> in img, ?
    // scrollamount --> in marquee, ?
    // scrolldelay --> in marquee, ?
    // start --> in img, ?
    // top --> in layer, CSS top
    // topmargin --> in body, CSS padding-top padding-bottom auf body
    // wrap --> in textarea, ?
    // z-index --> in layer, z-index
  }


  // fasst mehrere style-Attribute zu einem zusammen
  String verdichten (String eingabe)
  {
    int ab = 0; int einf = -1; int weiter = -1;
    while ((weiter = eingabe.indexOf("style=", ab)) >= 0)
    {
      int start = weiter; weiter += 6; int ende;
      if (eingabe.charAt(weiter) == '\"')
      {
        // Attribut in Anführungszeichen
        ++weiter; ende = eingabe.indexOf("\"", weiter);
      }
      else
      {
        // Attribut ohne Anführungszeichen, also mit Leer getrennt
        while (eingabe.charAt(weiter) == ' ') ++weiter;
        ende = eingabe.indexOf(" ", weiter);
      }
      if (ende < 0) { System.out.println ("Tag-Ende nicht gefunden"); System.exit(1); }
      if (einf == -1)
      {
        // Einfügeposition ermitteln
        einf = weiter; ab = ende + 1;
      }
      else
      {
        // Zusammensetzen
        int diff = (ende - weiter) + 1; // Strichpunkt und leer
        eingabe = eingabe.substring(0, einf) + eingabe.substring(weiter,ende) + "; " +
          eingabe.substring(einf, start) + eingabe.substring(ende+1);
        ab = start + diff; // Weitersuche setzen
      }
    }

    return eingabe;
  }

  private final static void warten()
  {
    try
    {
      int zeichen;
      while ((zeichen = System.in.read()) != '\n');
    } catch (IOException ex) {}
  }
}
