Client.


//********************************************************************

// client.java

//********************************************************************

// Implements the client side of a Java based client/server chat system.

//

// Version History:

// 1.00  M. Ayers  2/3/97

//        Base version, contains comments and 'looks nice'

//

// 1.01  M. Ayers  2/16/97

//        Added colors, added labels for title, channel, user.

//

// 1.02  M. Ayers  2/25/97

//        Added preferences for fonts and colors.

//

// 1.03  R. Ptashka 3/10/97

//        Integrated and re-implemented word wrapping.

//

// 1.04  M. Ayers  4/20/97

//        Added number of users per channel, and filtering status.

//********************************************************************





import  java.awt.*;

import  java.util.*;

import  java.applet.*;

import  java.io.*;

import  java.net.*;



public  class  client  extends  Applet  

  {

        TextArea messageDisplay;          // AWT Declarations.

        TextField channel, user, message;

        List channelList, userList;

        Button goChannel, addChannel, filter, unfilter, status, clear;

        Label titleLabel, channelLabel, userLabel;



        Socket network_client;      // Networking Declarations.

        DataInputStream net_input;

        PrintStream net_output;

        Font fnt;

        FontMetrics fm;

        Graphics g;





        String username, host, startchannel, fontname;  

               //Input Parameters

        Integer temp;

        int fontsize;

        Color color1, color2, color3, color4, color5, color6, color7,

              color8;

        boolean connected = false;

        writer w;



        public  Color stringColor(String  name)  

                {

                    if (name.equals("black")) {

                       return (Color.black);

                    } 

                    if (name.equals("blue")) {

                       return (Color.blue);

                    } 

                    if (name.equals("cyan")) {

                       return (Color.cyan);

                    } 

                    if (name.equals("darkGrey")) {

                       return (Color.darkGray);

                    } 

                    if (name.equals("gray")) {

                       return (Color.gray);

                    } 

                    if (name.equals("green")) {

                       return (Color.green);

                    } 

                    if (name.equals("lightGray")) {

                       return (Color.lightGray);

                    } 

                    if (name.equals("magenta")) {

                       return (Color.magenta);

                    } 

                    if (name.equals("orange")) {

                       return (Color.orange);

                    } 

                    if (name.equals("pink")) {

                       return (Color.pink);

                    } 

                    if (name.equals("red")) {

                       return (Color.red);

                    } 

                    if (name.equals("white")) {

                       return (Color.white);

                    } 

                    if (name.equals("yellow")) {

                       return (Color.yellow);

                    } 

                    return (Color.black);

                }

        // AWT Constructors, using Gridbag placements.



        public  Button makebutton(String  name,

                         GridBagLayout  gridbag, GridBagConstraints  c)  

                {

                    Button  button  =  new Button(name);

                    gridbag.setConstraints(button,  c);

                    add(button);

                    return (button);

                }

        public  TextArea  maketextarea(String  name, int rows, 

                              int columns,

                              GridBagLayout  gridbag,

                              GridBagConstraints  c)  

                {

                    TextArea  textarea  =  new TextArea(name, rows,

                                           columns);

                    gridbag.setConstraints(textarea,  c);

                    add(textarea);

                    return (textarea);

                }

        public  TextField  maketextfield(String  name, int columns,

                              GridBagLayout  gridbag,

                              GridBagConstraints  c)

                {

                    TextField  textfield  =  new TextField(name,

                                             columns);

                    gridbag.setConstraints(textfield,  c);

                    add(textfield);

                    return (textfield);

                }

         public  List  makelist(int rows,

                              GridBagLayout  gridbag,

                              GridBagConstraints  c)

                {

                    List  list  =  new List(rows, false);

                    gridbag.setConstraints(list,  c);

                    add(list);

                    return(list);

                }

         public  Label  makelabel(String name,

                              GridBagLayout  gridbag,

                              GridBagConstraints  c)

                {

                    Label  label  =  new Label(name);

                    gridbag.setConstraints(label,  c);

                    add(label);

                    return(label);

                }



        // Applet initialization.



    public  void  init()  

          {

                fontname = getParameter("FONTNAME");

                temp = new Integer (getParameter("FONTSIZE"));

                fontsize = temp.intValue();

                color1 = stringColor(getParameter("COLOR1"));

                color2 = stringColor(getParameter("COLOR2"));

                color3 = stringColor(getParameter("COLOR3"));

                color4 = stringColor(getParameter("COLOR4"));

                color5 = stringColor(getParameter("COLOR5"));

                color6 = stringColor(getParameter("COLOR6"));

                color7 = stringColor(getParameter("COLOR7"));

                color8 = stringColor(getParameter("COLOR8"));

                GridBagLayout  gridbag  =  new  GridBagLayout();

                    //User Interface setup.

                GridBagConstraints  c  =  new  GridBagConstraints();

                fnt = new Font(fontname,  Font.PLAIN,  fontsize);    

                    //Set font.

                setFont(fnt);

                setBackground (color2);

                setForeground (color1);

                setLayout(gridbag);

                c.weightx  =  6.0;

                c.fill = GridBagConstraints.BOTH;

                c.gridwidth  =  40;

                c.gridheight  =  9;

                c.weighty  =  1.0;

                c.insets.right = 5;

                c.insets.bottom = 5;

                c.insets.top = 5;

                c.insets.left = 5;

            messageDisplay  =  maketextarea("Message Display Area\n", 

                20, 40, gridbag, c);  

            messageDisplay.setEditable (false);

            g = messageDisplay.getGraphics();

            fm = g.getFontMetrics(fnt);



            messageDisplay.setBackground (color4);

            messageDisplay.setForeground (color3);

                c.weightx  =  1.0;

                c.insets.right = 0;

                c.insets.bottom = 0;

                c.insets.top = 0;

                c.insets.left = 0;

                c.gridwidth  =  GridBagConstraints.REMAINDER;

                c.gridheight  =  1;

                c.insets.right = 5;

                c.insets.top = 5;

            channelLabel = makelabel("Channel Information",gridbag,  c);   

                c.insets.top = 0;

            channel = maketextfield("Channel", 10,  gridbag,  c);   

            channel.setBackground (color6);

            channel.setForeground (color5);

            channelList = makelist(6,  gridbag,  c);   

            channelList.setBackground (color6);

            channelList.setForeground (color5);

                c.gridwidth  =  GridBagConstraints.RELATIVE;

            goChannel = makebutton("Go To Channel", gridbag, c);

            goChannel.setBackground (color8);

            goChannel.setForeground (color7);

                c.gridwidth  =  GridBagConstraints.REMAINDER;

            addChannel = makebutton("Add Channel", gridbag, c);

            addChannel.setBackground (color8);

            addChannel.setForeground (color7);

                c.insets.top = 5;

            userLabel = makelabel("User Information", gridbag, c);

                c.insets.top = 0;

            user = maketextfield("User", 10, gridbag, c);

            user.setBackground (color6);

            user.setForeground (color5);

                c.insets.top = 0;

            userList = makelist(6,  gridbag,  c);

            userList.setBackground (color6);

            userList.setForeground (color5);

                c.gridwidth  =  GridBagConstraints.RELATIVE;

            filter = makebutton("Filter User", gridbag, c);

            filter.setBackground (color8);

            filter.setForeground (color7);

                c.gridwidth  =  GridBagConstraints.REMAINDER;

            unfilter = makebutton("Unfilter User", gridbag, c);

            unfilter.setBackground (color8);

            unfilter.setForeground (color7);

                c.gridwidth  =  GridBagConstraints.REMAINDER;

                c.insets.top = 5;

            status = makebutton("Check Status", gridbag, c);

            status.setBackground (color8);

            status.setForeground (color7);

                c.insets.top = 0;

                c.gridwidth  =  40;

                c.insets.bottom = 5;

                c.insets.left = 5;

                c.weightx  =  6.0;

            message = maketextfield("Enter Text here", 40, gridbag, c);

            message.setBackground (color6);

            message.setForeground (color5);

                c.insets.left = 0;

                c.insets.bottom = 5;

                c.weightx  =  1.0;

            clear = makebutton("Clear Text Area", gridbag, c);

            clear.setBackground (color8);

            clear.setForeground (color7);

                c.gridwidth  =  GridBagConstraints.REMAINDER;

                // Finished User Interface setup.



            // Get start parameters and set up initial state.

            host = getParameter("HOST");

            username = getParameter("USERNAME");

            userList.addItem(username);

            userList.select(0);

            startchannel = getParameter("STARTCHANNEL");

            channelList.addItem(startchannel);

            channelList.select(0);

       }   



    public  void  start()  

          {

        if (connect())   //Check for connection creation.

          {

              connected = true;

              w = new writer(this);

              w.start();

          }

        else

          {

              username = "* NOT CONNECTED *";

              return;

          }

       }  // End Init.



    boolean connect()   //Create network connaction.

      {

          messageDisplay.appendText("<<<< Connecting user " + username + 

              " to " + host + " >>>>\n");

          messageDisplay.selectAll();

          try 

              {

                  network_client = new Socket(host, 1111); 

              }

          catch (IOException e)

              {

                  messageDisplay.appendText("<<<< Error...could not 

                      connect to host " + e + " >>>>\n");

                  return false;

              }

          messageDisplay.appendText("<<<< Connected to server >>>>\n");

          try

              {

                net_input =

                   new DataInputStream(network_client.getInputStream());

                net_output = 

                   new PrintStream (network_client.getOutputStream());

              }

          catch (IOException e ) 

              {

                  messageDisplay.appendText("<<<< Server is NOT ready

                      >>>>\n");

                  messageDisplay.selectAll();

                  return false;

              }

          write_net_output(username);

          write_net_output(startchannel);

          return true;

      }   // End connect.



    String read_net_input()  //Read input from network, 

                               one line at a time

      {

          try

              {

                  return net_input.readLine();

              }

          catch (IOException e)

              {

                  return null;  

              }

      }



    void write_net_output(String string)  //Write output to network,

                                            one line at a time.

      {

          net_output.println(string);

          net_output.flush();

      }

      

    void close_server()   //Close network connection.

      {

          try  

              {

                  network_client.close();  

              }

          catch (Exception e)    

              {

                  messageDisplay.appendText("<<<< Unable to close server

                      >>>>\n");  

              }

      }

      

    void word_wrap(String inputdata){



      String outputdata="";     //Text to be printed

      String tempdata;          //Temporary data for length counting

      int counter;

      Dimension dm=messageDisplay.size();

      int area_width;           //Width of output string in characters

      int current_width;

      int string_width;         //Width of output string in pixels



      



      tempdata=inputdata;

      string_width = fm.stringWidth(tempdata);



      while (string_width > (dm.width-25))

        {

          tempdata=tempdata.substring(0, tempdata.length()-1);

          string_width = fm.stringWidth(tempdata);

        } /* endwhile */

      area_width = tempdata.length();





      if (inputdata.length() > area_width)

        {

          tempdata = inputdata;

          while (inputdata.length() > area_width)

            {

              tempdata = inputdata.substring (0, area_width);

              current_width = tempdata.lastIndexOf(' ')+1;

              outputdata = inputdata.substring(0, current_width)+ "\n";

              messageDisplay.appendText(outputdata);

              messageDisplay.selectAll();

              inputdata = inputdata.substring(current_width);

              tempdata = inputdata;

              string_width = fm.stringWidth(tempdata);

              while (string_width > (dm.width-25))

                {

                  tempdata=tempdata.substring(0, tempdata.length()-1);

                  string_width = fm.stringWidth(tempdata);

                  area_width = tempdata.length();

                } /* endwhile */

              if (area_width > inputdata.length())

                {

                  messageDisplay.appendText(inputdata);

                  messageDisplay.selectAll();

                  break;

                } /* endif */

            } /* endwhile */

        }

      else

        {

          messageDisplay.appendText(inputdata);                  

          messageDisplay.selectAll();

        }

     }  //end word_wrap  

      

    public boolean handleEvent(Event e)   //Handlers for all AWT events.

      {

        String string = "error";

          switch (e.id) 

              {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

                case Event.KEY_RELEASE:

                  if (e.target.equals(channel))  //Hilite matching entry

                                                  in channel list.

                    {

                      for (int i = 0; i < channelList.countItems(); ++i) 

                        {

                          if (channelList.getItem(i).startsWith( 

                                channel.getText())) 

                            {

                              channelList.select(i);

                            }

                        }

                    }

                  if (e.target.equals(user))  //Hilite matching entry

                                                in user list.

                    {

                      for (int i = 0; i < userList.countItems(); ++i) 

                        {

                          if (userList.getItem(i).startsWith(  

                                user.getText())) 

                            {

                              userList.select(i);

                            }

                        }

                    }

                  break;

                case Event.LIST_SELECT:

                  if (e.target.equals(channelList)) //Display selected

                                                    item in channel box.

                    {

                     string = channelList.getSelectedItem();

                     if (string.indexOf(" ") != -1)

                      {

                       string = string.substring(0,string.indexOf(" "));

                      }

                     channel.setText(string);

                    }

                  if (e.target.equals(userList))   //Display selected

                                                     item in user box.

                    {

                     string = userList.getSelectedItem();

                     if (string.indexOf(" ") != -1)

                      {

                       string = string.substring(0,string.indexOf(" "));

                      }

                     user.setText(string);

                    }

                  break;

                case Event.ACTION_EVENT:    //Button handlers.

                  if (e.target.equals(goChannel)) 

                    {

                      if (connected)   

                        {

                          string = channelList.getSelectedItem();

                          if (string.indexOf(" ") != -1)

                            {

                              string = 

                              string.substring(0,string.indexOf(" "));

                            }

                          write_net_output("GO&" + string);   

                        }

                      messageDisplay.appendText("<<<< Go to channel " +

                                                 string + " >>>>\n");

                      messageDisplay.selectAll();

                    }

                  if (e.target.equals(addChannel)) 

                    {

                      int j = 0;

                      for (int i = 0; i < channelList.countItems(); ++i) 

                        {

                          string = channelList.getItem(i);

                          if (string.indexOf(" ") != -1)

                            {

                              string =

                              string.substring(0,string.indexOf(" "));

                            }

                          if (string.equals( channel.getText() )) 

                            {

                             j = 1;

                             messageDisplay.appendText("<<<< Channel " +

                             channel.getText() + 

                             " already exists. >>>>\n");

                            }

                        }

                      if (j == 0) 

                        {

                         if (connected)   

                            {

                              write_net_output("ADDCHANNEL&" +

                                                channel.getText());   

                            }

                         messageDisplay.appendText("<<<< Add channel " +

                                                    channel.getText() +

                                                    " >>>>\n");

                         messageDisplay.selectAll();

                        }

                    }

                  if (e.target.equals(filter)) 

                    {

                      if (connected)   

                        {

                          string = userList.getSelectedItem();

                          if (string.indexOf(" ") != -1)

                            {

                              string = 

                              string.substring(0,string.indexOf(" "));

                            }

                          write_net_output("FILTER&" + string);   

                        }

                      messageDisplay.appendText("<<<< Filter User " +

                                                 string + " >>>>\n");

                      messageDisplay.selectAll();

                    }

                  if (e.target.equals(unfilter)) 

                    {

                      if (connected)   

                        {

                          string = userList.getSelectedItem();

                          if (string.indexOf(" ") != -1)

                            {

                              string =

                              string.substring(0,string.indexOf(" "));

                            }

                          write_net_output("UNFILTER&" + string);   

                        }

                      messageDisplay.appendText("<<<< Unfilter User " +

                                                 string + " >>>>\n");

                      messageDisplay.selectAll();

                    }

                  if (e.target.equals(status)) 

                    {

                      if (connected)   

                        {

                          write_net_output("STATUS&");   

                        }

                      messageDisplay.appendText("<<<< Server and User

                                                 Status >>>>\n");

                      messageDisplay.selectAll();

                    }

                  if (e.target.equals(clear)) 

                    {

                      messageDisplay.setText("");

                      message.setText("");

                    }

                  if (e.target.equals(message)) 

                    {

                      String text= message.getText();

                      if (text.equals(""))    //Check for empty message.

                        {

                        } 

                      else 

                        {

                          if (connected)   

                            {

                              write_net_output("TEXT&" +

                                                message.getText());

                                  //Send message to server. 

                              word_wrap("You say: " +

                                         message.getText() + "\n");

                            }

                          else

                            {

                              messageDisplay.appendText("<<<< No

                                  connection.  Can't send message

                                  >>>>\n");

                            }

                          message.setText("");

                        }

                    }

                  break;

                default:

	          return false;

              }

          return false;

      }  // End HandleEvent.



    public void display()  //Update user interface based on network 

                             activity.

        {

          String string, channel, number;

          if (w.net_line.startsWith("TEXT&")) 

            {

              word_wrap(w.net_line.substring(5) + "\n");

            } 

          if (w.net_line.startsWith("GO&")) 

            {

              for (int i = 0; i < channelList.countItems(); ++i) 

                {

                  string = channelList.getItem(i);

                  if (string.indexOf(" ") != -1)

                    {

                      string = string.substring(0,string.indexOf(" "));

                    }

                  if (string.equals(w.net_line.substring(3))) 

                    {

                      channelList.select(i);

                    }

                }

              userList.clear();

              userList.addItem(username);

              userList.select(0);



            }

          if (w.net_line.startsWith("ADDCHANNEL&")) 

            {

              int j = 0;

              channel = w.net_line.substring(11);

              if (channel.indexOf("&") != -1)

                {

                  number = channel.substring(channel.indexOf("&") + 1);

                  channel = channel.substring(0,channel.indexOf("&"));

                }

              else

                {

                  number = "";

                }

              for (int i = 0; i < channelList.countItems(); ++i) 

                {

                  string = channelList.getItem(i);

                  if (string.indexOf(" ") != -1)

                    {

                      string = string.substring(0,string.indexOf(" "));

                    }

                  if (string.equals(channel)) 

                    {

                      channelList.replaceItem(channel + "     ( " +

                                              number + " )", i); 

                      j = 1;

                    }

                }

                if (j == 0) 

                  {

                    channelList.addItem(channel + "     ( " + number +

                                        " )"); 

                  }

            } 

          if (w.net_line.startsWith("ADDUSER&")) 

            {

              int j = 0;

              for (int i = 0; i < userList.countItems(); ++i) 

                {

                  if (userList.getItem(i).equals(

                        w.net_line.substring(8))) 

                    {

                      j = 1;

                    }

                }

                  if (j == 0) 

                    {

                      userList.addItem(w.net_line.substring(8));  

                    }

            } 

          if (w.net_line.startsWith("REMOVECHANNEL&")) 

            {

              for (int i = 0; i < channelList.countItems(); ++i) 

                {

                  string = channelList.getItem(i);

                  if (string.indexOf(" ") != -1)

                    {

                      string = string.substring(0,string.indexOf(" "));

                    }

                  if (string.equals(w.net_line.substring(14))) 

                    {

                      channelList.delItem(i); 

                    }

                }

            } 

          if (w.net_line.startsWith("REMOVEUSER&")) 

            {

              for (int i = 0; i < userList.countItems(); ++i) 

                {

                  string = userList.getItem(i);

                  if (string.indexOf(" ") != -1)

                    {

                      string = string.substring(0,string.indexOf(" "));

                    }

                  if (string.equals(w.net_line.substring(11))) 

                    {

                      userList.delItem(i);  

                    }

                }

            } 

          if (w.net_line.startsWith("FILTER&")) 

            {

              for (int i = 0; i < userList.countItems(); ++i) 

                {

                  string = userList.getItem(i);

                  if (string.indexOf(" ") != -1)

                    {

                      string = string.substring(0,string.indexOf(" "));

                    }

                  if (string.equals(w.net_line.substring(7))) 

                    {

                      userList.replaceItem(w.net_line.substring(7) +

                                           " - Filtered", i); 

                    }

                }

              messageDisplay.appendText("<<<< Filtering User " +

                                        w.net_line.substring(7) +

                                        " >>>>\n");

              messageDisplay.selectAll();

            } 

          if (w.net_line.startsWith("UNFILTER&")) 

            {

              for (int i = 0; i < userList.countItems(); ++i) 

                {

                  string = userList.getItem(i);

                  if (string.indexOf(" ") != -1)

                    {

                      string = string.substring(0,string.indexOf(" "));

                    }

                  if (string.equals(w.net_line.substring(9))) 

                    {

                      userList.replaceItem(w.net_line.substring(9), i); 

                    }

                }

              messageDisplay.appendText("<<<< Stopped Filtering User " +

                                        w.net_line.substring(9) +

                                        " >>>>\n");

              messageDisplay.selectAll();

            } 

        }  // End display.



    public void stop()

        {

          close_server();

          w.stop();

        }

  }  // End client.





class writer extends Thread    //Thread to read from network, prevents UI from blocking while reading from network.

  {

    String net_line = "";

    client c;



    public writer(client c)

      {

        this.c = c;

      }



    public void run()

      {

        while (true)

          {

            String input = c.read_net_input();  //Read a line from the

                                                  network

            net_line = input;

            c.display();  //Call code in UI to update display.

            System.out.println("String <" + input + ">");

          }

      }

  }  // End writer.