/* WebTag v1.0 by Philip R. Banks (copyright) 2000

A class for displaying a tag at the bottom of web pages and
providing fast navigation of the site via a Popup Menu.
Consequently it only works with v1.1 or higher of the Java
Environment.

It expects to be run either from the root directory of the site
it is to be used on or inside a Java directory off the root
directory. When active it provides three buttons :-

"Home" - Takes you back to the root level of the site. It
	assumes that you have a well configured web server that will
	automatically serve a file if the directory is listed in the
	URL. IE if the site's main page is :-

	http://some.site.org/index.html

	then the Home button tries to return you to :-

	http://some.site.org/

	And expects the webserver to serve the index.html by default.

"Index" - Returns back to the section index for that page. This
	is supplied as a parameter from the page that summons the
	applet. Thus :-

	<PARAM NAME="IndexPage" VALUE="relative URL">

	The URL is relative to the root of the site as used by the
	Home button. If the parameter isn't supplied, this button
	isn't displayed.

"Links" - Triggers the popup menu that allows fast navigation
	of the site in total. A 'linklist.txt' file has to be
	provided in the codebase. This file describes line by the
	line the menu to be displayed as recursive depth first
	traversal. Each line is a comma seperated descriptor with
	three major exceptions :-

	<menu entry>,<type of menu entry>,<relative URL>

	<Menu entry> is the menu label that appears on the menu.

	<type of menu entry> describes what it is. entry is a
	standard menu entry. submenu starts a new submenu and
	endentry terminates a submenu with a final menu entry.

	<relative URL> is the relative URL from root of the site to
	the page the menu entry is to link to.

	The three exceptions to the format are that for a submenu
	entry the relative can be dropped. Given that the Java
	engine won't let you select submenu entries then there is
	no point supplying a relative URL. You can if you like and
	want to keep the list consistent. It just gets ignored.

	Secondly a seperator entry can be added by supplying just
	a - only. Again you can put the other two components in if
	you like, but they will be ignored because seperator
	entries cannot be selected.

	Third an endentry can be a line by itself. This lets you
	terminate menus without having to have a final entry in
	them.

	You can't have empty lines in the file and lines begining
	with a hash (#) symbol are treated as comment lines and
	ignored by the parser.

	If the linklist file isn't provided, then this button
	isn't made available.

Finally the application inspects the date and loads one of two
tag images. One is a more 'summery' tag while the other is a
colder 'winter' one.

Version History
---------------

v1.0 First publicly released version. */

import java.awt.*;
import java.io.*;
import java.net.*;
import java.lang.*;
import java.util.Date;

/* A class for holding menu data and the URL associated with it. */

class MenuList {
	Object menu_entry = null;
	MenuList next = null;
	String rURL = "";

	public MenuList(Object entry, String the_URL) {
		if (entry == null) throw new NullPointerException();

		rURL = the_URL;
		menu_entry = entry;
	}
}

public class WebTag extends java.applet.Applet {
	FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
	Image tag;
	MenuList header;
	MenuList cur;
	Menu LinkMenu = null;
	URL baseURL = null, indexURL = null;

	String ReadStreamLine(BufferedInputStream handle) throws IOException {
		String answer = "";
		int character = 0;

		// The break terminates this loop. Do Smeg all else till it breaks.
		while (true) {
			character = handle.read();

			if (character < 32) break;
			answer = answer + (char) character;
		}

		if (answer.equals("")) answer = null;
		return answer;
	}

