// Beginning of new parsing code for multiple chatareas
// These would be const, except microsoft doesn't recognize it.
var CA_ACTIVE_BG_COLOR = "#cc9900"; // "#ffffcc";
var CA_DIMMED_BG_COLOR = "#666666";
var CA_ACTIVE_TXT_COLOR = "#333366";  // "#0000cc";
var CA_DIMMED_TXT_COLOR = "#999999";
var PAUSEAFTERLINE = 1500;  // 1.5 seconds
var PAUSEAFTERBURST = 5000; // 5 seconds; eventually kick up higher
var PAUSEAFTERALLBURSTS = 5000; // 5 seconds.
var COLORPINK = "#ffc0cb";

var INITIALDELAY_DEFAULT = 5;	// this should translate to 5000 milliseconds (5 seconds)
var CHARDELAY_DEFAULT = 5;	// this should translate to 60 milliseconds.
var LINEDELAY_DEFAULT = 5;		// this should translate to 1500 milliseconds (1.5 second)
var BURSTDELAY_DEFAULT = 5;			// this should translate to 20000 milliseconds (20 seconds)
var BGHUE_DEFAULT = 5;       // this should translate to a soft yellow background hue.
// The following typespeeds are in milliseconds (a higher number is slower)
var TYPESPEED_DEFAULT = 5;
var PAUSELINE_DEFAULT = 5;
//var TYPESPEED_SNAIL = 80;  
//var TYPESPEED_TURTLE = 70;  
//var TYPESPEED_RABBIT = 60;  
//var TYPESPEED_LEOPARD = 50;  
//var TYPESPEED_CHEETAH = 40;  

var	chatlines = new Array();  // this is the workhorse chat array...
var debugcounter = 0;
var activechatarea = -1; // Make certain it doesn't match any valid area to start with.
var curchatarealine = 0;
var ca = '';  // for constructing a dynamic object name for thechatarea
var caform = '';
var catextarea = '';
var speakers = new Array();

var debug = false;
var bursts = new Array();
var randomizer = new Array()
var tl = [["initialized"]];
/* alert("In header, tl is "+tl[]); */
var typeSpeed = 60;        // the typing rate, in milliseconds. (Higher number is slower)
var sleepInterval = 30;    // What should this be?
var curBurst = 0;          // This will be set before use.
var curSeqIndex = 0;		// The index into the randomizer array.  It gets incremented
							// sequentially to access randomized bursts in the randomizer array.

var chatActive = 0;
/* var tl = new Array(); */

// The following allows universal use of getElementById even when an old browser won't
// recognize it.  Now get rid of every occurrennce of document.all!
// about old browsers that lack it
//if(document.all && !document.getElementById) {
//    document.getElementById = function(id) {
//         return document.all[id];
//    }
//}
function calc_initialdelay(delayindex)
{
	return (delayindex * 1000);  // delayindex of 5 => 5 seconds
}

function calc_chardelay(delayindex)
{
	return (delayindex * 12);  // delayindex of 5 => 60 milliseconds
}
function calc_linedelay(delayindex)
{
	var milliseconds = 1500; // default of 1.5 seconds
//alert("In calc_linedelay, delayindex is " + delayindex);
	switch (delayindex)
	{
	case '1':
//alert("In case 1, detected a 1");
	  milliseconds = 500;  // half a second
	  break
	case '2':
	  milliseconds = 700;  
	  break
	case '3':
	  milliseconds = 900;  
	  break
	case '4':
	  milliseconds = 1200;  
	  break
	case '5':
	  milliseconds = 1500;  // 1.5 seconds
	  break
	case '6':
	  milliseconds = 2000; 
	  break
	case '7':
	  milliseconds = 4000; 
	  break
	case '8':
	  milliseconds = 7000; 
	  break
	case '9':
	  milliseconds = 10000;  // 10 seconds
	  break
	}
	return (milliseconds);  // delayindex of 5 => 1.5 seconds
}

function calc_burstdelay(delayindex)
{
	return (delayindex * 4000);  // delayindex of 5 => 20 seconds
}

function calc_bghue(bghueindex)
{
	var hue = CA_ACTIVE_BG_COLOR; // default of soft yellow orange
//alert("In calc_linedelay, delayindex is " + delayindex);
	switch (bghueindex)
	{
	case '1':
//alert("In case 1, detected a 1");
	  hue = "#ffffff";  // bloody hell white
	  break
	case '2':
	  hue = "#00cccc";  // pale blue  
	  break
	case '3':
	  hue = "#ccccff";  // pale lavender
	  break
	case '4':
	  hue = "#ffcccc";   // pale pink  
	  break
	case '5':
	  hue = "#cc9900";  // soft yellow-orange
	  break
	case '6':
	  hue = "#99cc66";  // pale olive green
	  break
	case '7':
	  hue = "#66ffcc";  // pale blue green
	  break
	case '8':
	  hue = "#00CCCC";  // pale teal
	  break
	case '9':
	  hue = "#ffffcc";  // pale yellow
	  break
	}
	//alert("In calc_bghue, returning hue of " + hue);
	return (hue);  
}

