var eintrag = new arrayCreate();   // database

// Input-Windows-Specification
var cEingabe      = "";     // content of inputfile
var cTrefferliste = false;  // true== keep searchrequest
var cWortanfaenge = false;  // true== compare only at the beginning
var cGrossklein   = false;  // true== compare upper/lower cases

// Scanner-Variables
var cLiteral    = "";     // searchrequest within the input
var eingabe     = "";     // left-over of the inputline
var token       = "";     // last found token

// Scanner-Token
var tEOF        = 0;
var tOr         = 1;
var tAnd        = 2;
var tNot        = 3;
var tKlammerAuf = 4;
var tKlammerZu  = 5;
var tLiteral    = 6;

// Parser-Variables
var fehler      = false;  // error, end analysis

/****************************************
@Name: unescapeString
******************************************/
function unescapeString(stringparam)
{
	var inputString = new String(stringparam);
	var resultString = new String("");
	var inputlen=inputString.length;

	for (i=0; i<inputlen; i++)
	{
		myChar=inputString.charAt(i);
		if (myChar == '&')
		{
			myChar=inputString.charAt(++i);
			if (myChar == '#')
			{
				startPos=i;
				myCharCode=0;
				while (i++ < inputlen && (myChar=inputString.charAt(i)) != ';')
				{
					myCharCode *= 10;
					myCharCode += parseInt(myChar, 10);
				}
				resultString+=String.fromCharCode(myCharCode);
			}
			else
			{
				resultString+='&';
				resultString+=myChar;
			}
		}
		else
			resultString+=myChar;
	}

	return resultString;
}

/****************************************
@Name: myAlert
******************************************/
function myAlert(stringparam)
{
	alert(unescapeString(stringparam));
}

//-------------------------------------------------- Array-management -

function arrayCreate() {
// *****************************************************************
// * Function..: arrayCreate
// * Tast...: Array-Object for management of various entries
// *****************************************************************

  this.item     = new Array();
  this.length   = aLength;    // return length
  this.add      = aAdd;       // append element
  this.concat   = aConcat;    // concatenate the elements of 2 arrays
  this.sort     = aSort;      // sort by criterion
}

function aLength() {
// *****************************************************************
// * Function..: arrayCreate.length
// * Task.....: return number of array-elementes
// *****************************************************************

  return this.item.length;
}

function aAdd(element) {
// *****************************************************************
// * Function..: arrayCreate.add
// * Task......: add array-element
// *****************************************************************

  this.item[this.item.length] = element;
}

function aConcat(array) {
// *****************************************************************
// * Function..: arrayCreate.concat
// * Task......: concatenate objekt-array with array and return reference to itself
// *****************************************************************

  if (array != this) {
    for (var i = 0; i < array.length(); i++) {
      this.item[this.item.length] = array.item[i];
    }
  }
  return this;
}

function aSort(Function) {
// *****************************************************************
// * Function..: arrayCreate.sort
// * Task......: sort Array-Elementes
// *****************************************************************

  this.item.sort(Function);
}

//---------------------------------------------------- Array-Elemente -

function eintragCreate() {
// *****************************************************************
// * Function..: eintragCreate
// * Task......: database-object
// *****************************************************************

  this.begriff;              // searchterm
  this.seite;                // URL
  this.beschreibung;         // description of the content of the page
}

function gefundenCreate() {
// *****************************************************************
// * Function..: gefundenCreate
// * Task......: found object
// *****************************************************************

  this.position;                // is this object part of entry[x]?
  this.prozent = 100;
  this.begriff = "Klick";
  this.doppelt = false;         // true: entry is already part of array
  this.addProzent = gAddProzent;
  this.addBegriff = gAddBegriff;
}

function gAddProzent(prozent) {
// *****************************************************************
// * Function..: gefundenCreate.addProzent
// * Task......: recalculate percentage
// *****************************************************************

  this.prozent = Math.round((this.prozent + prozent) / 2);
}

