// Pfind.js - Person Find (Originally in C CircleSoftware (c)1983/2002)
//
// Version 2.41                     copyright Circle Software (c) 2002
//
// Started 03/11/2002                          Last Update: 12/03/2002
//
// This file contains the functions needed to impliment a pfind type
// search of the data inside a web page. This file needs to be included
// in the HTML page to be searched, also this will only work for browsers
// that follow the W3C DOM standard, IE5.0 and NS6.0 or newer and can
// return the document.innerHTML.
//
// Note: The data text file can include a line with "<!--endOfList-->"
//       as the last line of the list and the program will pick up
//       on it and stop there. This could be helpful if you do not
//       want to search all the way to the end of a file for some reason.
//
//    -----------------------------------------------------------
//    A Pfind type database uses "*" as the first char on a line
//    to know that this starts/ends a database record. The rest
//    of the line is lost so it could be used as a Pfind comment 
//    line. This can cause problems if you use */ to end a C, JS,
//    Perl, etc type comment block and the * is the first char on
//    the line.
//    -----------------------------------------------------------
//    Also, Pfind.js uses "link" as the file name it is searching
//    and this name MUST be filled in by the HTML file using Pfind.
//    -----------------------------------------------------------
//
//  There are three types of data return:
//    1. Full record of data for any record containing a matched line.
//    2. Address lines returned for any record containing a matched line.
//    3. Only the matched lines are returned.
//
// Version 2.00 - 03/12/2002
// This design was begun after the original Pfind001.js was completely working
// the idea here is to make it easier to understand and maintain by making
// a few functions:
// 1. Pfind() to get one record & send it to FindMatch() & run PrintOut().
// 2. FindMatch() to find a match & if found pass it on to ReturnData();
// 3. ReturnData() to build up the Found string of desired output.
// 4. PrintOut() to open/display the new window of Found information
//
// Version 2.10
// 03/13/02 - Broke function Pfind() into Pfind() and FindMatch()
//
// Version 2.11
// 03/27/2002 - Problem retaining the length of this record. ReturnData was
//              using Record.length NOT RecLn in the building of a full Pfind
//              data record found & returned.
//
// Version 2.12
// 03/28/2002 - Changed message about wrong browser for innerHTML in PfindInit
//
// Version 2.20
// 03/29/2002 - Removed conditioin that something MUST be found before a 
//              display of the search results is shown so user knows when 
//              nothing found
//
// Version 2.30
// 03/29/2002 - Added hilighting the found line for a full record return
//              using: function HiLight()
//
// Version 2.40
// 11/14/2002 - Added a check for NSFlg (Netscape flag) & replace &gt; &
//              &lt; if found in a string.
//            - Added the ReplaceIt() function
//
// Version 2.41
// 12/03/2002 - Changed ReplaceIt() to use regular expressions & .replace
// --------------------------------------------------------------------------

var All;
var Bad = 0;     // Assume it is good to begin with.
var Max = 999;   // This holds the "max" # of lines of the DB HTML file
var Found = "";  // empty to begin with, no one has been found.
var Matches = 0; // Number of records with a match.

// --------------------------------------------------------------------
// Either gets the full documents innerHTML or gives a warning that
// this type of search is not supported by this browser.
//
// inputs:  none
// ouputs:  none
// actions: saves documents innerHTML in All, or gives an alert, 
//          and sets Bad=1;
// returns: none
// --------------------------------------------------------------------
function PfindInit() {
  if(document.documentElement.innerHTML) {
     All = document.documentElement.innerHTML;
  }
  else {
     var Stng = "Sorry, this browser can NOT perform this type of inner search."
     Stng += "\n\n Transfering to the default data file.";
     alert(Stng);
     Bad = 1; // Must be used in your HTML file so it can change it's location.
              // as in: if(Bad) document.location = defaultURL;
  }
}