function verifyForm() {
   // Note: If "cafe" is not currently active,
   // I should assume the reader wants chatter;
   // so take the same action here as I do
   // when the reader clicks on "cafe"
   SPOK = false;
   INTOK = false;
   for (ic = 0; ic < 5; ic++) {
      // alert(document.mainform.rSpeed[ic].value);
      if (document.mainform.rSpeed[ic].checked) {
         SPOK = true;
         typeSpeed = document.mainform.rSpeed[ic].value;
         }
      }
   for (ic = 0; ic < 5; ic++) {
      if (document.mainform.rInterval[ic].checked) {
         INTOK = true;
         sleepInterval = document.mainform.rInterval[ic].value;
         }
      }
   if (!SPOK || !INTOK) {
      alert('Please select a button in each category.');
      return false;
      }
   else toggleForm();
   if (chatActive == 0) /* Start chatting if not underway */
   doCafe();
   }

var text_pos;
var str_length;
//var str_length=tl[curBurst][0].length;
var rowforarea = new Array();
var contentsforarea = new Array();

//for (i=0;i<tl.length;i++) {
//alert("tl["+i+"] is "+tl[i]);
//}

// type_text() performs the following four actions:
//   Calls self recursively, putting out single character, until end of line.
//	 At end of line, waits PAUSEAFTERLINE seconds, then recurses to put out next line as above.
//   At end of burst, waits PAUSEAFTERBURST seconds, calls alarmFunc which inits next burst then
//       calls type_text() to put out lines (character by character) of this burst
//   At end of all bursts, sets chatActive 0, waits PAUSEAFTERALLBURSTS seconds, calls alarmFunc,
//		 which makes final call to type_text() to write nothing (clear all textareas).
function type_text()
{
   if (activechatarea != chatlines[currentline].chatarea)
   {
	   // Just changed chatarea; dim previous one, empty and colorize active one, reset linenum.
	   curchatarealine = 0;
	   if (activechatarea > -1)
	   {
		   // Make certain there was an activechatarea before now
	   	   dimChatArea(activechatarea);
	   }
	   activechatarea = chatlines[currentline].chatarea;
	   caform = getChatFormName(activechatarea);	
	   catextarea = getChatTextAreaName(activechatarea);	
	   if (!(typeof(document[caform][catextarea])))
	   {
			alert("Undefined form/textarea: " + caform + "." + catextarea);
	   }
	   document[caform][catextarea].value = '\r\n';  // Empty new chatarea in case used before.
//	   document[caform][catextarea].style.backgroundColor = CA_ACTIVE_BG_COLOR;
//alert("Active bghue is " + chatlines[currentline].bghue);
	   // Note that I will need to do the following assignment after every line in logic below.
	   document[caform][catextarea].style.backgroundColor = chatlines[currentline].bghue;
	   document[caform][catextarea].style.color = CA_ACTIVE_TXT_COLOR;
	   document[caform][catextarea].style.visibility = "visible";
   }

   if (chatActive == 0)
   {
	  // Let's make all chatareas disappear.
	  hideChatAreas();
	  return;  // We are finally done.
   }
   // I need to detect the start of a new line so I can change the box's color if need be.
   // But I mustn't do it in the logic below, or the color will appear prematurely.
   // I think text_pos of 0 will indicate start of new line:
   if (text_pos == 0)
   {
	   document[caform][catextarea].style.backgroundColor = chatlines[currentline].bghue;
   }
   contents = '';
   row = Math.max(0, curchatarealine - 7); 
   // New insight into above line.  According to the author:
   // "Note: if you change the number or rows in the <TEXTAREA>  (f.e. rows=10), in order to
   // deactivate the vertical scrollbar, you'll also need to adjust the value in this section
   // of the script:" (referring to the Math.max line above.
   // The -4 is for a box with 5 rows.  I would need -9 for a box with 10 rows.
   // Also, here's a big pisser.  The script assumes you are smart enough not to write a
   // line that is longer than the fucking width of the box.
   // That means, next on my agenda is a linewrap script...
   // Here's what I believe the above line and following while loop accomplish.  Row stays 0
   // for the first 4 lines (chatlines).  After that it begins to increment by one.  Meanwhile,
   // throughout the first chatline, the while loop fails.  On the second chatline, though
   // row remains 0, the while gets exercised, essentially appending '\r\n' to the chatarea
   // contents immediately after line 1.
   // exercised and But on So the while loop isn't even exercised until line
   // 5.  At that point row is assigned 1 in the above max statement.  It still tests less
   // than curchatarealine in the is still less than
   // becomes 1.do.  Actually, the while isn't even done on the
   // first pass (since row not less than chatline -- both are 0).
   // On the second pass, 
   while(row < curchatarealine)
   {
     // Original: contents += tl[curTopic][row++] + '\r\n';
	 contents += chatlines[row++].chattext.substring(0) + '\r\n';
   }

   document[caform][catextarea].value = contents + chatlines[currentline].chattext.substring(0, text_pos) + "_";
   if(text_pos++== str_length)
   {
	  // Finished line; adjust to next line.
	  // alert("In type_text, end of line: curBurst is " + curBurst + ", curburstline is " + curburstline + ", str_length is " + str_length + ", ca is " + ca);
	  text_pos = 0;
	  // Finished line; adjust to next line.
      if (currentline == (chatlines.length - 1))
	  {
		// We are done with all bursts.
		// Even though done, we'll make one more recursive call in 5 seconds to clear boxes.
        chatActive = 0;
        setTimeout("alarmFunc()", PAUSEAFTERALLBURSTS);
      }
      else
	  {
		 currentline++; // this is guaranteed safe, due to if part above.
		 // alert("preparing to process currentline " + currentline);
		 // alert("curBurst is " + curBurst + ", burstnum in currentline is " + chatlines[currentline].burstnum);

		 if (curBurst == chatlines[currentline].burstnum)
		 {
			 // Not at end of burst; let's record str_length and continue.
			 // But first delay 1.5 second and recurse.
			 str_length = chatlines[currentline].chattext.length;
         	 setTimeout("type_text()", chatlines[currentline-1].ldelay);  // was PAUSEAFTERLINE
			 							// Should I use [currentline-1] to get previous line's delay?
         }
		 else
		 {
			// alert("End of burst.");		 
 			// End of burst; set up for next burst, then punt to alarmFunc.
			// Or will alarmFunc do this setup?
 			//alert("In type_text, done with a burst: curSeqIndex is "+curSeqIndex);
			// Also, let's hide all the chatareas.
			hideChatAreas();
			curSeqIndex++;  // Increment the index into the randomizer array to get next burst
			curchatarealine = 0;  // Yes, needed.
            setTimeout("alarmFunc()", chatlines[currentline-1].bdelay); // was PAUSEAFTERBURST
									// I'm using [currentline-1] to get previous burst's delay spec(?)
         }
      }
   }
   else
   {
   		setTimeout("type_text()", chatlines[currentline].cdelay); // was typeSpeed
   }
}
/*
This source code is released to the public domain with the provision that
the copyright information remains in the source code.
Copyright (c) by: Robert N Bovara All Rights Reserved.
*/
var outMsg = "";
var i = 0;
var lineNo = 1;
var timerDM = null;
var msg = " ";
var ScreenLine = new Array();
/*
ScreenLine[1] = "";
alert("Just tried reading chatter, which is "+ScreenLine[1]);
*/
ScreenLine[1] = "Did anyone ever tell you you have lovely eyes?";
ScreenLine[2] = "They are really \"quite\" fetching."
ScreenLine[3] = "If I weren't married, I'd probably inquire whether";
ScreenLine[4] = "you are male or female."
ScreenLine[5] = "It shouldn't matter, I know. Still...\f ";
ScreenLine[6] = "I've often wondered what it would be like";
ScreenLine[7] = "to be the last person on Earth.";
ScreenLine[8] = "I bet it would change me a lot,"
ScreenLine[9] = "give me a whole new perspective on";
ScreenLine[10] = "loneliness\f";
ScreenLine[11] = "But I think I'd really do well at the Olympics."
ScreenLine[12] = "Under the circumstances.";
ScreenLine[13] = " \f";
/*
ScreenLine[1] = "Doesn't this look better than status bar displays?"
ScreenLine[2] = "Isn't this easier to read than \"sideways\" scrollers?"
ScreenLine[3] = " ";
ScreenLine[4] = "How many lines can you display on the status bar?"
ScreenLine[5] = "Here, you can not only display more than one line,\f ";
ScreenLine[6] = "But, you can also display more than one \"page\" !"
ScreenLine[7] = " ";
ScreenLine[8] = "Aren't you glad your browser interprets JavaScript (JScript)?"
ScreenLine[9] = " ";
ScreenLine[10] = "Enjoy!....\f";
ScreenLine[11] = "P.S.\t'Tis better to have no moving text at all ....."
ScreenLine[12] = "\t... than to have a \"sideways\" scroller.";
ScreenLine[13] = " \f";
*/
/*
To change or add messages, just replace values of or add to ScreenLine[n]
above. Each ScreenLine[n] is a separate line. To change the "page" before
the defined page length is reached, insert a \f character at the end of the
line where you want the break. Use \" for quotes and \t for tabs in the
message text.
*/
var msgNum = 1;
// set to first message to display
var msgCnt = 3;
// set to number of last message "page" to display.
/*var typeSpeed = 70; // the typing rate, in milliseconds. (Higher number is slower)*/
var pageLen = 2;
// set to page size, usually number of ROWS in TEXTAREA
var delay = typeSpeed;
var r = 0;
var cr = "\r\n";
if ("3" <= navigator.appVersion.charAt(0)) {
   var cr = "\n"}
