//
// AirLook.java - defines top level applet class for Airport Lookup Tool
//
//  Copyright (c) 1996 by Philip Garnatz, Garnatz and Grovender, Inc.
//  All Rights Reserved
//
// references to Java packages used
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.applet.Applet;
//import FileBlock;
//
   public class AirLook4 extends JApplet implements ActionListener {

        // member data
        JTextField       textField;
        JTextArea        outField;
        JButton          apt_button;
        JButton          cty_button;
        JButton          clr_button;

        // only works in appletviewer
        //final static int _width=550, _height=350;

        FileBlock master_i = new FileBlock();       
        FileBlock data_blk = new FileBlock();       
        FileBlock data_blk3 = new FileBlock();       
        int i = 0;
        int ix = 0;
        int ixm = 0;
        int lflag = 1;
	Color ltgreen = new Color(128, 255, 153);
	Color ltgold = new Color(255, 255, 204);

        public void init(){
           //resize(_width, _height);                // size the app window
           textField=new JTextField();             // input field
           textField.setText("msp");              // sample start
           textField.setBorder(new LineBorder(Color.gray, 3));
           textField.addActionListener(this);
           Font f = new Font("Courier", Font.BOLD, 14);
           this.getContentPane().setFont(f);
           textField.setFont(f);
	   Color gold = new Color(255, 222, 173);
           JPanel buttonbar = new JPanel();
           buttonbar.setLayout(new GridLayout(2,1));
           JPanel topbar = new JPanel();
           GridBagLayout gbl = new GridBagLayout();
           GridBagConstraints gbc = new GridBagConstraints();
           topbar.setLayout(gbl);
           topbar.setBackground(Color.white);
              // text field
           gbc.weightx = 1;
           gbc.ipadx = 5;
           gbc.fill = GridBagConstraints.HORIZONTAL;
           gbl.setConstraints(textField, gbc);
           topbar.add(textField);
              // lookup code button
           apt_button=new JButton("lookup by airport code");
           apt_button.setBackground(ltgreen);
           buttonbar.add(apt_button);
              // lookup city
           cty_button=new JButton("lookup by city name");
           cty_button.setBackground(ltgold);
           cty_button.addActionListener(this);
           apt_button.addActionListener(this);
           buttonbar.add(cty_button);
              // add buttonbar to topbar
           gbc.weightx = 0;
           gbc.fill = GridBagConstraints.NONE;
           gbl.setConstraints(apt_button, gbc);
           gbl.setConstraints(buttonbar, gbc);
           topbar.add(buttonbar);
              // clear button
           clr_button = new JButton("Clear");
           clr_button.setBackground(gold);
           gbc.gridwidth = GridBagConstraints.REMAINDER;
           gbl.setConstraints(clr_button, gbc);
           topbar.add(clr_button);
           clr_button.addActionListener(this);

           this.getContentPane().setLayout(new BorderLayout());          // create a layout mgr
           // setBackground(Color.white);
           this.setBackground(gold);
           this.getContentPane().add("North", topbar);

           outField=new JTextArea(7,40);           // output lines
           outField.setEditable(false);
           outField.setBackground(ltgold);
           outField.setFont(f);

           JScrollPane jspane = new JScrollPane();
           jspane.getViewport().add(outField);

           master_i = new FileBlock(this.getDocumentBase(), "air/air.ix", 11);
           lookIt();
           this.getContentPane().add("Center", jspane);

        } // end of init

        // called to look up a new code
        public void lookIt(){
           String s=textField.getText().toUpperCase();  // get user input
           ixm = master_i.BinarySearch(s, 3, 0);
           String file2 = "air/air." + master_i.substring(ixm, 5, 7);
           if(!file2.equals(data_blk.fname())) {
              data_blk = new FileBlock(this.getDocumentBase(), file2, 80);
           }
           ixm = data_blk.BinarySearch(s, 3, 0);

           if(FileBlock.StrComp (data_blk.substring(ixm, 0, 3), s) == 0) {
              outField.append
                 (" Here is the airport for the code " + s +"\n");
              outField.append
                 (data_blk.substring(ixm, 0, 80).trim()+"\n");
              int newlen = outField.getText().length();
              outField.select(newlen, newlen);

           } else {

              outField.append
                 (" No exact match found for "+ s +", here are the closest:\n");
              int ixl = ixm-2; if(ixl<0) ixl = 0;
              int ixh = ixm+3;
              if(ixh > data_blk.length()) ixh = data_blk.length();
              for(ix=ixl; ix<ixh; ix++){
                 outField.append
                    (data_blk.substring(ix, 0, 80).trim() +"\n");
              }
              outField.append (" --\n");
              int newlen = outField.getText().length();
              outField.select(newlen, newlen);

           }
        }

        public void lookName(){
           String s=textField.getText().toUpperCase();  // get user input
           char ch1;
           try {ch1 = s.charAt(0);}
           catch(StringIndexOutOfBoundsException e) { ch1 = ' ';}
           if ( ch1 < 'A' || ch1 > 'Z' ) {
              outField.append
              (" Lookup city name - first letter must be [A-Z]: " + ch1 + "\n");
              return;
           }
           String file3 = "air/cty." + ch1;
           if(!file3.equals(data_blk3.fname())) {
              data_blk3 = new FileBlock(this.getDocumentBase(), file3, 40);
           }
           ixm = data_blk3.BinarySearch( s, 32, 8);
           int ixl = ixm-2; if(ixl<0) ixl = 0;
           int ixh = ixm+4;
           if(ixh > data_blk3.length()) ixh = data_blk3.length();

           if(FileBlock.StrComp (data_blk3.substring(ixm, 8, 40), s) == 0) {
              outField.append
                 (" Here is an airport or city code for city name: " + s +"\n");
              ixl = ixm;
              ixh = ixm;
              for (ix=ixm-1; ix>0; ix-- ) { 
                 if(Math.abs(
                    FileBlock.StrComp(data_blk3.substring(ix, 8, 40), s)
                     ) == 2) break;
              }
              if( ix+1 < ixl ) ixl = ix+1;
              for (ix=ixm+1; ix<data_blk3.length(); ix++ ) { 
                 if(Math.abs(
                    FileBlock.StrComp(data_blk3.substring(ix, 8, 40), s)
                    ) == 2) break;
              }
              if( ix > ixh ) ixh = ix;
           } else {
              outField.append (" Here are airport or city codes for the "
                  + "closest matches to: "+ s +"\n");
           }
           for(ix=ixl; ix<ixh; ix++){
              s=data_blk3.substring(ix, 0, 4); // get 3 letter code
              ixm = master_i.BinarySearch( s, 3, 0);
              String file2 = "air/air." +
                           master_i.substring(ixm, 5, 7);
              if(!file2.equals(data_blk.fname())) {
                 data_blk = new FileBlock(this.getDocumentBase(), file2, 80);
              }
              ixm = data_blk.BinarySearch(s, 3, 0);
              outField.append (data_blk.substring(ixm, 0, 80).trim() +"\n");
           }
           outField.append (" --\n");
           int newlen = outField.getText().length();
           outField.select(newlen, newlen);
        }

        public void actionPerformed(ActionEvent event) {
           if(event.getSource() == apt_button)
           {
              apt_button.setBackground(ltgreen);
              cty_button.setBackground(ltgold);
              lflag = 1;
              lookIt();
           }

           if(event.getSource() == cty_button)
           {
              apt_button.setBackground(ltgold);
              cty_button.setBackground(ltgreen);
              lflag = 2;
              lookName();
           }

           if(event.getSource() == clr_button)
           {
              outField.setText("");
              textField.setText("");
           }
 
           if( event.getSource() == textField ) {
               if(lflag == 1) {
                  lookIt();
               } else {
                  lookName();
               }
           }
        }

} // end class AirLook4