// --------------------------------------------------------------------
// The basic pfind search function. It will save the complete record
// of data if a match is found. There will be no options in this 
// version, so the cases will be changed to be the same, the display
// option will be of the complete record, and a key-word type search
// on one line only will be implamented.
//
// inputs:  the string to search for (space delimited?)
//          typ - The type of data to display
//             R - display the DB record that has the matching line
//             L - display only the matching line
//             A - display only the address lines (not yet implemented)
// actions: All will be searched for any line that matches, if a match
//          is found the complete pfind record will be saved into a
//          new string, in full HTML file form.
// outputs: A new window with the search results
// return:  none
//
// --------------------------------------------------------------------
function Pfind(typ) {
  
  // ------------------------------------------------------------------
  // The Pfind search code starts here
  // ------------------------------------------------------------------
  var finding = document.Lookup.PfindStuf.value;
  var finds = new Array(); // finds is the array of things to look for
  var TmpTxt = "";
  var Tmptx2 = "";
  var AllLines = new Array();
  var Record = new Array(); // To hold one record of data
  var j1 = 0;
  var GotOne = 0;
  var RecLn = 0;
  var NoLines = 0; // # lines in this file.
  var k = 0;
  var done = 0;

  Found = "";  // Nothing found so far.
  Matches = 0; // Number of records with a match.

  TmpTxt = finding.toLowerCase(); // convert all key "words" to lowercase
  finds = TmpTxt.split(" ");      // Put key words in an array
  // --------------------------------------------------------

  AllLines = All.split("\n"); // Put the entire HTML DB file into an array
  NoLines = AllLines.length - 1; // # lines in this file.
  Max = NoLines + 1;

  TmpTxt = AllLines[k].substring(0,1); 

  // ------------------------------------------------------------------
  // Do this loop until we're sure we're past the data base section.
  // ------------------------------------------------------------------
  Tmptx2 = AllLines[k].toLowerCase();
  while(Tmptx2.indexOf("endoflist") == -1 && k<Max && !done) {

  // ---------------------------------------------------------------------
  // Find the start of this first record.
  // ---------------------------------------------------------------------
  TmpTxt = AllLines[k].substring(0,1); 
  while(TmpTxt != "*" && !done) {
    ++k
    TmpTxt = AllLines[k].substring(0,1); 
  }
  // ---------------------------------------------------------------------

  Record[j1] = AllLines[k]; // load first record line

  ++j1; // next record line
  ++k;  // next line from the DB
  // ----------------------------------------------------------
  // If we're at the end of the file, then Die!
  // ----------------------------------------------------------
  if(k > NoLines) { // If trying to get LastLine + 1, Die!
     Max = k;
     done = 1;
     break;
  }
  // ----------------------------------------------------------
  TmpTxt = AllLines[k].substring(0,1);  // get the next line, 1st char

  
  // ---------------------------------------------------------------------
  // Find the rest of this record.
  // ---------------------------------------------------------------------
  while(TmpTxt != "*" && !done) {
    Record[j1] = AllLines[k]; // load next record line

    // ----------------------------------------------------------
    // If not at the end of the file yet, see if we're at the 
    // end of the data list, if we are then Die!
    // ----------------------------------------------------------
    Tmptx2 = AllLines[k].toLowerCase();
    if (Tmptx2.indexOf("endoflist") != -1) {
       Max = k;
       done = 1;
       break;
    }
    // ----------------------------------------------------------

    ++k;
    ++j1;
    // ----------------------------------------------------------
    // If we're at the end of the file, then Die!
    // ----------------------------------------------------------
    if(k > NoLines) { // If trying to get LastLine + 1, Die!
       Max = k;
       done = 1;
       break;
    }
    // ----------------------------------------------------------
    TmpTxt = AllLines[k].substring(0,1);  // get the next line, 1st char

  }
  // ---------------------------------------------------------------------
  RecLn = j1;

  if(!done) {
     FindMatch(Record, finds, typ, RecLn);
  }
  else { // We're done searching so print out what we've found.
     PrintOut(typ, finding);
  }

}



// --------------------------------------------------------------------
// Check the record for a match, if found pass it on to ReturnData.
//
// inputs:  The data record, the Finds array of key-words, the type of
//          data to be returned, and the record length.
// ouputs:  none
// actions: Passes a matched record on to ReturnData(), 
// returns: none.
// --------------------------------------------------------------------
function FindMatch(Record, Finds, typ, RecLn) {
  var GotOne = 0;
  
  // ---------------------------------------------------------------------
  // Now, check this record for a matching line
  // ---------------------------------------------------------------------
  for(var cnt=1; cnt<RecLn && !GotOne; ++cnt) {
    var j2 = 0;
    var hit = 0;
    var Tmptx2 = Record[cnt].toLowerCase(); // convert DB line to lowercase
  
    // Check for 1st key "word" in this DB line (all lowercase)
    if(Tmptx2.indexOf(Finds[j2]) != -1) { // Line matches so far
      ++j2;
      ++hit;

      // ----------------------------------------------------------
      // Now find if all key words are in this line, someplace!
      // Due to the nature of indexOf the order of the key words
      // is irrelevant.
      // ----------------------------------------------------------
      for( ; j2<finds.length; ++j2) {
        if(Tmptx2.indexOf(finds[j2]) != -1) { // Looks good so far
          ++hit;
        }
      }
      // ----------------------------------------------------------

      // ------------------------------------------------------------
      // If the # of hits == # key words we have a matched line!
      // ------------------------------------------------------------
      if(hit == finds.length) { // This is a good one! Found one! Matches!
         ++Matches;
         GotOne = 1;
         var LineNo = cnt;

         if(typ == "R")
            Record = HiLight(Record, finds, RecLn);
         ReturnData(Record, LineNo, typ, RecLn);
        // ------------------------------------------------
      } // end of: if(hit == finds.length) (It's a Match!)
    }
  } // end of: for(var cnt=1; cnt<Record.length; ++cnt)

  // Reset to the top for the next record, 
  // since we're at the end of this record.
  j1 = 0;

 } // done with: while(AllLines[k].indexOf("<!--endOfList") == -1)
  // ------------------------------------------------------------------
}