for (x = 1; x <= (msgCnt); x++) {
   ScreenLine[x] = ScreenLine[x] + cr;
   }
msg = ScreenLine[1];
function DisplayMsg() {
   if (msg.length <= i || msg.charAt(i) == "\f") {
      r = i;
      i = 0;
      /*
      if (msgCnt == msgNum) { // To repeat msg, remove this conditional
      i = 0;
      msgNum = 1;
      lineno = 1;
      r = 0;
      outmsg = "";
      msg = ScreenLine[msgNum];
      document.chatarea2form.chatarea2.value = "";
      return;
      }
      else
      */
      ChangeMsg();
      }
   outMsg = outMsg + msg.charAt(i);
   i++;
   if (msg.charAt(i) == "\f" || (lineNo == pageLen && i == msg.length)) {
      delay = 4000;
      }
   else {
      if (msg.charAt(i) == cr && msg != " " + cr) {
         delay = 2000;
         }
      else {
         delay = typeSpeed;
         }
      }
   document.chatarea2form.chatarea2.value = outMsg;
   /* self.document.forms[2].elements[0].value=outMsg; */
   timerDM = setTimeout("DisplayMsg()", delay);
   }
function ChangeMsg() {
   msgNum++;
   if (msgCnt < msgNum) {
      msgNum = 1;
      }
   lineNo++;
   if (pageLen < lineNo || msg.charAt(r) == "\f") {
      outMsg = ScreenLine[msgNum].charAt(i);
      i++;
      lineNo = 1;
      }
   msg = ScreenLine[msgNum];
   }