function gAddBegriff(begriff) {
// *****************************************************************
// * Function..: gefundenCreate.addBegriff
// * Task......: add a new expression
// *****************************************************************

  if (this.begriff == "Klick") {
    this.begriff = begriff;
  }
  else {
    if ((begriff == "Klick") && (this.begriff != "")) {
      // ignorieren
    }
    else {
      if (this.begriff != begriff) {
        this.begriff = this.begriff + "<br>" + begriff;
      }
    }
  }
}

function sortProzent(x,y) {
// *****************************************************************
// * Function..: sortProzent
// * Task......: sort-function for gefundenCreate.sort
//               (by percentage)
// *****************************************************************

  if (x.prozent < y.prozent) {return -1};
  if (x.prozent > y.prozent) {return 1};
  return 0;
}


function getToken() {
// *****************************************************************
// * Function..: getToken
// * Task......: determine Token from inputline
// *****************************************************************

  cLiteral = "";
  while ((eingabe.length > 0) && (eingabe.substring(0,1) == " ")) {
    eingabe = eingabe.substring(1,eingabe.length);
  }
  if (eingabe.substring(0,1) == '"') {
    eingabe = eingabe.substring(1,eingabe.length);
    while ((eingabe.length > 0) && (eingabe.substring(0,1) != '"')) {
      cLiteral = cLiteral + eingabe.substring(0,1);
      eingabe = eingabe.substring(1,eingabe.length);
    }
    if (eingabe.length > 0) {
      eingabe = eingabe.substring(1,eingabe.length);
    }
  } else
  if ((eingabe.substring(0,1) == "(") || (eingabe.substring(0,1) == ")")) {
    cLiteral = eingabe.substring(0,1);
    eingabe = eingabe.substring(1,eingabe.length);
  }
  else {
    while ((eingabe.length > 0) && (eingabe.substring(0,1) != " ") &&
       (eingabe.substring(0,1) != "(") && (eingabe.substring(0,1) != ")")) {
      cLiteral = cLiteral + eingabe.substring(0,1);
      eingabe = eingabe.substring(1,eingabe.length);
    }
  }
  if (cLiteral.toUpperCase() == "OR") {
    token = tOr
  }
  else {
    if (cLiteral.toUpperCase() == "AND") {
      token = tAnd
    }
    else {
      if (cLiteral.toUpperCase() == "NOT") {
        token = tNot
      }
      else {
        if (cLiteral == "(") {
          token = tKlammerAuf
        }
        else {
          if (cLiteral == ")") {
            token = tKlammerZu
          }
          else {
            if ((eingabe == "") && (cLiteral == "")) {
              token = tEOF
            }
            else {
              token = tLiteral
            }
          }
        }
      }
    }
  };
}

function ausdruck(inGefunden,ebene) {
// *****************************************************************
// * Function..: ausdruck
// * Task......: Parser-Priority: NOT, AND, OR)
// *             Expression ::= Term [[OR] Term]*
// *	           (space is interpreted as tOr).
// *****************************************************************

  inGefunden = term(inGefunden,ebene);
  while ((fehler == false) && ((token == tOr) || (token == tNot) ||
         (token == tLiteral) || (token == tKlammerAuf))) {
    if (token == tOr) { getToken() };
    inGefunden = Ergebnis_or(inGefunden,term(inGefunden,ebene));
  }
  if ((ebene == 0) && (token != tEOF)) {
    error(str_erw1)
  }
  return inGefunden;
}

function term(inGefunden,ebene) {
// *****************************************************************
// * Function..: term
// * Task......: Parser: recursive descent 1. level:
// *             Term ::= Not-Factor [AND Not-Factor]*
// *****************************************************************

  inGefunden = nFaktor(inGefunden,ebene);
  while ((fehler == false) && (token == tAnd)) {
    getToken();
    inGefunden = Ergebnis_and(inGefunden,nFaktor(inGefunden,ebene));
  }
  return inGefunden;
}