// --------------------------------------------------------------------
// Return the type of data the user wants.
//
// inputs:  The data record found, the line # of the matched line, the
//          type of data to be returned.
// ouputs:  none
// actions: saves the required lines into "Found", 
// returns: none
// --------------------------------------------------------------------
function ReturnData(Record, Match, typ, RecLn) {
   
   if(typ == "L") { // return only the matched line;
      Found += Record[Match] + "\n";
   }
   else if(typ == "A") { // Return the address lines
      var line = "";
      for(var i=1; i<RecLn; ++i) {
         line = Record[i].substring(1, 2);
         if(line != ":") {
            Found += Record[i] + "\n";
         }
      }
      Found += "\n";
   }   
   else if(typ == "R") { // Return the complete DataBase record
      for(var i=1; i<RecLn; ++i) { // Record.length should be RecLn 3/27/02 pk

         // -----------------------------------------------------------
         // Added 11/14/2002 to replace &gt; & &lt; with > & <
         // -----------------------------------------------------------
         if(NSFlg) { // Got to search & replace these if it's Netscape
           if(Record[i].indexOf("&lt;") != -1) {
              Record[i] = ReplaceIt(Record[i], "&lt;", "<");
           }
           if(Record[i].indexOf("&gt;") != -1) {
              Record[i] = ReplaceIt(Record[i], "&gt;", ">");
           }
         }
         // -----------------------------------------------------------

         Found += Record[i] + "\n";
      }
      Found += "\n<hr>\n\n";
   }
}