function quitDisplay() {
   document.chatarea2form.chatarea2.value = "";
   /* self.document.forms[0].elements[0].value = "Type yourself a Note today!"; */
   }

  var alarmId;

  function alarmFunc() {
    // Sound the alarm call. You could play a sound here
    // as well, by using location=soundfile, etc.
/*    alert("ALARM CALL!"); */
//alert("In alarmFunc, chatactive is "+chatActive+", curSeqIndex is "+curSeqIndex);
    if (chatActive == 1) { /* don't try setting these if this is a stop Chat cleanup call */
       // Two possibilities: new burst, or just new line of current burst.
	   if (curBurst != randomizer[curSeqIndex])
	   {
		   // alert("alarmFunc detected new burst!");
		   // new Burst.  Need to find which burst comes next, and
		   // adjust currentline accordingly.
       	   curBurst = randomizer[curSeqIndex];
	       // Need to find where curBurst begins in chatlines array
	   	   currentline = -1;
		   // alert("Will search for curBurst of " + curBurst + "in chatlines");
		   for (findidx = 0; findidx < chatlines.length; findidx++)
		   {
				// alert("chatlines[" + findidx + "] is " + chatlines[findidx].burstnum);
				if (chatlines[findidx].burstnum == curBurst)
		   		{
			   		currentline = findidx;
			   		break;
		   		}
	   		}
	   		if (currentline == -1)
	   		{
		   		alert("Failed to find burst number in chatlines!");
		   		// probably ought to fail...
	   		}
	   }
       text_pos=0;
       // str_length=tl[curBurst][0].length;
       str_length=chatlines[currentline].chattext.length;
    }
	// Before calling type_text, let's check all the values.
//	alert("In alarmFunc before type_text: curBurst is " + curBurst + ", curburstline is " + curburstline + ", str_length is " + str_length);
	type_text();  // Note that this gets called even if chat is not active -- to clear the area.

/*      doBlather(); */
  }



  function doBurst() {
    // ???curTopic and curIndex probably relate curBurst.  Let's assume that.
//    Read (and parse) a line from the array.
//    While line ne blank {
//      if (chatarea = leadingnumber()) {
//        speaker = getspeaker(chatarea);
//      }
//      else {
//        chatarea = activechatarea;
//        speaker = activespeaker;
//      }
//      type_text(chatarea,speaker);
    }

  function startTimeout(id) {
    var minutes = prompt("How many minutes?", 0);
    // Time-outs are measured in milliseconds, so if the
    // user enters 1 minute, we need to multiply by 60000.
    alarmId = setTimeout("alarmFunc()", minutes*60000);
}

//Typing Text (DHTML) v1 (Sunday, April 15th, 2001)
//Programmed by: Haitham M. Al-Beik
//Email: albeik26@hotmail.com
//Visit http://javascriptkit.com for this script
var BlatherText = new Array();
BlatherText[0] = "Did anyone ever tell you you have lovely eyes?";
BlatherText[1] = "They are reall quite fetching";
BlatherText[2] = "If I weren't married, I'd probably inquire whether";
BlatherText[3] = "you are male or female.";
BlatherText[4] = "It shouldn't matter, I know. Still...";
var ttloop = 0;
// Repeat forever? (1 = True; 0 = False)
/* ORIG SETTING var tspeed = 50; // Typing speed in milliseconds (larger number = slower) */
var tspeed = 80;
// Typing speed in milliseconds (larger number = slower)
var tdelay = 1000;
// Time delay between BlatherTexts in milliseconds
// ------------- NO EDITING AFTER THIS LINE ------------- \\
var dwAText, cBlather = 0, eline = 0, cchar = 0, mxText;
function doBlather() {
   mxText = BlatherText.length - 1;
   dwAText = BlatherText[cBlather];
   setTimeout("addChar()", 1000)}
function addBlather() {
   cBlather += 1;
   if (cBlather <= mxText) {
      dwAText = BlatherText[cBlather];
      if (dwAText.length != 0) {
         document.chatarea2form.chatarea2.value = "";
         eline = 0;
         setTimeout("addChar()", tspeed) }
      }
   }
function addChar() {
   if (eline != 1) {
      if (cchar != dwAText.length) {
         nmttxt = "";
         for (var k = 0; k <= cchar; k++) nmttxt += dwAText.charAt(k);
         document.chatarea2form.chatarea2.value = nmttxt;
         cchar += 1;
         if (cchar != dwAText.length) document.chatarea2form.chatarea2.value += "_";
         }
      else {
         cchar = 0;
         eline = 1;
         }
      if (mxText == cBlather && eline != 0 && ttloop != 0) {
         cBlather = 0;
         setTimeout("addBlather()", tdelay);
         }
      else setTimeout("addChar()", tspeed);
      }
   else {
      setTimeout("addBlather()", tdelay) }
   }
activateMenu = function(nav) {
	/* currentStyle restricts the Javascript to IE only */
   // Ascertain that object nav is in the page AND that it has currentStyle defined.
   // Since currentStyle is an IE thing, all of this code relates only to IE.
   if (document.getElementById(nav) && document.getElementById(nav).currentStyle) {
		// alert("Inside currentStyle test");
		var navroot = document.getElementById(nav);
      /* Get all the list items within the menu */
      var lis = navroot.getElementsByTagName("LI");
      for (i = 0; i < lis.length; i++) {
         /* If the LI has another menu level */
         if(lis[i].lastChild.tagName == "UL") {
            /* assign the function to the LI */
            lis[i].onmouseover = function() {
               /* display the inner menu */
               this.lastChild.style.display = "block";
               }
            lis[i].onmouseout = function() {
               this.lastChild.style.display = "none";
               }
            }
         }
      }
   }