//
// FileBlock.java - defines a String manipulation class for Airport Lookup Tool
//
//  Copyright (c) 1997 by Philip Garnatz, Garnatz and Grovender, Inc.
//  All Rights Reserved
//
//
class FileBlock 
   {
        // member data
   String data_blk;
   String file_sav;
   int lenrec;

   public FileBlock () {
      data_blk = null;
      file_sav = " ";
      lenrec = 0;
   }

   public FileBlock (URL base, String file, int lenrec) {
      data_blk = ReadFileURL(base, file, lenrec);
      file_sav = file;
      this.lenrec = lenrec;
   }

        // called to read in an index or data block
   String ReadFileURL(URL base, String file, int nbytes) {
      StringBuffer data1 = new StringBuffer(5000);
      boolean done = false;
      int i = 0;
           // DataInputStream fin = null;
      URL myURL = null;
      InputStream myinp = null;
      BufferedReader fin = null;
      String temp;

          // open URL and read from file
      try 
         {
         myURL = new URL(base, file);
         }
      catch (MalformedURLException e) 
         {
         System.out.println("Unexpected exception: " + e);
         System.exit(0);
         }

      try 
         {
         myinp = myURL.openStream();
         fin = new BufferedReader (new InputStreamReader(myinp));
         }
      catch (Exception e) 
         {
         System.out.println("Unexpected exception: " + e);
         System.exit(0);
         }

            // initial read
      temp = " ";
      try 
         {
         temp =  fin.readLine();
         }
         catch (Exception e) 
         {
              System.out.println("Unexpected exception: " + e);
              done = true;
              // System.exit(0);
         }

         while(!done) 
         {
            int sl = temp.length();
            if (sl > nbytes ) sl = nbytes;
             data1.append(temp.substring(0,sl));
             if( sl < nbytes ) {
                 for( int j=sl; j<nbytes; j++) data1.append(" ");
             }
             i += nbytes;
             try {
              // read the whole file
                temp =  fin.readLine();
             }
             catch (Exception e) {
                System.out.println("Unexpected exception: " + e);
                done = true;
             }
             if( temp ==  null) {
                done = true;
             }  else {
                if(temp.length() <= 1) done = true;
             }
         }  // end while
      return data1.toString();
      }

       // called to look up a string
      public int BinarySearch(String s, int lk, int off)
         {
       //Arguments: 
       //           s   - String to search for (look in blk)
       //           lk  - search length within line
       //           off - search offset within line
           int it = 0;
           int ib = (data_blk.length()/lenrec)-1;
           int il = 0;
           int ix;
           while(it <= ib) {
              il = (it+ib)/2 + 1;
              if(il > ib) il = ib;
              ix = il * lenrec;
              int cpr = StrComp(s, 
                 data_blk.substring(ix+off,ix+lk+off).toUpperCase());
              if ( cpr == 0) {
                 return il;
              } else {
                 if( it == ib ) return il;
                 if ( cpr > 0) {
                    ib = il - 1;
                 }  else {
                    it = il;       // use it = il;  don't use: it = il + 1
                 }
              }
           }  // end while
        return il;
        }

        // called for string comparison

        public static int StrComp(String r, String s){
           int ll = r.length();
           if( s.length() < ll ) ll = s.length();
           for(int i=0; i < ll; i++) {
              char r1 = r.charAt(i);
              char s1 = s.charAt(i);
              if ( s1 < r1 ) return -2;
              if ( r1 < s1 ) return 2;
           }
        // exact match up to end of one string - check for non-trailing blanks
           if ( s.length() < r.length() ) {
              for(int i=ll; i < r.length(); i++) {
                 char r1 = r.charAt(i);
                 if( r1 != ' ') return -1;
              }
           } else if ( r.length() < s.length() ) {
              for(int i=ll; i < s.length(); i++) {
                 char s1 = s.charAt(i);
                 if( s1 != ' ') return 1;
              }
           }
           return 0;
        }

        public String substring(int line, int start, int end)
        {
           return data_blk.substring(line*lenrec+start, line*lenrec+end);
        }

        public String fname()
        {
           return file_sav;
        }

        public int length()
        {
           if(lenrec == 0) return 0;
           return data_blk.length()/lenrec;
        }

} // end class FileBlock


