--- /dev/null
+import java.awt.*;
+
+public class NamedPanel extends Panel {
+ public static final int LEFT=0, CENTER=1, RIGHT=2;
+ public static final int TOP=0, MIDDLE=1, BOTTOM=2;
+
+ boolean clean;
+
+ int x_tl, y_tl;
+ int x_tlm, y_tlm;
+ int x_trm, y_trm;
+ int x_tr, y_tr;
+ int x_br, y_br;
+ int x_bl, y_bl;
+
+ String name;
+ int h_alignment, v_alignment;
+
+ int name_width, name_height, name_a_height;
+ Color back, nw, se;
+ Insets border, pane;
+ Insets theInsets;
+ Dimension old_size;
+
+ NamedPanel( String name ) {
+ this( name, LEFT, MIDDLE );
+ }
+
+ NamedPanel( String name, int h_alignment ) {
+ this( name, h_alignment, MIDDLE );
+ }
+
+ NamedPanel( String name, int h_alignment, int v_alignment ) {
+ border = new Insets( 4, 4, 4, 4 );
+ pane = new Insets( 4, 4, 4, 4 );
+
+ theInsets = addInsets( border, pane );
+
+ this.name = name;
+ this.h_alignment = h_alignment;
+ this.v_alignment = v_alignment;
+ clean = false;
+ }
+
+ public void addNotify() {
+ super.addNotify();
+ fontBox();
+
+ theInsets = addInsets( border, pane );
+ theInsets.top += name_height;
+ validate();
+ }
+
+ final public Insets addInsets( Insets i1, Insets i2 )
+ {
+ return new Insets( i1.top + i2.top, i1.left + i2.left, i1.bottom + i2.bottom, i1.right + i2.right );
+ }
+
+ public Insets insets() {
+ return theInsets;
+ }
+
+ public Insets getInsets() {
+ return theInsets;
+ }
+
+ public void setLabel( String name ) {
+ this.name = name;
+ clean = false;
+ repaint();
+ }
+
+ public void align( int alignment ) {
+ h_alignment = alignment;
+ clean = false;
+ }
+
+ public void paint( Graphics g ) {
+ super.paint( g );
+
+ Dimension tmp = size();
+
+ if( (!clean) || ((tmp.width != old_size.width) || (tmp.height != old_size.height) ) ) {
+ old_size = tmp;
+
+ calculateCrap();
+ clean = true;
+// g.clearRect( 0, 0, tmp.width, tmp.height);
+ }
+
+ g.setColor( nw );
+ g.drawLine( x_tl, y_tl, x_tlm, y_tlm );
+ g.drawLine( x_trm, y_trm, x_tr, y_tr );
+ g.drawLine( x_bl, y_bl, x_tl, y_tl );
+
+ g.drawLine( x_tr-1, y_tr+1, x_br-1, y_br-1 );
+ g.drawLine( x_bl+1, y_bl-1, x_br-1, y_br-1 );
+
+ g.drawLine( x_trm, y_trm, x_trm, y_trm+1 );
+
+ g.setColor( se );
+ g.drawLine( x_tl+1, y_tl+1, x_tlm-1, y_tlm+1 );
+ g.drawLine( x_trm+1, y_trm+1, x_tr-1, y_tr+1 );
+ g.drawLine( x_bl+1, y_bl-1, x_tl+1, y_tl+1 );
+
+ g.drawLine( x_tr, y_tr+1, x_br, y_br );
+ g.drawLine( x_bl+1, y_bl, x_br, y_br );
+
+ g.drawLine( x_tlm, y_tlm, x_tlm, y_tlm+1 );
+
+ g.setColor( getForeground() );
+ g.drawString( name, x_tlm + 5, border.top+name_a_height );
+ }
+
+ void fontBox() {
+ FontMetrics fm = getFontMetrics( getFont() );
+
+ name_height = fm.getMaxAscent() + fm.getMaxDescent();
+ name_a_height = fm.getMaxAscent();
+ name_width = fm.stringWidth( name );
+ }
+
+ void calculateCrap() {
+ fontBox();
+
+ back = getBackground();
+ se = back.brighter();
+ nw = back.darker();
+
+ x_tl = border.left;
+ y_tl = border.top;
+
+ switch( v_alignment ) {
+ default: break;
+ case MIDDLE: y_tl += name_height/2; break;
+ case BOTTOM: y_tl += name_height; break;
+ }
+
+ x_tr = old_size.width - border.left;
+ y_tr = y_tl;
+
+ x_br = x_tr;
+ y_br = old_size.height - border.bottom;
+
+ x_bl = x_tl;
+ y_bl = y_br;
+
+ y_tlm = y_trm = y_tl;
+
+ switch( h_alignment ) {
+ default:
+ x_tlm = x_tl + 20;
+ x_trm = x_tlm + name_width + 8;
+ break;
+ case CENTER:
+ x_tlm = (x_tl + (x_tr - x_tl)/2) - name_width/2 - 5;
+ x_trm = x_tlm + name_width + 8;
+ break;
+ case RIGHT:
+ x_trm = x_tr - 5;
+ x_tlm = x_trm - (name_width + 8);
+ break;
+ }
+ }
+ }
--- /dev/null
+/* PairPanel.java
+ * Utility class so I don't have to think about GridBagLayout
+ */
+
+import java.awt.*;
+
+public class PairPanel extends Panel
+ {
+ GridBagLayout gbLayout;
+ GridBagConstraints gbLeft, gbRight;
+
+ PairPanel() {
+ this( 0, 0 );
+ }
+
+ PairPanel( int x, int y ) {
+ setLayout( gbLayout = new GridBagLayout() );
+
+ gbLeft = new GridBagConstraints();
+ gbLeft.gridwidth = 1;
+ gbLeft.ipadx = x;
+ gbLeft.ipady = y;
+ gbLeft.anchor = GridBagConstraints.EAST;
+
+ gbRight = new GridBagConstraints();
+ gbRight.ipadx = x;
+ gbRight.ipady = y;
+ gbRight.gridwidth = GridBagConstraints.REMAINDER;
+ gbRight.anchor = GridBagConstraints.WEST;
+ }
+
+ public void addLeft( Component c ) {
+ gbLayout.setConstraints( c, gbLeft );
+ add( c );
+ }
+
+ public void addRight( Component c ) {
+ gbLayout.setConstraints( c, gbRight );
+ add( c );
+ }
+ }
--- /dev/null
+import java.awt.*;
+
+public class Panel3D extends Panel
+ {
+ static final int LOWER = 1;
+ static final int HIGHER = 0;
+ static final int RIDGE = 2;
+
+ public Insets outside, ridge, plane;
+ int state = 0;
+
+ public Panel3D( )
+ {
+ setUp( HIGHER, null, null, null );
+ }
+
+ public Panel3D( int state )
+ {
+ setUp( state, null, null, null );
+ this.state = state;
+ }
+
+ public Panel3D( int state, Insets outside )
+ {
+ setUp( state, outside, null, null );
+ }
+
+ public Panel3D( int state, Insets outside, Insets ridge )
+ {
+ setUp( state, outside, ridge, null );
+ }
+
+ public Panel3D( int state, Insets outside, Insets ridge, Insets plane )
+ {
+ setUp( state, outside, ridge, plane );
+ }
+
+ public void setUp( int state, Insets outside, Insets ridge, Insets plane )
+ {
+ this.state = state;
+
+ this.outside = (outside == null) ? new Insets( 3, 3, 3, 3 ) : outside;
+ this.ridge = addInsets( this.outside, (ridge == null) ? new Insets( 3, 3, 3, 3 ) : ridge );
+ this.plane = addInsets( ( (state & RIDGE) == RIDGE) ? this.ridge: this.outside, (plane == null ) ? new Insets( 4, 4, 4, 4 ) : plane );
+ }
+
+ final public Insets addInsets( Insets i1, Insets i2 )
+ {
+ return new Insets( i1.top + i2.top, i1.left + i2.left, i1.bottom + i2.bottom, i1.right + i2.right );
+ }
+
+ public void paint( Graphics g )
+ {
+ super.paint( g );
+ Dimension d = size();
+ Color bg = getBackground();
+
+ g.setColor(bg);
+ g.draw3DRect( outside.left, outside.top, d.width - outside.right - outside.left, d.height - outside.top - outside.bottom, (state & LOWER) != LOWER );
+ if( (state & RIDGE) == RIDGE )
+ g.draw3DRect( ridge.left, ridge.top, d.width - ridge.right - ridge.left, d.height - ridge.top - ridge.bottom, (state & LOWER) == LOWER );
+
+ }
+
+ public Insets insets() {
+ return plane;
+ }
+
+ public Insets getInsets() {
+ return plane;
+ }
+ }
+
+
--- /dev/null
+/* citFrame.java
+ * shell for citPanel, so we can be an applet and application
+ */
+
+import java.awt.*;
+
+public class citFrame extends Frame {
+ citPanel cp;
+
+ public citFrame() {
+ super( "Citadel!" );
+
+ setLayout( new BorderLayout() );
+
+ add( "Center", cp = new citPanel() );
+
+ resize( 400, 400 );
+ show();
+ }
+
+ public boolean handleEvent( Event e ) {
+ if( e.id == Event.WINDOW_DESTROY ) {
+ if( citadel.me.theNet != null )
+ citadel.me.theNet.println( "QUIT" );
+ System.out.println( "Bye bye!" );
+ System.exit( 0 );
+ }
+ return super.handleEvent( e );
+ }
+}
+
--- /dev/null
+/* citPanel.java
+ * The daddy of the mack daddy.
+ */
+
+import java.awt.*;
+
+public class citPanel extends Panel {
+ loginPanel lp;
+ mainPanel mp;
+ messagePanel msgp;
+ enterPanel ep;
+ logoffPanel offP;
+
+ CardLayout deck;
+
+ public citPanel() {
+ setLayout( deck = new CardLayout() );
+
+ add( "Login", lp = new loginPanel() );
+ add( "Main", mp = new mainPanel() );
+ add( "Message", msgp = new messagePanel() );
+ add( "Enter", ep = new enterPanel() );
+ add( "Logoff", offP = new logoffPanel() );
+
+ citadel.me.cp = this;
+ login();
+ }
+
+ public void login() {
+ deck.show( this, "Login" );
+ lp.refresh();
+ }
+
+ public void mainMenu() {
+ deck.show( this, "Main" );
+ mp.refresh();
+ }
+
+ public void enterRoom( citReply r ) {
+ deck.show( this, "Message" );
+ msgp.refresh( r );
+ }
+
+ public void enterMsg( String room ) {
+ enterMsg( room, null );
+ }
+
+ public void enterMsg( String room, String recip ) {
+ deck.show( this, "Enter" );
+ ep.refresh( room, recip );
+ }
+
+ public void logoff( String err ) {
+ offP.refresh( err );
+ deck.show( this, "Logoff" );
+ }
+}
--- /dev/null
+/* citReply.java
+ *
+ * Object to parse the reply from the server, so I don't have to think
+ * about it when I write code.
+ */
+
+import java.util.*;
+
+public class citReply {
+ public static final int LISTING_FOLLOWS=100, OK=200, MORE_DATA=300,
+ SEND_LISTING=400, ERROR=500, BINARY_FOLLOWS=600, SEND_BINARY=700,
+ START_CHAT_MODE=800;
+
+ int res_code;
+ String line,data;
+ Vector args, listing;
+ boolean expressmsg;
+
+ public citReply( String line ) {
+ this.line = line;
+
+ args = new Vector();
+ listing = null;
+ data = null;
+ res_code = ERROR;
+ expressmsg = false;
+
+ parseLine();
+ }
+
+ public void parseLine() {
+ try {
+ res_code = Integer.parseInt( line.substring( 0, 3 ) );
+ } catch( Exception e ) {};
+
+ StringBuffer s = new StringBuffer();
+
+ if( (line.length() > 3) && (line.charAt( 3 ) == '*') )
+ expressmsg = true;
+
+ for( int i = 4; i < line.length(); i++ ) {
+ char c = line.charAt( i );
+ if( c == '|' ) {
+ args.addElement( s.toString() );
+ s = new StringBuffer();
+ }
+ else
+ s.append( c );
+ }
+ if( s.length() != 0 ) args.addElement( s.toString() );
+
+ }
+
+ public boolean expressMessage() {
+ return expressmsg;
+ }
+
+ public boolean listingFollows() {
+ return res_code/100 == LISTING_FOLLOWS/100;
+ }
+
+ public boolean ok() {
+ return res_code/100 == OK/100;
+ }
+
+ public boolean moreData() {
+ return res_code/100 == MORE_DATA/100;
+ }
+
+ public boolean sendListing() {
+ return res_code/100 == SEND_LISTING/100;
+ }
+
+ public boolean error() {
+ return res_code/100 == ERROR/100;
+ }
+
+ public boolean binaryFollows() {
+ return res_code/100 == BINARY_FOLLOWS/100;
+ }
+
+ public boolean sendBinary() {
+ return res_code/100 == SEND_BINARY/100;
+ }
+
+ public boolean startChatMode() {
+ return res_code/100 == START_CHAT_MODE/100;
+ }
+
+ public boolean addData( String s ) {
+ if( s.equals( "000" ) )
+ return false;
+
+ if( listing == null ) listing = new Vector();
+ listing.addElement( s );
+ return true;
+ }
+
+ public String getLine( int i ) {
+ if( listing == null ) return null;
+
+ if( (i<0) || (i>=listing.size()) ) return null;
+
+ return (String)listing.elementAt( i );
+ }
+
+ public String getData() {
+ if( data != null ) return data;
+
+ StringBuffer s = new StringBuffer();
+
+ for( Enumeration e=listing.elements(); e.hasMoreElements(); ) {
+ s.append( (String)e.nextElement() );
+ s.append( "\n" );
+ }
+
+ data = s.toString();
+
+ return data;
+ }
+
+ public String getArg( int i ) {
+ if( args == null ) return "";
+
+ if( (i<0) || (i>=args.size()) ) return "";
+
+ return (String)args.elementAt( i );
+ }
+}
+
--- /dev/null
+/* citadel.java
+ *
+ * the "main" object
+ */
+
+public class citadel {
+ String host;
+ boolean applet;
+ net theNet;
+ server serverInfo;
+ user theUser;
+ citPanel cp;
+
+ boolean floors;
+
+ public static citadel me;
+
+ public static void main( String args[] ) {
+ citadel cb = new citadel( false );
+ if( args.length > 0 )
+ cb.openConnection( args[0] );
+ else
+ cb.openConnection();
+ citFrame cf = new citFrame();
+ }
+
+ public citadel( boolean applet ) {
+ me = this;
+ this.applet = false;
+ theUser = null;
+ }
+
+ public void lostNetwork( String reason ) {
+ theNet = null;
+ cp.logoff( "lost network connection: " + reason );
+ }
+
+ public boolean openConnection( ) {
+ return openConnection( "127.0.0.1" );
+ }
+
+ public boolean openConnection( String host ) {
+ this.host = host;
+ if( theNet == null ) theNet = new net( );
+
+ if( theNet.connect(host) ) {
+ System.out.println( "Connected to server." );
+
+ citReply rep = theNet.getReply( "INFO" );
+ if( rep.listingFollows() )
+ serverInfo = new server( rep );
+
+ return true;
+ }
+ else {
+ System.out.println( "Couldn't connect to server." );
+ }
+ return false;
+ }
+
+ public String getBlurb() {
+ if( serverInfo != null ) return serverInfo.blurb;
+ return "";
+ }
+
+ public String getSystemMessage( String name ) {
+ citReply rep = theNet.getReply( "MESG " + name );
+ if( rep.listingFollows() )
+ return rep.getData();
+ else
+ return "Couldn't find " + name;
+ }
+
+ public void loggedIn( citReply r ) {
+ theUser = new user( r );
+ floors = serverInfo.floor_flag != 0;
+ floors &= theUser.floors();
+ cp.mainMenu();
+ }
+
+ public citReply getReply( String s ) {
+ if( theNet == null ) return null;
+
+ return theNet.getReply( s );
+ }
+
+ public void enterRoom( String room ) {
+ enterRoom( room, null );
+ }
+
+ public void enterRoom( String room, String pass ) {
+ String cmd = "GOTO " + room;
+ if( pass != null )
+ cmd = cmd + " " + pass;
+ citReply r=getReply( cmd );
+ if( r.ok() ) {
+ cp.mp.visited( room );
+ cp.enterRoom( r );
+ } else if( r.res_code == 540 ) /* ERROR+PASSWORD_REQUIRED */
+ new passwordWindow( room );
+ }
+
+ public void enterMsg( String room ) {
+ cp.enterMsg( room );
+ }
+
+ public void nextNewRoom() {
+ enterRoom( cp.mp.nextNewRoom() );
+ }
+
+ public void expressMsg() {
+ citReply r=getReply( "GEXP" );
+ System.out.println( "EXPRESS MSG" );
+ if( !r.error() ) new expressWindow( r );
+ }
+
+ public void sendMessage( String body, String rec, boolean mail ) {
+ String cmd = "ENT0 1|";
+ if( mail ) cmd = cmd + rec;
+ cmd = cmd + "|0|0|0";
+
+ citReply r = getReply( cmd );
+ if( r.sendListing() ) {
+ theNet.println( body );
+ theNet.println( "000" );
+ }
+ }
+
+ public void logoff() {
+ cp.logoff(null);
+ theNet.println( "quit" );
+ }
+
+ public void who_online() {
+ System.out.println( "Who, pray tell, is online?" );
+ }
+
+ public void page_user() {
+ page_user( null );
+ }
+
+ public void page_user( String who ) {
+ new pageWindow( who );
+ }
+}
--- /dev/null
+/* displayInfo.java
+ * Display room's info
+ */
+
+import java.awt.*;
+
+public class displayInfo extends Frame {
+ String name;
+ TextArea text;
+
+ public displayInfo( String name ) {
+ super( "Info for : " + name );
+
+ this.name = name;
+ setLayout( new BorderLayout() );
+
+ add( "Center", text = new TextArea() );
+ Panel p;
+ add( "South", p = new Panel() );
+ p.add( new Button( "Close" ) );
+
+ citReply r = citadel.me.getReply( "RINF" );
+ if( r.listingFollows() )
+ text.append( r.getData() );
+ else
+ text.append( "<no room info>" );
+ resize( 300, 300 );
+ show();
+ }
+
+ public boolean handleEvent( Event e ) {
+ if( e.id == Event.WINDOW_DESTROY )
+ dispose();
+ return super.handleEvent( e );
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( e.target instanceof Button )
+ dispose();
+ return super.action( e, o );
+ }
+}
--- /dev/null
+/* enterPanel.java
+ * For entering messages
+ */
+
+import java.awt.*;
+
+public class enterPanel extends Panel {
+ boolean mail;
+ String room, recip;
+ NamedPanel np;
+
+ TextField who;
+ TextArea msg;
+
+ Button ok, cancel;
+
+ public enterPanel() {
+ PairPanel pp = new PairPanel();
+ pp.addLeft( new Label( "Recipient : " ) );
+ pp.addRight( who = new TextField( 10 ) );
+
+ setLayout( new BorderLayout() );
+ add( "North", pp );
+
+ np = new NamedPanel( "room name" );
+ np.setLayout( new BorderLayout() );
+ np.add( "Center", msg = new TextArea() );
+
+ add( "Center", np );
+
+ Panel p = new Panel();
+
+ p.add( ok = new Button ( "Send" ) );
+ p.add( cancel = new Button ( "Cancel" ) );
+ add( "South", p );
+ mail = false;
+ }
+
+ public void refresh( String room, String r ) {
+ if( room.equalsIgnoreCase( "Mail" ) ) {
+ who.enable();
+ who.setText( r );
+ mail = true;
+ } else {
+ who.disable();
+ who.setText( "DISABLED" );
+ mail = false;
+ }
+
+ msg.setText( "" );
+
+ np.setLabel( room );
+ this.room = room;
+ this.recip = r;
+
+ msg.enable();
+ if( !mail ) {
+ citReply rep = citadel.me.getReply( "ENT0 0|0|0|0|0" );
+ if( !rep.ok() ) {
+ msg.setText( "You aren't allowed to post here." );
+ msg.disable();
+ }
+ }
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( e.target == ok ) {
+ citadel.me.sendMessage( msg.getText(), who.getText(), mail );
+ citadel.me.cp.deck.show( citadel.me.cp, "Message" ); // Umm... this is bad
+ } else if( e.target == cancel ) {
+ citadel.me.cp.deck.show( citadel.me.cp, "Message" ); // Umm... this is bad } else if( e.taget == who ) {
+ msg.requestFocus();
+ }
+ return super.action( e, o );
+ }
+}
--- /dev/null
+/* expressWindow.java
+ * for showing express messages...
+ */
+
+import java.awt.*;
+
+public class expressWindow extends Frame {
+ String user;
+ TextArea msg;
+ Button reply, ok;
+
+ public expressWindow( citReply r ) {
+ user = r.getArg( 3 );
+
+ setTitle( user + " : express message" );
+
+ setLayout( new BorderLayout() );
+ NamedPanel np = new NamedPanel( "Message" );
+
+ np.setLayout( new BorderLayout() );
+ np.add( "Center", msg = new TextArea() );
+ msg.append( r.getData() );
+
+ add( "Center", np );
+
+ Panel p = new Panel();
+ p.add( reply = new Button( "Reply" ) );
+ p.add( ok = new Button( "OK" ) );
+ add( "South", p );
+
+ resize( 300, 300 );
+ show();
+ }
+
+ public boolean handleEvent( Event e ) {
+ if( e.id == Event.WINDOW_DESTROY )
+ dispose();
+ return super.handleEvent( e );
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( e.target == reply ) {
+ dispose();
+ citadel.me.page_user( user );
+ } else if( e.target == ok )
+ dispose();
+ return super.action( e, o );
+ }
+}
--- /dev/null
+/* loginPanel.java
+ * login screen
+ */
+
+import java.awt.*;
+
+public class loginPanel extends Panel {
+ TextArea text;
+ TextField user, pass;
+ Button login;
+
+ public loginPanel() {
+ setLayout( new BorderLayout() );
+
+ String blurb = citadel.me.getBlurb();
+ if( blurb.length() == 0 ) blurb = "Citadel";
+
+ add( "North", new Label( blurb ) );
+ add( "Center", text = new TextArea() );
+
+ text.setFont( new Font( "Courier", Font.PLAIN, 12 ) );
+
+ Panel p = new Panel();
+ p.setLayout( new BorderLayout() );
+
+ PairPanel pp = new PairPanel();
+
+ pp.addLeft( new Label( "Username:" ) );
+ pp.addRight( user = new TextField( 10 ) );
+ pp.addLeft( new Label( "Password:" ) );
+ pp.addRight( pass = new TextField( 10 ) );
+ pass.setEchoCharacter( '.' );
+
+ p.add( "Center", pp );
+
+ Panel ppp = new Panel();
+ ppp.add( login = new Button( "Login" ) );
+
+ p.add( "East", ppp );
+
+ add( "South", p );
+ }
+
+ public boolean handleEvent( Event e ) {
+ if( e.id == Event.GOT_FOCUS ) {
+ if( (e.target != user) && (e.target != pass) )
+ user.requestFocus();
+ }
+ return super.handleEvent( e );
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( e.target == user ) {
+ pass.requestFocus();
+ }
+ if( (e.target == login) || (e.target == pass) ) {
+ String u = user.getText(), p=pass.getText();
+
+ if( u.length() == 0 ) {
+ text.append( "\nNeed to enter in username.\n" );
+ user.requestFocus();
+ } else if (p.length() == 0 ) {
+ text.append( "\nNeed to enter in password.\n" );
+ pass.requestFocus();
+ } else {
+ citReply r = citadel.me.getReply( "USER " + u );
+ if( r.moreData() ) {
+ r = citadel.me.getReply( "PASS " + p );
+ if( r.error() ) {
+ text.append( "<bad password>" + r.getArg( 0 ) );
+ } else {
+ citadel.me.loggedIn( r );
+ }
+ } else {
+ text.append( "<bad user>" + r.getArg( 0 ) );
+ }
+ }
+ }
+ return super.action( e, o );
+ }
+
+ public void refresh() {
+ text.setText( citadel.me.getSystemMessage( "hello" ) );
+ user.setText( "" );
+ pass.setText( "" );
+ }
+}
+
+
--- /dev/null
+/* logoffPanel.java
+ * Display the "goodbye" message
+ */
+
+import java.awt.*;
+
+public class logoffPanel extends Panel {
+ TextArea area;
+ TextField host;
+ Button connect,close;
+ boolean applet;
+
+ public logoffPanel() {
+ applet = citadel.me.applet;
+ setLayout( new BorderLayout() );
+
+ NamedPanel np = new NamedPanel("Disconnected");
+ np.setLayout( new BorderLayout() );
+
+ np.add( "Center", area = new TextArea() );
+ area.setFont( new Font( "Courier", Font.PLAIN, 12 ) );
+
+ add( "Center", np );
+
+ Panel p = new Panel();
+
+ if( !applet ) {
+ p.add( host = new TextField() );
+ host.setText( citadel.me.host );
+ }
+
+ p.add( connect = new Button ( "Connect" ) );
+
+ if( !applet )
+ p.add( close = new Button( "Close" ) );
+
+ add( "South", p );
+ }
+
+ public boolean action ( Event e, Object o ) {
+ if( e.target == connect ) {
+ if( !applet )
+ citadel.me.host = host.getText();
+
+ citadel.me.openConnection( citadel.me.host );
+ citadel.me.cp.login();
+ } else if ( e.target == close ) {
+ System.out.println( "Thanks!" );
+ System.exit( 0 );
+ }
+ return super.action( e, o );
+ }
+
+ public void refresh( String s ) {
+ if( s == null )
+ area.setText( citadel.me.getSystemMessage( "goodbye" ) );
+ else
+ area.setText( s );
+ }
+}
--- /dev/null
+/* mainPanel.java
+ */
+
+import java.awt.*;
+
+public class mainPanel extends Panel {
+ List new_msgs, seen;
+ Button next_room, goto_room;
+ Button who_is_online, page_user;
+ Button logout;
+
+ public mainPanel() {
+ setLayout( new BorderLayout() );
+
+ Panel p = new Panel();
+ p.setLayout( new GridLayout( 1, 2 ) );
+
+ NamedPanel np = new NamedPanel( "New Messages" );
+ np.setLayout( new BorderLayout() );
+ np.add( "Center", new_msgs = new List() );
+
+ p.add( np );
+
+ np = new NamedPanel( "Seen Messages" );
+ np.setLayout( new BorderLayout() );
+ np.add( "Center", seen = new List() );
+ p.add( np );
+
+ add( "Center", p );
+
+ p = new Panel();
+ p.add( next_room = new Button ( "Next Room" ) );
+ p.add( goto_room = new Button ( "Goto Room" ) );
+ p.add( who_is_online = new Button( "Who is Online" ) );
+ p.add( page_user = new Button( "Page User" ) );
+ add( "North", p );
+
+ p = new Panel();
+ p.add( logout = new Button( "Logout" ) );
+ add( "South", p );
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( (e.target == new_msgs) || (e.target == seen) || (e.target == goto_room)) {
+ String room = getRoom();
+ if( room != null )
+ citadel.me.enterRoom( room );
+ } else if( e.target == who_is_online ) {
+ citadel.me.who_online();
+ } else if( e.target == page_user ) {
+ citadel.me.page_user();
+ } else if (e.target == next_room ) {
+ citadel.me.nextNewRoom();
+ } else if( e.target == logout ) {
+ citadel.me.logoff();
+ } else {
+ return super.action( e, o );
+ }
+ return true;
+ }
+
+
+ public boolean handleEvent( Event e ) {
+ if( e.id == Event.LIST_SELECT ) {
+ if( e.target == new_msgs ) {
+ int i = seen.getSelectedIndex();
+ if( i != -1 )
+ seen.deselect( i );
+ } else {
+ int i = new_msgs.getSelectedIndex();
+ if( i != -1 )
+ new_msgs.deselect( i );
+ }
+ }
+ return super.handleEvent( e );
+ }
+
+ public void refresh() {
+ new_msgs.clear();
+ parseRooms( new_msgs, citadel.me.getReply( "LKRN" ) );
+
+ seen.clear();
+ parseRooms( seen, citadel.me.getReply( "LKRO" ) );
+ }
+
+ public void parseRooms( List l, citReply r ) {
+ int i=0;
+ String s;
+
+ while( (s = r.getLine( i++) ) != null ) {
+ int j = s.indexOf( '|' );
+ if( j != -1 )
+ l.addItem( s.substring( 0, j ) );
+ else
+ l.addItem( s );
+ }
+ }
+
+ public String getRoom() {
+ String s = new_msgs.getSelectedItem();
+ if( s == null ) s = seen.getSelectedItem();
+
+ return s;
+ }
+
+ public String nextNewRoom() {
+ if( new_msgs.countItems() == 0 ) return "Lobby";
+
+ return new_msgs.getItem( 0 );
+ }
+
+ public void visited( String room ) {
+ for( int i = 0; i < new_msgs.countItems(); i++ ) {
+ if( room.equals( new_msgs.getItem( i ) ) ) {
+ new_msgs.delItem( i );
+ seen.addItem( room );
+ }
+ }
+ }
+}
--- /dev/null
+/* messagePanel.java
+ */
+
+import java.awt.*;
+import java.util.*;
+
+public class messagePanel extends Panel {
+ Choice reading;
+ Button who_is_online, room_info;
+ Button next_room, page_user;
+ Button next_msg, prev_msg, enter_msg, back;
+ TextField msgInfo;
+ TextArea theMsg;
+ NamedPanel np;
+
+ Vector msgs;
+ int cur_pos = -1;
+
+ String name;
+ int total, unread, info, flags, highest, highest_read;
+ boolean mail, aide;
+ int mail_num, floor;
+
+ public messagePanel() {
+ setLayout( new BorderLayout() );
+
+ Panel p = new Panel();
+ p.add( reading = new Choice() );
+ reading.addItem( "Read New" );
+ reading.addItem( "Read All" );
+ reading.addItem( "Last 5" );
+ reading.select( 0 );
+
+ // p.add( who_is_online = new Button( "Who is Online" ) );
+ p.add( room_info = new Button( "Room Info" ) );
+ p.add( next_room = new Button( "Next Room" ) );
+ p.add( page_user = new Button( "Page User" ) );
+ add( "North", p );
+
+ np = new NamedPanel( "Message" );
+ np.setLayout( new BorderLayout() );
+ np.add( "North", msgInfo = new TextField() );
+ np.add( "Center", theMsg = new TextArea() );
+ add( "Center", np );
+
+ p = new Panel();
+ p.add( next_msg = new Button( "Next Message" ) );
+ p.add( prev_msg = new Button( "Prev Message" ) );
+ p.add( enter_msg = new Button( "Enter Message" ) );
+ p.add( back = new Button( "Back" ) );
+ add( "South", p );
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( e.target == reading ) {
+ getMsgsPtrs();
+ } else if( e.target == page_user ) {
+ citadel.me.page_user();
+ } else if( e.target == who_is_online ) {
+ citadel.me.who_online();
+ } else if( e.target == room_info ) {
+ new displayInfo( name );
+ } else if( e.target == next_msg ) {
+ cur_pos++;
+ displayMessage();
+ } else if( e.target == prev_msg ) {
+ cur_pos--;
+ displayMessage();
+ } else if( e.target == enter_msg ) {
+ citadel.me.enterMsg( name );
+ } else if( e.target == next_room ) {
+ citadel.me.nextNewRoom();
+ } else if( e.target == back ) {
+ citadel.me.cp.mainMenu();
+ }
+ return super.action( e, o );
+ }
+
+ public void refresh( citReply r ) {
+ name = r.getArg( 0 );
+ np.setLabel( name );
+ total = atoi( r.getArg( 1 ) );
+ unread = atoi( r.getArg( 2 ) );
+ info = atoi( r.getArg( 3 ) );
+ flags = atoi( r.getArg( 4 ) );
+ highest = atoi( r.getArg( 5 ) );
+ highest_read = atoi( r.getArg( 6 ) );
+ mail = atoi( r.getArg( 7 ) ) != 0;
+ aide = atoi( r.getArg( 8 ) ) != 0;
+ mail_num = atoi( r.getArg( 9 ) );
+ floor = atoi( r.getArg( 10 ) );
+
+ if( info != 0 ) new displayInfo( name );
+ getMsgsPtrs();
+ }
+
+ public int atoi( String s ) {
+ try {
+ return Integer.parseInt( s );
+ } catch( Exception e ) {
+ return 0;
+ }
+ }
+
+ public void getMsgsPtrs() {
+ msgs = null;
+ String which = "new";
+ if( reading.getSelectedIndex() == 1 ) which = "all";
+ else if( reading.getSelectedIndex() == 2 ) which = "last|5";
+ citReply r = citadel.me.getReply( "MSGS " + which );
+ if( !r.error() ) {
+ msgs = r.listing;
+ cur_pos = 0;
+ }
+ displayMessage();
+ }
+
+ public void displayMessage() {
+ if( msgs == null) {
+ msgInfo.setText( "<no messages>" );
+ theMsg.setText( "" );
+ return;
+ }
+
+ if( cur_pos <= 0 ) {
+ cur_pos = 0;
+ prev_msg.disable();
+ } else
+ prev_msg.enable();
+
+ if( cur_pos >= msgs.size()-1 ) {
+ cur_pos = msgs.size()-1;
+ next_msg.disable();
+ } else
+ next_msg.enable();
+
+ String num = (String)msgs.elementAt( cur_pos );
+
+ citReply r = citadel.me.getReply( "MSG0 " + num + "|0" );
+ if( r.error() ) {
+ msgInfo.setText( "<error>" );
+ theMsg.setText( r.getArg(0) );
+ return;
+ }
+
+ int n = atoi( num );
+ if( n > highest_read ) {
+ highest_read = n;
+ citadel.me.getReply( "SLRP " + num );
+ }
+
+ Vector msg = r.listing;
+ String s, from="", time="", room="", node="", rcpt="";
+ do {
+ s = (String)msg.firstElement();
+ System.out.println( s );
+ msg.removeElementAt( 0 );
+ from = begin( from, s, "from=" );
+ time = begin( time, s, "time=" );
+ room = begin( room, s, "room=" );
+ node = begin( node, s, "hnod=" );
+ rcpt = begin( rcpt, s, "rcpt=" );
+ } while( (msg.size() > 0) && (!s.equals( "text" )) );
+
+ time = makeDate( time );
+
+ String sum = (cur_pos+1) + "/" + msgs.size() + " " + time + " from " + from;
+ if( !node.equals( citadel.me.serverInfo.human_name ) )
+ sum = sum + " (@"+node+")";
+ if( !rcpt.equals( "" ) )
+ sum = sum + " to " + rcpt;
+ if( !room.equals(name) )
+ sum = sum + " in " + room;
+
+ msgInfo.setText( sum );
+ theMsg.setText( r.getData() ); /* this relies on the fact that we've removed the header lines above. probably a messy way to deal with references. */
+ }
+
+ public String makeDate( String time ) {
+ long t=0;
+ try {
+ t = Long.parseLong( time );
+ } catch( NumberFormatException nfe ) {
+ };
+
+ Date d = new Date( t*1000 );
+ return d.toLocaleString();
+ }
+
+ public String begin( String def, String data, String key ) {
+ if( data.indexOf( key ) == 0 )
+ return data.substring( key.length() );
+ return def;
+ }
+
+}
--- /dev/null
+/* net.java
+ * chilly@alumni.psu.edu
+ *
+ * Object to talk the network talk with cit/ux server.
+ * Dispatches events.
+ */
+
+import java.io.*;
+import java.net.*;
+
+public class net {
+ Socket theServer;
+
+ DataInputStream in;
+ DataOutputStream out;
+
+ public net() {
+ theServer = null;
+ }
+
+ public void println( String s ) {
+ System.out.println( ">" + s );
+ try {
+ if( theServer != null )
+ out.writeBytes( s + "\n" );
+ } catch( IOException ioe ) {
+ citadel.me.lostNetwork( "Connection dropped (write)" );
+ if( theServer != null ) {
+ try { theServer.close(); theServer = null; }
+ catch( Exception e ) {};
+ }
+ }
+ }
+
+ public String readLine( ) {
+ try {
+ if( theServer != null ) {
+ String s = in.readLine();
+ System.out.println( "<" + s );
+ return s;
+ }
+ } catch( IOException ioe ) {
+ citadel.me.lostNetwork( "Network error: reead" );
+ if( theServer != null ) {
+ try { theServer.close(); theServer = null; }
+ catch( Exception e ) {};
+ }
+ }
+ return null;
+ }
+
+ public boolean connect( ) {
+ return connect( "127.0.0.1" );
+ }
+
+ public boolean connect( String serverName ) {
+ return connect( serverName, 504 );
+ }
+
+ public boolean connect( String serverName, int port ) {
+ try {
+ theServer = new Socket( serverName, port );
+
+ in = new DataInputStream( theServer.getInputStream() );
+ out = new DataOutputStream( theServer.getOutputStream() );
+
+ } catch( IOException ioe ) {
+ citadel.me.lostNetwork( "Couldn't connect to server" );
+ return false;
+ }
+
+ citReply rep = getReply();
+
+ if( rep.ok() ) return true;
+ return false;
+ }
+
+ public citReply getReply() {
+ return getReply( (String)null );
+ }
+
+ public citReply getReply( String cmd ) {
+ if( cmd != null ) println( cmd );
+
+ citReply r = new citReply( readLine() );
+ if( r.listingFollows() ) {
+ while( r.addData( readLine() ) ) ;
+ }
+
+ if( r.expressMessage() )
+ citadel.me.expressMsg();
+
+ return r;
+ }
+}
+
+
+
+
--- /dev/null
+/* pageWindow.java
+ */
+
+import java.awt.*;
+
+public class pageWindow extends Frame {
+ String user;
+ Choice who;
+ TextField msg;
+ Button send, cancel;
+
+ public pageWindow( String user ) {
+ this.user = user;
+
+ setTitle( "Page a user" );
+ setLayout( new BorderLayout() );
+
+ PairPanel pp = new PairPanel();
+ pp.addLeft( new Label( "Send message to:" ) );
+ pp.addRight( who = new Choice() );
+
+ add( "North", pp );
+
+ NamedPanel np = new NamedPanel( "Message" );
+ np.setLayout( new BorderLayout() );
+ np.add( "Center", msg = new TextField() );
+
+ add( "Center", np );
+
+ Panel p = new Panel();
+ p.add( send = new Button( "Send" ) );
+ p.add( cancel = new Button( "Cancel" ) );
+ add( "South", p );
+
+ citReply r = citadel.me.getReply( "RWHO" );
+ int i=0, which=0;
+ String s;
+ while( (s=r.getLine( i++ )) != null ) {
+ String u = getUser(s);
+ if( u.equalsIgnoreCase( user ) ) which = i-1;
+ who.addItem( u );
+ }
+
+ who.select( which );
+
+ resize( 300, 150 );
+ show();
+ }
+
+ public String getUser( String s ) {
+ int i = s.indexOf( '|' )+1;
+ int j = s.indexOf( '|', i );
+ return s.substring( i, j );
+ }
+
+ public boolean handleEvent( Event e ) {
+ if( e.id == Event.WINDOW_DESTROY )
+ dispose();
+ return super.handleEvent( e );
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( (e.target == msg) || (e.target == send) ) {
+ String user = who.getSelectedItem();
+ String m = msg.getText();
+ if( m.length() > 0 )
+ citadel.me.getReply( "SEXP " + user + "|" + m );
+ dispose();
+ } else if( e.target == cancel )
+ dispose();
+ return super.action( e, o );
+ }
+}
--- /dev/null
+/* passwordWindow.java
+ * Prompt user for room password
+ */
+
+import java.awt.*;
+
+public class passwordWindow extends Frame {
+ String room;
+ TextField text;
+
+ public passwordWindow( String room ) {
+ super( "Password for: " + room );
+
+ this.room = room;
+
+ setLayout( new BorderLayout() );
+ add( "North", new Label( "Please enter password for " + room ) );
+
+ PairPanel pp = new PairPanel();
+ pp.addLeft( new Label ( "Password: " ) );
+ pp.addRight( text = new TextField() );
+ text.setEchoCharacter( '.' );
+
+ add( "South", new Button( "Goto!" ) );
+
+ resize( 250, 150 );
+ show();
+ }
+
+ public boolean handleEvent( Event e ) {
+ if( e.id == Event.WINDOW_DESTROY ) {
+ dispose();
+ }
+ return super.handleEvent( e );
+ }
+
+ public boolean action( Event e, Object o ) {
+ if( (e.target == text) || (e.target instanceof Button) ) {
+ String s = text.getText();
+ citReply r = citadel.me.getReply( "GOTO " + room + " " + s );
+ if( r.ok() ) {
+ citadel.me.enterRoom( r );
+ dispose();
+ } else {
+ dispose();
+ new passwordWindow( room );
+ }
+ }
+ return super.action( e, o );
+ }
+}
--- /dev/null
+/* server.java
+ * server info data structure
+ */
+
+public class server {
+ int session_id;
+ String node_name, human_name, fqdn, server_name;
+ int rev_level;
+ String geo_local, sysadmin;
+ int server_type;
+ String page_prompt;
+ int floor_flag, page_level;
+
+ String blurb;
+
+ public server( citReply r ) {
+ session_id = atoi( r.getLine( 0 ) );
+ node_name = r.getLine( 1 );
+ human_name = r.getLine( 2 );
+ fqdn = r.getLine( 3 );
+ server_name = r.getLine( 4 );
+ rev_level = atoi( r.getLine( 5 ) );
+ geo_local = r.getLine( 6 );
+ sysadmin = r.getLine( 7 );
+ server_type = atoi( r.getLine( 8 ) );
+ page_prompt = r.getLine( 9 );
+ floor_flag = atoi( r.getLine( 10 ) );
+ page_level = atoi( r.getLine( 11 ) );
+
+ blurb = server_name + " " + human_name + " " + geo_local;
+ System.out.println( blurb );
+ }
+
+ public int atoi( String s ) {
+ if( s == null ) return 0;
+
+ try {
+ return Integer.parseInt( s );
+ } catch( NumberFormatException nfe ) {};
+ return 0;
+ }
+}
--- /dev/null
+/* user.java
+ * user structure
+ */
+
+public class user {
+ public static final int NEEDVALID=1, PERM=4, LASTOLD=16, EXPERT=32,
+ UNLISTED=64, NOPROMPT=128, DISAPPEAR=512, REGIS=1024, PAGINATOR=2048,
+ INTERNET=4096, FLOORS=8192;
+
+ String username;
+ int access, call, msg, num;
+ long flags;
+
+ public user( citReply r ) {
+ username = r.getArg( 0 );
+ access = atoi( r.getArg( 1 ) );
+ call = atoi( r.getArg( 2 ) );
+ msg = atoi( r.getArg( 3 ) );
+ flags = atoi( r.getArg( 4 ) );
+ num = atoi( r.getArg( 5 ) );
+ }
+
+ public boolean floors() {
+ return (flags & FLOORS)==FLOORS;
+ }
+
+ public int atoi( String s ) {
+ if( s == null ) return 0;
+
+ try {
+ return Integer.parseInt( s );
+ } catch( NumberFormatException nfe ) {};
+ return 0;
+ }
+}