private void processHyperlink(String href) {
		href = fixLink(href.trim());
		if (SCRIPT_PATTERN.matcher(href).find()) {
			executeScripts(href);
		} else {
			boolean valid = true;
			final String s = href.toLowerCase();
			boolean mwClient = s.indexOf("client=mw") != -1 || (s.startsWith(Modeler.getContextRoot()) && s.endsWith(".jsp"));
			if (mwClient || s.endsWith(".cml") || s.endsWith(".mml") || s.endsWith(".gbl") || s.endsWith(".gif") || s.endsWith(".png") || s.endsWith(".jpg") || s.endsWith(".jpeg") || s.endsWith(".txt") || s.endsWith(".pdb") || s.endsWith(".xyz") || s.endsWith(".mws") || s.indexOf("/cgi-bin/htsearch?") != -1) {
				if (targetIsBlank) {
					notifyPageListeners(new PageEvent(this, PageEvent.OPEN_NEW_WINDOW, href, linkParam));
				} else {
					if (navigator != null) { // if there is a navigator, the address will be pushed into a stack
						navigator.visitLocation(href);
					} else {
						visit(href);
					}
				}
			} else if (s.endsWith(".zip")) {
				// navigator.visitLocation(href);
				// FIXME: can we not put the address into the navigator's stack?
				visit(href);
			} else if (s.endsWith(".htm") || s.endsWith(".html")) {
				ExternalClient.open(ExternalClient.HTML_CLIENT, href, Page.this);
			} else if (s.endsWith(".pdf")) {
				ExternalClient.open(ExternalClient.PDF_CLIENT, href, Page.this);
			} else if (s.endsWith(".swf")) {
				ExternalClient.open(ExternalClient.FLASH_CLIENT, href, Page.this);
			} else if (s.endsWith(".rm") || s.endsWith(".ram") || s.endsWith(".avi")) {
				ExternalClient.open(ExternalClient.REALPLAYER_CLIENT, href, Page.this);
			} else if (s.endsWith(".qt") || s.endsWith(".mov")) {
				ExternalClient.open(ExternalClient.QUICKTIME_CLIENT, href, Page.this);
			} else if (s.endsWith(".mpg") || s.endsWith(".mpeg") || s.endsWith(".mp3")) {
				if (OS.startsWith("Mac")) {
					ExternalClient.open(ExternalClient.QUICKTIME_CLIENT, href, Page.this);
				} else {
					ExternalClient.open(ExternalClient.REALPLAYER_CLIENT, href, Page.this);
				}
			} else if (s.endsWith(".jnlp")) {
				ExternalClient.open(ExternalClient.JNLP_CLIENT, href, Page.this);
			} else if (FileUtilities.isRemote(href)) {
				ExternalClient.open(ExternalClient.HTML_CLIENT, href, Page.this);
			} else if (s.startsWith("mailto:") && href.indexOf("@") != -1) {
				ExternalClient.open(ExternalClient.EMAIL_CLIENT, href.substring(href.indexOf(":") + 1, href.length()), Page.this);
			} else {
				valid = false;
				final String s0 = href;
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(Page.this), "This hyperlink connects to an unrecognized type of document,\n" + "or an unsupported action.\n" + s0, "Hyperlink error", JOptionPane.ERROR_MESSAGE);
					}
				});
			}
			if (valid) {
				if (!HistoryManager.sharedInstance().wasVisited(href))
					HistoryManager.sharedInstance().addAddress(href);
			}
		}
	}