function nFaktor(inGefunden,ebene) {
// *****************************************************************
// * Function..: nFaktor
// * Task......: Parser: recursive descent 2. level:
// *             Not-Factor ::= [NOT] Binary-factor
// *****************************************************************

  if (token == tNot) {
    getToken();
    inGefunden = Ergebnis_not(bFaktor(inGefunden,ebene));
  }
  else {
    inGefunden = bFaktor(inGefunden,ebene);
  }
  return inGefunden;
}

function bFaktor(inGefunden,ebene) {
// *****************************************************************
// * Function..: bFaktor
// * Task......: Parser: recursive descent 3. level:
// *             Binary-factor ::= Literal | (expression)
// *****************************************************************

  if (token == tKlammerAuf) {
    getToken();
    ebene = ebene + 1;
    inGefunden = ausdruck(inGefunden,ebene);
    if (token != tKlammerZu) { error(str_erw2) };
    getToken();
  }
  else {
    if (token == tLiteral) {
      inGefunden = begriffSuchen(cLiteral);
      getToken();
    }
    else { error(str_erw3) };
  }
  return inGefunden;
}

function Ergebnis_or(inErgebnis,inErgebnis2) {
// *****************************************************************
// * Function..: Ergebnis_or
// * Task......: resultarrays or-link
// *****************************************************************

  var ergebnis = inErgebnis.concat(inErgebnis2);
  var gefunden = new arrayCreate();
  for (var i = 0; i < ergebnis.length(); i++) {
    if (ergebnis.item[i].doppelt == false) {
      gefunden.add(ergebnis.item[i]);
      for (var ii = i + 1; ii < ergebnis.length(); ii++) {
        if (ergebnis.item[ii].doppelt == false) {
          if (ergebnis.item[ii] == ergebnis.item[i]) {
            ergebnis.item[ii].doppelt = true;
          }
          else {
            if (ergebnis.item[ii].position == ergebnis.item[i].position) {
              ergebnis.item[ii].doppelt = true;
              gefunden.item[gefunden.length() - 1].addProzent(
                                              ergebnis.item[ii].prozent);
              gefunden.item[gefunden.length() - 1].addBegriff(
                                              ergebnis.item[ii].begriff);
            }
          }
        }
      }
    }
  }
  return gefunden;
}

function Ergebnis_and(inErgebnis,inErgebnis2) {
// *****************************************************************
// * Function..: Ergebnis_and
// * Task......: resultarrays and-link
// *****************************************************************

  var ergebnis = inErgebnis.concat(inErgebnis2);
  var gefunden = new arrayCreate();
  for (var i = 0; i < ergebnis.length(); i++) {
    var angelegt = false;
    if (ergebnis.item[i].doppelt == false) {
        for (var ii = i + 1; ii < ergebnis.length(); ii++) {
        if (ergebnis.item[ii].doppelt == false) {
          if (ergebnis.item[ii] == ergebnis.item[i]) {
            ergebnis.item[ii].doppelt = true;
          }
          else {
            if (ergebnis.item[ii].position == ergebnis.item[i].position) {
              ergebnis.item[ii].doppelt = true;
              if (angelegt == false) {
                gefunden.add(ergebnis.item[i]);
                angelegt = true;
              }
              gefunden.item[gefunden.length() - 1].addProzent(
                                              ergebnis.item[ii].prozent);
              gefunden.item[gefunden.length() - 1].addBegriff(
                                              ergebnis.item[ii].begriff);
            }
          }
        }
      }
    }
  }
  return gefunden;
}

function Ergebnis_not(inErgebnis) {
// *****************************************************************
// * Function..: Ergebnis_not
// * Task......: deliver inverted result to database
// *****************************************************************

  var gefunden = new arrayCreate();
  for (var i = 0; i < eintrag.length(); i++) {
    gefunden.add(new gefundenCreate());
    gefunden.item[gefunden.length() - 1].position = i;
  }
  for (var i = 0; i < inErgebnis.length(); i++) {
    for (var ii = 0; ii < gefunden.length(); ii++) {
      if (gefunden.item[ii].doppelt == false) {
        if (gefunden.item[ii].position == inErgebnis.item[i].position) {
          gefunden.item[ii].doppelt = true;
        }
      }
    }
  }
  var ergebnis = new arrayCreate();
  for (var i = 0; i < gefunden.length(); i++) {
    if (gefunden.item[i].doppelt == false) {
      ergebnis.add(gefunden.item[i]);
    }
  }
  return ergebnis;
}