window.onload = function() {
   /* pass the function the id of the top level UL */
   /* remove one, when only using one menu */
   activateMenu('vertnav');
   }
function toggleForm() {
   if (document.mainform.style.visibility == "visible") document.mainform.style.visibility = "hidden";
   else document.mainform.style.visibility = "visible";
   }
function stopMsg() {
   chatActive = 0;
   /* index = tl[curBurst].length; */
   if (document.mainform.style.visibility == "visible") document.mainform.style.visibility = "hidden";
   }
//function doCafe() {
//   var tnum;
//   /*
//   Here I need to read sleepInterval and do something intelligent with it.
//   I know I have a handful of messages to choose from randomly. But I don't
//   want to repeat any of them. Assume I have 4.
//   After randomizing them, I need to go into a for loop that will start each
//   chat; however, before calling doChat or whatever, I need to do a wait
//   that takes sleepInterval into account.
//  
//   How to get the timer to work correctly?
//   Okay. So I call setTimeout and specify alarmFunc.
//   At the specified time, alarmFunc will call type_text to start
//   the first chat. Once that finishes, it is up to type_text to
//   update curTopic, and if topics remain, do another setTimeout, specifying alarmFunc.  
//   */
//   /* topic=new Array(); */
//   for (tnum = 0; tnum < tl.length; tnum++) {
//      topic[tnum] = tnum;
//      }
//   function RandomSort() {
//      return Math.floor((Math.random() * tl.length) - 1);
//      }
//   topic = topic.sort(RandomSort);
//   //alert("topics are: "+topic[0]+" "+topic[1]+" "+topic[2]+" "+topic[3]);
//   curIndex = 0;
//   chatActive = 1;
//   setTimeout("alarmFunc()", 20000);
//   }
function getvalidindex(delayindex, defaultdelayindex)
{
	// alert("in getvalidindex; delayindex is " + delayindex);
	if ((typeof(delayindex) != "undefined") && (delayindex.length != 0))
	{
		if (delayindex != parseInt(delayindex))
		{
			alert('Argument delayindex ==>' + delayindex + '<== is not an integer; defaulting to 5');
			useindex = 5;
		}
		else
		{
			useindex = delayindex;
		}
	}
	else
	{
		useindex = defaultdelayindex;
	}
	// alert("in getvalidindex, ready to return; delayindex is " + delayindex);
	return useindex;
}

function doCafe(initialdelay,chardelay,linedelay,burstdelay,bghue) {
   var tnum;
   /*
   doCafe will wait milliseconddelay before beginning the chats.
   Here I need to read sleepInterval and do something intelligent with it.
   Assum I have 4 bursts to choose from randomly.
   After randomizing them, I call setTimeout and specify alarmFunc.
   At the specified time, alarmFunc calls type_text to start
   the first burst. Once that finishes, it is up to type_text to
   update curBurst, and if bursts remain, do another setTimeout, specifying alarmFunc.
   */
	// Note that these delays remain just the indexes (1-9) and are not calculated into milliseconds.
	// The calculated versions reside in the chatlines array, to be read by type_text.
//alert("Inside doCafe");
	initialdelay_cafe = getvalidindex(initialdelay,INITIALDELAY_DEFAULT);
	chardelay_cafe = getvalidindex(chardelay,CHARDELAY_DEFAULT);
	linedelay_cafe = getvalidindex(linedelay,LINEDELAY_DEFAULT);
	burstdelay_cafe = getvalidindex(burstdelay,BURSTDELAY_DEFAULT);
	bghue_cafe = getvalidindex(bghue,BGHUE_DEFAULT);

   function RandomSort() {
      return Math.floor((Math.random() * bursts.length) - 1);
   }

   // Parse the raw input into the two-dimensional bursts array -- essentially an
   // array of bursts, each burst being an array of chatlines.
   // Each chatline consists of three fields: chatarea, speaker, chattext.
//alert("Inside doCafe")

   totalbursts = parseChatFile();
// alert("totalbursts is " + totalbursts);

//alert("bursts is " + bursts.length + "; chatlines in burst 0 is " + bursts[0].length);
//var b;
//for (b=0;b<bursts.length;b++) {
//			showBurst(bursts[b]);
//}
// showAllBursts(bursts);  // test it.

   // Now that we know the bursts, let's create a randomizing array for accessing them.
   for (tnum=0; tnum < totalbursts; tnum++) {
       randomizer[tnum]=tnum;
   }
// SUPPRESS RANDOM FOR DEBUGGING PURPOSES!!!
//   randomizer=randomizer.sort(RandomSort);  // randomize the sort.
   // i.e., randomizer[0] = 3, randomizer[1] = 0, randomizer[2] = 1, randomizer[3] = 2
   // alert("topics are: "+randomizer[0]+" "+randomizer[1]+" "+randomizer[2]+" "+randomizer[3]);
//   for (tnum=0; tnum < bursts.length; tnum++) {
//       alert("randomizer[" + tnum + "] = " + randomizer[tnum]);
//   }

   curSeqIndex = 0;  // Incremented index into randomizer array to get randomized bursts
   currentline = 0;  // This is necessary for init; else undefined in alarmFunc()
//   activechatarea = bursts[randomizer[curSeqIndex]][0].chatarea; // Need to set this here
   																 // so its change is detectable.
   chatActive = 1;
	var initdelay = calc_initialdelay(initialdelay_cafe)
//	alert("In doCafe, ready to setTimeout: initdelay is " + initdelay);
   setTimeout("alarmFunc()", calc_initialdelay(initialdelay_cafe)); // as written, this won't
   												// allow idelay in input file to override.
												// Investigate how to remedy...
   }