// --------------------------------------------------------------------
// Prints the found data out on to the new window.
//
// inputs:  The data via the global Found.
// ouputs:  Found data into a new HTML window.
// actions: Opens a new window and places the new HTML page into it. 
// returns: none
// --------------------------------------------------------------------
function PrintOut(typ, finding) {
  var Head = "";  // To be filled in when we have # of Matches
  var Foot = "";  // To be filled in when we have # of Matches
  var Many = "match";
  if(Matches != 1) {
     Many += "es";
  }

  Head = "<html><head><title>"+Matches+" - "+Many+" found in file: ";
  Head += link+"</title>\n";
  Head += '<script language="JavaScript" typ ="text/javascript">\n';
  Head += '<!-- Hide from non-JS browsers\n';
  Head += "var Matches = "+Matches+"\n\n";
  Head += 'window.status="'+Matches;
  Head += ' - Carroll Amateur Radio Emergency Team Members Found."\n\n';
  Head += 'function Click() {\n  window.status="Click here to view larger image."\n}\n\n';
  Head += "function Base() {\n";
  Head += '  window.status="'+Matches+' - Carroll Amateur Radio Emergency Team Members Found."\n';
  Head += '}\n// -->\n </script></head>\n';
  Head += '<body bgcolor="#bbffdd">\n';
  Head += '<center><font face="arial">\n';
  Head += '<h2>\n';
  Head += '<script language="JavaScript">\n   ';
  Head += "document.write(document.title);\n";
  Head += "</script></h2>\n\n";
  Head += '</h4><b>Matching: '+finding+"</b></h4>\n";
  Head += '';
  Head += '';
  Head += '</font><hr><br>\n';
  Head += '<br></center><pre>\n';

  Foot = '<form>\n';
  Foot += '<input type="Button" name="Close" value="Close Me" ';
  Foot += 'onclick="window.close();">\n</form>\n<br><br>';
  Foot += '</pre></body></html>\n';
  
  // ------------------------------------------------------------------
  // Done with the searching, display the found data in a child window
  // ------------------------------------------------------------------
    var Many = "Match"; if(Matches != 1) { Many += "es"; }
    
    if(typ == "L") {
       Found += "<br><br>\n\n";
    }
    
    if(typ == "R") {
       Found += "\n\n";
    }
    Found += "<br><hr>";
    Found += Matches+" "+Many+" found. ";
    Found += " &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; ";
    Found += "Pfind.js Ver 2.30 - copyright &copy; Circle Software 2002";
    Found += "<hr><br>";

    var Text = Head + Found + Foot;
    var PfWin = window.open("", "Pfind");
    PfWin.document.write(Text);
    PfWin.document.close();
    PfWin.focus();
  // ------------------------------------------------------------------
}



// ----------------------------------------------------------
// Displays a message & allows an exit from this code
// inputs:  Message text to display
// outputs: Displays the message & wait for key inputs
// actions: Returns to this code, or to previous html page
// returns: none
// ----------------------------------------------------------
function DeBug(txt) {
  var A = prompt(txt, "Continue/Exit == Enter/X-key.");
  if(A== "X" || A== "x") { // Go back to the LAST safe page!
    javascript:history.go(-1);

    // and just to be sure...(This causes an error due to "TimeOut")
    window.setTimeOut("Debug('Looping Error!');", 1000);
  }
}



// --------------------------------------------------------------------
// Return the data the user wants with the key-words hilighted.
//
// inputs:  The data record found, the key-words, the record length
// ouputs:  none
// actions: Adds hi-lighting to the key words in the Record. 
// returns: the Record array for this record.
// --------------------------------------------------------------------
function HiLight(Record, finds, RecLn) {
   var pntr = new Array();
   var stmp = "";
   var yes = 1;
   var Tmpt = "";
   
   for (var i=0; i<finds.length; ++i) {
      pntr[i] = -1;
   }

   for(var j=0; j<RecLn; ++j) {
      yes = 1;
      Tmpt = Record[j].toLowerCase(); // convert DB line to lowercase
      for(var i=0; i<finds.length; ++i) {
         pntr[i] = Tmpt.indexOf(finds[i]);
      }
         
      for(var i=0; i<finds.length; ++i) {
         if(pntr[i] == -1)
            yes = 0;
      }
      
      if(yes) {
         stmp = "<font color='red'><b>"+Record[j]+"</b></font>";
         Record[j] = stmp;
      }
   }
   return Record;
}


// ------------------------------------------------------
// To replace things like &gt; and &lt; with > and <
//
// Inputs:
//        Stng - the string to be searched & fixed
//        Fnd  - the characters to be replaced (found)
//        Rep  - The character(s) to replace Fnd with.
//
// Return: The fixed string.
// ------------------------------------------------------
function ReplaceIt(Stng, Fnd, Rep) {
   /*
   while(Stng.indexOf(Fnd) != -1) {
      var pntr = Stng.indexOf(Fnd);
      var stn = Stng.substring(0, pntr);
      var flen = Fnd.length;
      stn += Rep;
      stn += Stng.substring(pntr+flen, Stng.length);
      Stng = stn;
   }
   */
              
   // Or using regular expressions & .replace
   var Tmps = new RegExp(Fnd, "g");
   Stng = Stng.replace(Tmps, Rep);

   return(Stng);
}