function error(text) {
// *****************************************************************
// * Function..: error
// * Task......: Parser: Error message in outputline (<)
// *****************************************************************

  if (fehler == false) {
    if (eingabe.length == 0) {
      parent.sucheingabe.document.abfrage.eingabe.value = cEingabe + "<";
    }
    else {
      parent.sucheingabe.document.abfrage.eingabe.value =
         cEingabe.substring(0,cEingabe.lastIndexOf(eingabe,
                            cEingabe.length)) + "<" +
         cEingabe.substring(cEingabe.lastIndexOf(eingabe,
                            cEingabe.length),cEingabe.length);
    }
    myAlert(str_fehl + text);
  }
  fehler = true;
}

//----------------------------------------------------------- Output -

function kopf() {
// *****************************************************************
// * Function..: kopf()
// * Task......: print header of searchresults
// *****************************************************************

  if ((cWortanfaenge == true) && (cGrossklein == true)) {
    var eingabe = cEingabe + '<br><FONT class="small">' + str_wgk + '</FONT>';
  }
  else {
    if (cGrossklein == true) {
      var eingabe = cEingabe + '<br><FONT class="small">' + str_gk + '</FONT>';
    }
    else {
      if (cWortanfaenge == true) {
        eingabe = cEingabe + '<br><FONT class="small">' + str_wa + '</FONT>';
      }
      else { var eingabe = cEingabe }
    }
  }
  document.writeln('<DIV align="center"><table width="550">' +
	'<TR><TD class="text">' + str_sn + eingabe +'</td></tr></table>' +
	  '<TABLE width="550">' +
		  '<colgroup>' +
			'<col width="1*"><col width="2*"><col width="3*"><col width="3*">' +
		   '</colgroup>' +

			'<TR><TD class="searchheader">&nbsp;</TD>' +
				'<TD class="searchheader">' + str_tr + '</TD>' +
				'<TD class="searchheader">' + str_sb + '</TD>' +
				'<TD class="searchheader">' + str_bes + '</TD></TR>');
}


function leerZeile() {
// *****************************************************************
// * Function..: leerZeile()
// * Task......: no suitable entry was found
// *****************************************************************

  parent.suchausgabe.document.write('<TR><TD class="counter">-</TD>' +
      '<TD class="hitquote">0%</TD>' +
      '<TD class="searchname">---</TD>' +
      '<TD class="description">' + str_keg + '</TD></TR>');
}

function zeile(gefunden,prozent,begriff,seite,beschreibung) {
// *****************************************************************
// * Function..: zeile
// * Task......: prints a single line from the searchresults
// *****************************************************************
  if (cOhneFrame == false) {
    var begriffArray = begriff.split("<br>");
    var highlightStr;
    parent.suchausgabe.document.write('<TR><TD class="counter">' + gefunden + '.</TD>' +
                                      '<TD  class="hitquote">' + prozent + '%</TD>' + '<TD  class="searchname">');
    for (i=0; i<begriffArray.length; i++)
    {
	highlightStr = begriffArray[i].replace(/<b>/,"").replace(/<\/b>/,"").replace(/ /,"%20");
	parent.suchausgabe.document.write('<A HREF="' + seite + '?highlight=' + highlightStr + '">' + begriffArray[i] + '</A><br>');
    }
    parent.suchausgabe.document.write('</TD>' + '<TD class="description"><div style="width: 100%; height: 100%; overflow : auto;">' + beschreibung + '</div></TD></TR>');
  }
  else {
    parent.suchausgabe.document.write('<TR><TD class="counter">' + gefunden + '.</TD>' +
        '<TD class="hitquote">' + prozent + '%</TD>' +
        '<TD class="searchname"><div style="width: 100%; height: 100%; overflow : auto;"><A HREF="' + seite + '" TARGET="_parent">' +
        begriff + '</A></div></TD>' +
        '<TD class="description">' + beschreibung + '</TD></TR>');
  }
}