// function startChat() {
//   curchatline = 0;
//   text_pos = 0;
//   str_length = tl[curBurst][0].chattext.length;
//   type_text();
//   }

function randomWait() {
   alert("In randomWait");
   return;
   }


  function isBlankLine(theline) {
  	if (theline.length == 0) {
		return true;
	}
	else {
		return false;
	}
	}

function alphaNumericCheck(){
var regex=/[0-9A-Za-z]*/;
if(regex.test(document.formName.inputName.value)){
return true;
} else {
return false;
}
}

  function isLeadingNumber(theline) {
	var numbers = "0123456789";
	if (numbers.indexOf(theline[0]) == -1) {
		//*alert("detected leading number!");	
		return false;
	}
	//*alert("Did not see a leading number...");
	return true;
	}

function chatLine (chatarea,speaker,burstnum,burstlinenum,chattext,idelay,cdelay,ldelay,bdelay,bghue) {
	// This accounts for all possible elements of a line.
	this.chatarea = chatarea;
	this.speaker = speaker;
	this.burstnum = burstnum;
	this.burstlinenum = burstlinenum;
	this.chattext = chattext;
	this.idelay = idelay;
	this.cdelay = cdelay;
	this.ldelay = ldelay;
	this.bdelay = bdelay;
	this.bghue = bghue
	};

// parseChatLine will handle lines of the following form:
// 1=Sally					# Speaker name assignment ('=' must immediately follow number)
// 2=George					# ditto.
// 1/Hi, how are you?       # speaker id followed by speech (slash can actually be any char but '=')
// 2/I am fine.				# ditto.
// What are you doing today?# No speaker id; will assume prior speaker.
// [c9]1/Stop prying, you!  # char delay spec + speaker id + speech
// [l3c7]Sorry.  I snapped. # line delay spec + char delay spec (reversible) + speech (speaker id inherited)
function parseChatLine(theline) {
	var VALIDTIMERFLAGS = 'iclbh';  // Note: h is actually for hue
	var TIMINGSPEC_MAXSIZE = 2*VALIDTIMERFLAGS + 2; // a number for each flag, and 2 brackets.
	var numbers = "0123456789";
    var chatarea = '';
	var speaker = '';
	var chattext = '';
	var idelay = 0;    // signifies using the default
	var cdelay = 0;    // signifies using the default
	var ldelay = 0;    // signifies using the default
	var bdelay = 0;    // signifies using the default
	var bghue = 0;	   // signifies using the default	
	var LEFTBRACKET = '[';
	var RIGHTBRACKET = ']';
	var rightbracketpos = -1;  // assume there is no bracket spec.
	//	var thisChatLine = new chatLine; // make certain this defaults to empty strings for all.
	var offset = 0;  // By default, we start at beginning of string (start index of 1)
	// Check for timing spec ('['):
	if (theline.substr(0,1) == LEFTBRACKET)
	{
		rightbracketpos = theline.indexOf(RIGHTBRACKET);  // note that position is 0-based.
		//alert("rightbracketpos is " + rightbracketpos);
		if (rightbracketpos > (TIMINGSPEC_MAXSIZE - 1))
		{
			alert("Faulty timing spec: " + rightbracketpos + " exceeds max size of " + TIMINGSPEC_MAXSIZE);
			// take some reasonable action.  bail on spec or the line.
		}
		else if (rightbracketpos < 0)
		{
			alert("Faulty timing spec: Missing right bracket");
			// take some reasonable action.  bail on spec or the line.
		}
		// ??? already initialized offset to 1; is that correct? offset = 0;
		offset++;  // Move past left bracket.
		while (offset < rightbracketpos)   // (offset != rightbracketpos)
		{
			timerflag = theline.substr(offset,1).toLowerCase();
			if (VALIDTIMERFLAGS.indexOf(timerflag) == -1)
			{
				alert("Invalid timer flag (" + timerflag + ") detected");
				// take some bloody action.  Maybe bail on the spec or the line.
			}
			
			if (timerflag == 'i')
			{
				idelay = theline.substr(offset+1,1);
				//alert("Timerflag: Got initial delay of " + idelay);
				idelay = calc_initialdelay(getvalidindex(idelay,initialdelay_cafe));
			}
			else if (timerflag == 'c')
			{
				cdelay = theline.substr(offset+1,1);
				//alert("Timerflag: Got char delay of " + cdelay);
				cdelay = calc_chardelay(getvalidindex(cdelay,chardelay_cafe));
			}
			else if (timerflag == 'l')
			{
				ldelay = theline.substr(offset+1,1);
				//alert("Timerflag: Got line delay of " + ldelay);
				ldelay = calc_linedelay(getvalidindex(ldelay,linedelay_cafe));
				//alert("After calc: Timerflag: Got line delay of " + ldelay);
			}
			else if (timerflag == 'b')
			{
				bdelay = theline.substr(offset+1,1);
				//alert("Timerflag: Got burst delay of " + bdelay);
				bdelay = calc_burstdelay(getvalidindex(bdelay,burstdelay_cafe));
			}
			else if (timerflag == 'h')   // This is actually for hue
			{
				bghue = theline.substr(offset+1,1);
				//alert("Timerflag: Got burst delay of " + bdelay);
				bghue = calc_bghue(getvalidindex(bghue,bghue_cafe));
			}			
			offset = offset + 2;  // advance past the timer flag and its integer value.
		}
		if (theline.substr(offset,1) == RIGHTBRACKET)
		{
			// let's step one past, okay?
			offset++;
		}
	}
	if (numbers.indexOf(theline.substr(offset,1)) != -1) {
		// alert("detected leading number " + theline.substr(offset,1) + "!");	
		// thisChatLine.chatarea = theline[0];
		chatarea = theline.substr(offset,1);
		// alert("Before speaker definition test, theline is " + theline);
		// alert("substring 1,1 is " + theline.substr(1,1));
		if ((theline.substr(offset).length > 1) && (theline.substr(offset).substr(1,1) == '=')) {
			// We've got a speaker definition.
			// alert("detected speaker definition!");	
			// thisChatLine.speaker = substring(theline,3);
			// alert("In speaker definition, theline is " + theline);
			speaker = theline.substr(offset).substr(2);
			// alert("speaker is " + speaker);
		}
		else {
			// Line is of the form:  2/I am chatting away.
			// thisChatLine.chattext = substring(theline,3);			
			chattext = theline.substr(offset).substr(2);			
		}
	}
	else {
			// Line is of the form:  I am chatting away.
			// alert("Just chat text: " + theline);
			// thisChatLine.chattext = theline;
			chattext = theline.substr(offset);
	}
	// Note that we have no awareness of args 2 and 3 (burstnum and burstnumline),
	// as that info is not part of a line entity.  So the caller (parseChatFile)
	// will need to add that.
	var thisChatLine = new chatLine(chatarea,speaker,"","",chattext,idelay,cdelay,ldelay,bdelay,bghue);
	return thisChatLine;
	}

	