	void BuildMenu(BufferedInputStream handle, Menu theMenu) throws IOException {
		MenuItem mItem;
		String line, title, entry, rel_URL;

		entry = "";

		while ((line = ReadStreamLine(handle)) != null) {
			// Check for empty lines and comment lines.
			if (!line.equals("") && !(line.indexOf("#") == 0)) {
				if (line.equals("endentry")) {
					// This is an end entry, so break out of the loop.
					break;
				} else {
					if (line.equals("-")) {
						// Handle seperator entries cleanly.

						title = "-";
						entry = "entry";
						rel_URL = "";
					} else {
						//Extract the title for the menu item.
						title = line.substring(0,line.indexOf(","));
						line = line.substring(line.indexOf(",")+1);
	
						// Menu type.
						if (line.indexOf(",") == -1) {
							entry = line;
						} else {
							entry = line.substring(0,line.indexOf(","));
						}

						if (!entry.equals("submenu")) {
							line = line.substring(line.indexOf(",")+1);

							// The relative URL.
							rel_URL = line;
						} else {
							// Submenus don't have a URL entry because they
							// can't be operated.

							rel_URL = "";
						}
					}

					// Okay now build the menu.
					mItem = null;

					if (entry.equals("entry") || entry.equals("endentry")) {
						mItem = new MenuItem();
						mItem.setLabel(title);

						theMenu.add(mItem);
					}

					if (entry.equals("submenu")) {
						mItem = new Menu();
						mItem.setLabel(title);

						BuildMenu(handle, (Menu)mItem);

						theMenu.add(mItem);
					}

					if (!title.equals("-") && !entry.equals("submenu")) {
						// Don't bother putting submenu or seperator entries
						// in the link list.

						if (cur == null) {
							cur = new MenuList((Object)mItem, rel_URL);
						} else {
							cur.next = new MenuList((Object)mItem, rel_URL);
							cur = cur.next;
						}
						if (header == null) header = cur;
					}
					// If we are on an end entry then quit.
					if (entry.equals("endentry")) break;
				}
			}
		}
	}

	public void init() {
		URLConnection conn = null;
		BufferedInputStream data;
		URL page;
		Button btn;

		//Get the base URL;

		baseURL = getCodeBase();
		String bURL = baseURL.toString();
		baseURL = null;		

		if (bURL.indexOf("Java/") != -1 ) {
			bURL = bURL.substring(0,bURL.indexOf("Java/"));
		}
		try {
			baseURL = new URL(bURL);
		} catch (MalformedURLException e) {
			baseURL = getCodeBase();
		}

		//Get the section index URL;
		String iURL = getParameter("IndexPage");
		if (iURL != null) {
			try {
				indexURL = new URL(baseURL.toString() + iURL);
			} catch (MalformedURLException e) {
			}
		}

		//Load the Image.
		String tag_name;

		Date today = new Date();
		if ((today.getMonth() > 4) && (today.getMonth() < 9)) {
			tag_name = "winter.gif";
		} else {
			tag_name = "summer.gif";
		}
		tag  = getImage(getCodeBase(),tag_name);

		//Add the default Buttons.
		setLayout(layout);
		if (baseURL != null) {
			btn = new Button("Home");
			add(btn);
		}
		if (indexURL != null) {
			btn = new Button("Index");
			add(btn);
		}

		// Fetch the menu file.
		cur = header;
		try {
			page = new URL(getCodeBase() + "linklist.txt");
			try {
				MenuItem mi;

				conn = page.openConnection();
				conn.connect();
				data = new BufferedInputStream(conn.getInputStream());

				try {
					LinkMenu = (Menu) new PopupMenu();
					BuildMenu(data, (Menu)LinkMenu);
					btn = new Button("Links");

					add(btn);
					add((PopupMenu)LinkMenu);
				} finally {
					// No Popup menus allowed. Damn it.

				}

				data.close();
			} catch (IOException e) {
				System.out.println("Error .. " + e.getMessage());
			}
		} catch (MalformedURLException e) {
			System.out.println("Bad URL to linklist.");
		}
	}

	public void paint(Graphics screen) {
		setBackground(Color.white);
		screen.drawImage(tag, 0, 20, this);
	}

	public boolean action(Event evt, Object arg) {
		boolean res = false;

		if (evt.target instanceof Button) {
			String labl = (String) arg;

			if (labl.equals("Home")) {
				if (baseURL != null) getAppletContext().showDocument(baseURL);
			}

			if (labl.equals("Index")) {
				if (indexURL != null) getAppletContext().showDocument(indexURL);
			}

			if (labl.equals("Links")) {
				if (LinkMenu != null) {
					PopupMenu fred = (PopupMenu) LinkMenu;
					fred.show(this,evt.x+10,evt.y+10);
				}
				res = true;
			}
		}

		if ((evt.target instanceof Menu) || (evt.target instanceof MenuItem)) {
			MenuList ptr;

			ptr = header;
			while (ptr != null) {
				if (ptr.menu_entry == evt.target) {
					URL destination;

					try {
						destination = new URL(baseURL + ptr.rURL);
						getAppletContext().showDocument(destination);
					} catch (MalformedURLException e) {
						// Malformed URL? Do nothing then.
					}

					ptr = null;
				} else {
					ptr = ptr.next;
				}
			}
		}

		return res;
	}
}