function fuss() {
// *****************************************************************
// * Function..: fuss
// * Task......: prints end ot the searchresultlist
// *****************************************************************

 parent.suchausgabe.document.write('</TABLE></DIV>'+
                           		    '<p>' +
                                    '<DIV align="center">Erzeugt mit <A HREF="http://oase-shareware.' +
                                    'org/salz" TARGET="_parent">S@lz&Pfeffer</A>: ' +
                                    'Copyright &copy; 1997-98 bei ' +
                                    'Rainer Eschen, <A HREF="http://' +
                                    'oase-shareware.org" TARGET="_parent">' +
                                    'OASE</A>.</DIV></p>' +
                                    '</BODY></HTML>');
}

function trefferliste(gefunden) {
// *****************************************************************
// * Function..: trefferliste
// * Task......: prints resultlist
// *****************************************************************
 // myAlert(gefunden.length());
  if (gefunden.length() == 0) {
    leerZeile();
  }
  else {
    for (var i = gefunden.length() - 1; i > -1; i--) {
      zeile(i + 1,gefunden.item[i].prozent,gefunden.item[i].begriff,
            eintrag.item[gefunden.item[i].position].seite,
            eintrag.item[gefunden.item[i].position].beschreibung);
    }
  }
}

//------------------------------------------------------- Suche -

function toUpperCaseUmlaute(eingabeBegriff) {
// *****************************************************************
// * Function..: toUpperCaseUmlaute
// * Task......: UpperCase + Umlaut-Workaround
// *****************************************************************

  eingabeBegriff = eingabeBegriff.toUpperCase();
  /* conversion a with umlaut*/
  var pos = eingabeBegriff.indexOf("\u00E4");
  while (pos > -1) {
    eingabeBegriff = eingabeBegriff.substring(0,pos) +
                     "\u00C4" + eingabeBegriff.substring(pos + 1,eingabeBegriff.length);
    pos = eingabeBegriff.indexOf("\u00E4",pos + 1);
  }
  /* conversion u with umlaut*/
  pos = eingabeBegriff.indexOf("\u00FC");
  while (pos > -1) {
    eingabeBegriff = eingabeBegriff.substring(0,pos) +
                     "\u00DC" + eingabeBegriff.substring(pos + 1,eingabeBegriff.length);
    pos = eingabeBegriff.indexOf("\u00FC",pos + 1);
  }
  /* conversion o with umlaut*/
  var pos = eingabeBegriff.indexOf("\u00F6");
  while (pos > -1) {
    eingabeBegriff = eingabeBegriff.substring(0,pos) +
                     "\u00D6" + eingabeBegriff.substring(pos + 1,eingabeBegriff.length);
    pos = eingabeBegriff.indexOf("\u00F6",pos + 1);
  }
  return eingabeBegriff;
}