//  function isLeadingNumber(theline) {
//	var regex=/[0-9]/;
//	if(regex.test(theline[0])){
//		alert("detected leading number!");
//		return true;
//	} else {
//		alert("Did not see a leading number...");
//		return false;
//	}
//	}

  function showChatLine(chatline) {
		alert("chatarea / speaker / text == " + chatline.chatarea + " / " + chatline.speaker+ " / " +  chatline.chattext);

//		document.writeln("<p>" + chatline.chatarea);
//  		document.writeln(" : " + chatline.speaker);
//		document.writeln(" : " + chatline.chattext + "</p>");
	}  

  function showBurst(burst) {
	var i;
	// alert("In showBurst, burst.length is " + burst.length);
	for (i=0;i < burst.length; i++) {
		showChatLine(burst[i]);
	}
	}  

  function showAllBursts(thebursts) {
  	var ab;
	for (ab=0; ab < thebursts.length; i++) {
		showBurst(thebursts[ab]);
	}
  }

// parseChatFile reads an array of lines (tl) representing the contents of a user file, and
// creates an array fully describing how each line is to be typed out.  The input array is not
// well-formed, as the user is allowed to use shortcuts and defaults during data entry.
// The output array massages this into an array that fully describes each line for ease of
// typing out by typetext
  function parseChatFile() {
    // ???curTopic and curIndex probably relate curBurst.  Let's assume that.
    // Read the file line by line.
	var burst = 0;  // Try 0 for now, assuming array indexing methodology
	var pendingnewburst = 0; // flag to detect (and ignore) multiple blank lines.
	var currentspeaker = -1;
	var chatlineidx = -1;  // can't use the for loop "i" since it counts blank lines, etc.
	var currentchatarea = -1;  // Not certain this is needed or used...
// global?	var bursts = new Array();
	//	var chatlines = new Array();
	// Need to prime first burst for pushing one chatline after another.
	//*alert("setting new Array for bursts[" + burst + "]");
	// chatlines = new Array();  // must this be global? bursts worked okay via next line...
	//bursts[burst] = new Array();
	for (var i=0;i < tl.length; i++) {
		var thisline = new String(tl[i]);
		// alert("This is thisline:" + thisline);
		thisChatLine = parseChatLine(thisline);
// showChatLine(thisChatLine);		
		if ((thisChatLine.chattext == "") && (thisChatLine.speaker == "")) {
			//*alert("Detected a fucking blank line, thank you very much.");
			// This was a blank line; we're starting a new burst.
			if (pendingnewburst) {
				//*alert("Previous line was blank; don't increment for consecutive blank lines");
				continue;  // nothing to do on this loop.
			}	
			burst++;
			pendingnewburst = 1;  // Flag the detection of a new burst.  Where do we unset?
			continue;  // We're done with this line.
		}

		// Here's the logic with speaker.  First off, speaker is a name field.
		// So it has values like 'Sally' or 'Henry'.  If non-null, we know the line
		// was a speaker definition -- associating a name with a chatarea.  In essence:
		// 3=George
		// So we mustn't count this line as a chatline.  But how exactly do we handle it?
		// Well, we maintain (in this function only) an array associating speaker with chatarea.
		// These associations can be changed and overwritten any number of times during a burst
		// or bursts.  But at the bottom of the loop, the actively assigned speaker is grabbed
		// from this array and stuck in the current chatline.  I believe this allows one to
		// put new speaker definitions anywhere in the input, so boxes can change speakers on
		// the fly.
		if (thisChatLine.speaker != '') 
		{
			// We are defining a new speaker in terms of a chatarea; speaker and chatarea
			// are both guaranteed specified.
			// Note that we might override earlier speaker, but that is fine.
			// Make certain this array technique works.  For instance, if we start with
			// chatarea of 4, will that work?  Or do I need a special associative array?
			// alert("Detected speaker = " + thisChatLine.speaker + ", chatarea is " + thisChatLine.chatarea + ", speakers.length is " + speakers.length);
			speakers[thisChatLine.chatarea] = thisChatLine.speaker;
			currentchatarea = thisChatLine.chatarea; // Default next chatline to this chatarea
			continue; // We're done with this line.
		}

		// If we reach this point, we have a line with chattext, and it will be counted.
		pendingnewburst = 0; // this isn't a blank line; so clear this flag.
		chatlineidx++;
		chatlines[chatlineidx] = thisChatLine;

		if (thisChatLine.chatarea == '') 
		{
			if (currentchatarea == -1)
			{
				alert("Error: currentchatarea never defined!");
				// ought to take action
			}
			else
			{
				chatlines[chatlineidx].chatarea = currentchatarea;  // assume it is current speaker
			}
		}
		else
		{
			// chatarea was specified.  Let's make it currentchatarea.
			currentchatarea = thisChatLine.chatarea;
		}
		if (thisChatLine.idelay == 0) 
		{
			chatlines[chatlineidx].idelay = calc_initialdelay(initialdelay_cafe);
		}
		if (thisChatLine.cdelay == 0) 
		{
			chatlines[chatlineidx].cdelay = calc_chardelay(chardelay_cafe);
		}
		if (thisChatLine.ldelay == 0) 
		{
			chatlines[chatlineidx].ldelay = calc_linedelay(linedelay_cafe);
		}
		if (thisChatLine.bdelay == 0) 
		{
			chatlines[chatlineidx].bdelay = calc_burstdelay(burstdelay_cafe);
		}
		if (thisChatLine.bghue == 0) 
		{
			chatlines[chatlineidx].bghue = calc_bghue(bghue_cafe);
		}
//alert("I am line " + chatlineidx + ", and I will be " + chatlines[chatlineidx].bghue);
//alert("in parseChatFile, done with line: i=" + chatlines[chatlineidx].idelay + ",c=" + chatlines[chatlineidx].cdelay + ",l=" + chatlines[chatlineidx].ldelay + ",b=" + chatlines[chatlineidx].bdelay);
		// Now ensure that we get the latest speaker for the line's chatarea.
		chatlines[chatlineidx].speaker = speakers[chatlines[chatlineidx].chatarea];
		chatlines[chatlineidx].burstnum = burst;
	}
	return (chatlines[chatlineidx].burstnum+1);
} // end parseChatFile

  function doBurst() {
    // ???curTopic and curIndex probably relate curBurst.  Let's assume that.
//    Read (and parse) a line from the array.
//    While line ne blank {
//      if (chatarea = leadingnumber()) {
//        speaker = getspeaker(chatarea);
//      }
//      else {
//        chatarea = activechatarea;
//        speaker = activespeaker;
//      }
//      type_text(chatarea,speaker);
    }

  function hideChatAreas() {
	var ca_tmpname;
	// alert("in hideChatAreas: speakers.length is " + speakers.length);
	for (i=0;i < speakers.length; i++) {
		// alert("speakers[" + i + "] is " + speakers[i]);
		// Because (I think) we stored in an associative way, length is not reliable.
		// There can even be holes in the array.  Someone could have defined usage of
		// chatareas 4 and 2.  So let's test for undefined at each index value.
		if (typeof(speakers[i]) != "undefined") {
  		    // alert("Passed undefined test: speakers[" + i + "] is " + speakers[i]);
			ca_tmpform = getChatFormName(i);
			ca_tmparea = getChatTextAreaName(i);			
		    // document.eval(ca_tmpname).style.background-color = "#ffffcc";
	   		document[ca_tmpform][ca_tmparea].style.visibility = "hidden";
		}
    }
  }

