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.