function begriffSuchen(eingabe) {
// *****************************************************************
// * Function..: begriffSuchen
// * Task......: compare an individual entry with the database
// *****************************************************************

  var gefunden = new arrayCreate();
  var eingabeBegriff = new String(eingabe);
  if (cGrossklein != true) {
    eingabeBegriff = toUpperCaseUmlaute(eingabe);
  }
  for (var i = 0 ; i < eintrag.length(); i++) {
    var eintragBegriff = new String(eintrag.item[i].begriff);
    var eintragBegriffAusgabe = eintragBegriff;
    if (cGrossklein != true) {
      eintragBegriff = toUpperCaseUmlaute(eintragBegriff);
    }
    var angelegt = false;  // true = found-object is established
    var pos = eintragBegriff.indexOf(eingabeBegriff);
    while (pos > -1) {
      var trennerVor = eintragBegriff.lastIndexOf(",",pos);
      var punktVor = eintragBegriff.lastIndexOf(".",pos);
      if ((punktVor > 0) && (punktVor > trennerVor))
		trennerVor = punktVor;
      var trennerNach = eintragBegriff.indexOf(",",pos);
      var punktNach = eintragBegriff.indexOf(".",pos);
      if ((punktNach > 0) && (punktNach < trennerNach))
		trennerNach = punktNach;
      if (trennerNach < 0) { trennerNach = eintragBegriff.length };
      var eintragBegriffEinzel = eintragBegriff.substring(trennerVor + 1,
                                    trennerNach);
      var eintragBegriffEinzelAusgabe = eintragBegriffAusgabe.substring(trennerVor + 1,
                                    trennerNach);
      var prozent = 100;
      if ((eintragBegriffEinzel.length - eingabe.length > 0)) {
        prozent = Math.round((eingabe.length / eintragBegriffEinzel.length) * 100);
      }
      var posBegriffEinzel = eintragBegriffEinzel.indexOf(eingabeBegriff);
      eintragBegriffEinzel = eintragBegriffEinzelAusgabe.substring(0,posBegriffEinzel) +
         "<b class='searchhighlight'>" + eintragBegriffEinzelAusgabe.substring(posBegriffEinzel,
         posBegriffEinzel + eingabe.length) + "</b>" +
         eintragBegriffEinzelAusgabe.substring(posBegriffEinzel + eingabe.length,
         eintragBegriffEinzel.length);
      if (angelegt == false) {
        if (cWortanfaenge == true) {
          if (posBegriffEinzel == 0) {
            angelegt = true;
            gefunden.add(new gefundenCreate());
            gefunden.item[gefunden.length() - 1].position = i;
            gefunden.item[gefunden.length() - 1].begriff = eintragBegriffEinzel;
            gefunden.item[gefunden.length() - 1].prozent = prozent;
          }
        }
        else {
          angelegt = true;
          gefunden.add(new gefundenCreate());
          gefunden.item[gefunden.length() - 1].position = i;
          gefunden.item[gefunden.length() - 1].begriff = eintragBegriffEinzel;
          gefunden.item[gefunden.length() - 1].prozent = prozent;
        }
      }
      else {
        if (cWortanfaenge == true) {
          if (posBegriffEinzel == 0) {
            gefunden.item[gefunden.length() - 1].position = i;
            gefunden.item[gefunden.length() - 1].addBegriff(eintragBegriffEinzel);
            gefunden.item[gefunden.length() - 1].addProzent(prozent);
          }
        }
        else {
          gefunden.item[gefunden.length() - 1].position = i;
          gefunden.item[gefunden.length() - 1].addBegriff(eintragBegriffEinzel);
          gefunden.item[gefunden.length() - 1].addProzent(prozent);
        }
      }
      pos = eintragBegriff.indexOf(eingabeBegriff, trennerNach);
    }
  }
  return gefunden;
}

function suchen() {
// *****************************************************************
// * Function..: suchen
// * Task......: Search-function with submit
// *****************************************************************
  cEingabe = parent.sucheingabe.document.abfrage.eingabe.value;
  cTrefferliste = false;//directly defined because it is deactivated
  cWortanfaenge = parent.sucheingabe.document.abfrage.wortanfaenge.checked;
  cGrossklein   = parent.sucheingabe.document.abfrage.grossklein.checked;
  var gefunden = new arrayCreate();
  if (cEingabe == "") {
    myAlert(str_bse);
    return;
  };
  kopf();
  fehler = false;
  eingabe = cEingabe;
  getToken();
  var ebene = 0;
  gefunden = ausdruck(gefunden,ebene);
  if (fehler == false) {
    gefunden.sort(sortProzent);
    trefferliste(gefunden);
  }
  else {
    leerZeile();
  }
}