//  function dimChatArea(chatareanum) {
//	var ca_tmpname;
//    ca_tmpname = 'chatarea' + chatareanum + 'form.chatarea' + chatareanum;
//	document.eval(ca_tmpname).style.backgroundColor = "#CCCCCC";
//  }
  function dimChatArea(chatarea) {
	  var ca_form = getChatFormName(chatarea);	
	  var ca_area = getChatTextAreaName(chatarea);		  
      document[ca_form][ca_area].style.backgroundColor = CA_DIMMED_BG_COLOR;
      document[ca_form][ca_area].style.color = CA_DIMMED_TXT_COLOR;
  }

// A javascript version of PHP's in_array function 
Object.prototype.in_array = function(datum, strict) {
	if (strict) function equals(a,b) { return a === b }
	else function equals(a,b) { return a == b }
	for (var i in this) {
		if (equals(this[i], datum)) return true;
	}
	return false;
}

// A hypothetical use of the above prototype in_array
//		if (speakers.in_array(i)) alert("Hey, " + i + " is in speakers array");
//		alert("speakers[" + i + "] is " + speakers[i]);


function getChatFormName(chatarea) {
   return 'chatarea' + chatarea + 'form';
}
function getChatTextAreaName(chatarea) {
   return 'chatarea' + chatarea;
}
