	      
      // state of this page
      //    0 - editing content; the next action is submitText request
      //    1 - SpellCheckSuggestions have been received; now the user is selectin suggestions;
      //	    the next request is UserChoices request.
      //    2 - user has edited word; now all suggestions are cleared ??? and the next request is a submitTextRequest
      var UI_page_state = 0;

      // text colors
      var UI_edit_text_color = 'black';
      var UI_edit_background_color = 'white';
      var UI_edit_font_size = '12pt';
      var UI_edit_font_face = 'georgia';
    
      var UI_mark_misspelled_words_color = '#FF0033'; //'deeppink';
      var UI_mark_confused_words_color = '#3300ff' ;//'blueviolet';

      // input length limit
      var UI_text_length_limit = 1000; 

      // logic stuff.
      var UI_suggestion_count = 0;

      var UI_speak_edit_text = 0; 	
       
      var UI_is_speaking = 0;   
      var UI_is_stopping = 0;
      var on_stop_speaking = null;

      // toolbar stuff.
      _dynarch_menu_url = "/ghotit/hmenu2.9/";
      var toolbar_menu;


        /*
	var UI_SAPI_voice = null;
	var UI_SAPI_holder = null;
	*/
      	
        try {	
	  var holder = new ActiveXObject("Gsapictl.GHOTITSAPIINIT.1");
	  var UI_SAPI_voice  =  holder.SPVoice;
        } catch(e) {
	  var holder = null; 
	  var UI_SAPI_voice = null; 
        }

	//var profile_T1,profile_T2,profile_T3,profile_T4;
	
	var UI_tts_language = "uk-eng";
        var UI_tts_enabled  = 1;

	function VOICE_enabled()
	{
	   return holder != null;  
	}
	function VOICE_speak_do(text,uimessage)
	{
	  if ( UI_SAPI_voice != null && UI_tts_enabled != 0) {
	
		if (UI_is_speaking != 0) {
		    if (uimessage == 0) { 
			UI_is_stopping = 2; 
		    } else { 
			if ( on_stop_speaking) {
			   on_stop_speaking = 0;
		        }
			UI_is_stopping = 0; 
		    }	
		    VOICE_stop(); 
		}	

		try
		{
		   var lid = UI_tts_language == "uk-eng" ? "809" : "9";
		   var txt = '<LANG LANGID="' + lid + '"> ' + text + ' </LANG>';
 	           //var txt = '<LANG LANGID="809"' + text + '</LANG> <LANG LANGID="9"> ' + TE
 		   return UI_SAPI_voice.Speak( txt, 9 );
		}
		catch(exception)
		{
		}
		return 0;
	  }	
	}
	function VOICE_speak(text)
	{
	   VOICE_speak_do( text, 0 );
	}
	function VOICE_ui_speak(text)
	{
	   VOICE_speak_do( text, 1 );
	}
	function VOICE_stop()
	{
	  if ( UI_SAPI_voice != null && UI_tts_enabled != 0) {
		try
		{
		   UI_SAPI_voice.Speak( "", 2 );
		}
		catch(exception)
		{
		}	    
	  }	
	}
	function VOICE_get_volume()
        {
	  if ( UI_SAPI_voice != null ) {
	    try {
	      return UI_SAPI_voice.Volume;
	    } catch(e) {
	    }
          }
          return -1;
        }
	function VOICE_set_volume(vol)
        {
	  if ( UI_SAPI_voice != null ) {
	    try {
	      UI_SAPI_voice.Volume = vol;
	    } catch(e) {
	    }
          }
	}
	function VOICE_get_rate()
        {
	  if ( UI_SAPI_voice != null ) {
	    try {
	      return UI_SAPI_voice.Rate;
	    } catch(e) {
	    }
          }
          return -1;
        }
	function VOICE_set_rate(vol)
        {
	  if ( UI_SAPI_voice != null ) {
	    try {
	     UI_SAPI_voice.Rate = vol;
	    } catch(e) {
	    }
          }
	}
	function VOICE_get_voice()
        {
	  if ( UI_SAPI_voice != null ) {
	    try {
	      return UI_SAPI_voice.Voice.GetDescription();
	    } catch(e) {
	    }
          }
          return -1;
        }
	function VOICE_set_voice(vol)
        {
	  if ( UI_SAPI_voice != null ) {
	    try {
	     UI_SAPI_voice.Voice = UI_SAPI_voice.GetVoices().Item(vol);
	    } catch(e) {
	    }
          }
	}
	function VOICE_set_voice_by_name(val)
        {
	  var VoicesToken = UI_SAPI_voice.GetVoices();

  	  // Add correct strings to Voice Select box
  	  for( var i=0; i<VoicesToken.Count; i++ )
	  {
		if (val == VoicesToken.Item(i).GetDescription()) {
	     	   VOICE_set_voice(i);
		   break;
		}
	  }
	}

	function VOICE_cleanup()
	{
	  if ( UI_SAPI_voice != null ) {
	    delete UI_SAPI_voice;  
	    delete UI_SAPI_holder;
            UI_SAPI_voice = null;
            UI_SAPI_holder = null; 
          }
        }
 	
	
	function enter_edit_mode()
	{ 
		   ui_clear_word_menues(); 
		   ctl_by_id('content').value = get_correction_text(); 
		   ctl_set_visible("suggestion_pane",0);
		   ctl_set_visible("content",1);
		   UI_init_state(0);
		   if (UI_last_selected_word != 0) {
		     ctl_set_sel("content", UI_last_selected_word, UI_last_selected_word); 
		   }
		   
	}


	function ui_clear_word_menues()
	{
	    //delete all menues (to prevent leaks)
	    clear_suggestions(1);
	}

      function talk_menu_set_image(state) 
      {
	    if (state) {	
		ctl_by_id("talk_btn").src = "/ghotit/stop.jpg";
	    } else {
		ctl_by_id("talk_btn").src = "/ghotit/play.jpg"; 
	    }
      }

     
      function toolbar_menu_handler(action) {
	      var li = action.params;
	      var style = ctl_by_id('content').style;
	      var style_alt = ctl_by_id('suggestion_pane').style; 

	      if (li.title == "spell-check") {
		   // spell checker
		   ui_check_spelling(); 
	      }
	      else if (li.title == "Talk") {
		DynarchMenu._closeOtherMenus( null ); 
		if (VOICE_enabled()) {
		   if (UI_speak_edit_text == 0) {
		     var text;
	             if (UI_page_state == 0) { // edit state
		       text = ctl_by_id('content').value;
		       // on screen we see edit control, where text is stored ad \r\n (i.e. windows)
		       // we need text of same length in order to sync selection with spoken text.
		       text = text.split( "\r\n" ).join( " ");
		     } else { // correction state
		       text = get_correction_text();
		       // hack hack hack
		       //text = text.split( "-" ).join( " - ");
 
		     }
	             UI_speak_edit_text = 1; 			   
		     ctl_debug_output( '[set UI_speak_edit_text = ' + UI_speak_edit_text  + ']'); 
		     VOICE_speak(text);
	   	      
		     talk_menu_set_image( 1 ); 			
		    } else {
	             talk_menu_set_image( 0 ); 
		     VOICE_stop();		 	 		      
 		    }
		 }
 	      } 
	      else if (li.title == "edit-text") {
 
		       enter_edit_mode(); 
	      }
	      else if (/^FONT-SIZE\/(.*)/.test(li.title)) {
		      var font_size_item = toolbar_menu.items["font-size"];
		      font_size_item.setLabel(RegExp.$1);
		      
		      style.fontSize = RegExp.$1;
		      style_alt.fontSize = RegExp.$1;
		      
		      UI_edit_font_size = RegExp.$1;
	      } else if (/^FONT\/(.*)/.test(li.title)) {
		      var font_item = toolbar_menu.items["fonts"];
		      font_item.setLabel(action.info.label);
		      
		      style.fontFamily = RegExp.$1;
		      style_alt.fontFamily = RegExp.$1;
			      
		      UI_edit_font_face = RegExp.$1;
	      } else if (/^FORMAT\/(.*)/.test(li.title)) {
		      var value = RegExp.$1;
		      action.info.setPressed();
		      if (value == "bold") {
			      style_alt.fontWeight = style.fontWeight = action.info.pressed ? "bold" : "normal";
		      } else if (value == "italic") {
			      style_alt.fontStyle = style.fontStyle = action.info.pressed ? "italic" : "normal";
		      } else if (value == "underline") {
			      style_alt.textDecoration  = style.textDecoration = action.info.pressed ? "underline" : "none";
			      toolbar_menu.items["strike"].setPressed(false);
		      } else if (value == "strike") {
			      style_alt.textDecoration = style.textDecoration = action.info.pressed ? "line-through" : "none";
			      toolbar_menu.items["underline"].setPressed(false);
		      }
	      } else if (/^FG\/(.*)/.test(li.title)) {
		      var color = RegExp.$1;
		      if (color != UI_edit_background_color) { 
                        if (color != "none")
			      style_alt.color = style.color = color;
		        else
			      style_alt.color = style.color = "";
		        var icon = toolbar_menu.items["foreground"].icon;

                        icon.className = "color-" + color;
		        UI_edit_text_color = color;
		      }	
	      } else if (/^BG\/(.*)/.test(li.title)) {
		      var color = RegExp.$1;
		      if (color != UI_edit_text_color) { 
 
                        if (color != "none")
			      style_alt.backgroundColor = style.backgroundColor = color;
		        else
			      style_alt.backgroundColor = style.backgroundColor = "";

		        var icon = toolbar_menu.items["background"].icon;
                        icon.className = "color-" + color;
		        UI_edit_background_color = color;
	             }		
              } else {
		    alert("not-handled: " + li.title);
	      }
      };
      function toggleJustify(action) {
	      var item = toolbar_menu.items["justify"];
	      item.display();
	      action.info.icon.src = item.visible ? "/ghotit/hmenu2.9/icons/checkbox-1.gif" : "/ghotit/hmenu2.9/icons/checkbox-0.gif";
              return true;
      };
      function togglePaste(action) {
	      var item = toolbar_menu.items["paste"];
	      item.disable(!item.disabled);
	      action.info.icon.src = item.disabled ? "/ghotit/hmenu2.9/icons/checkbox-0.gif" : "/ghotit/hmenu2.9/icons/checkbox-1.gif";
              return true;
      };
      function toggleTooltips(action) {
	      var item = action.info;
	      var toolbar_menu = item.menu;
	      toolbar_menu.config.tooltips =! toolbar_menu.config.tooltips;
	      item.icon.src = toolbar_menu.config.tooltips ? "/ghotit/hmenu2.9/icons/checkbox-1.gif" : "/ghotit/hmenu2.9/icons/checkbox-0.gif";
              return true;
      };
      function selectSkin(action) {
	      var item = action.info;
	      var a = ["modern", "xp", "xp-apps", "win2k", "win98", "aqua"], l;
	      for (var i = 0; i < a.length; ++i) {
		      l = document.getElementById("theme-skin-" + a[i]);
		      if (l)
			      l.disabled = true;
	      }
	      l = document.getElementById("theme-" + item.id);
	      if (l) {
		      l.disabled = false;
		      toolbar_menu.items["skin"].setLabel("Skin: " + l.title);
	      }
      };



function ui_add_tts_voice_options()
{
	var ctl = ctl_by_id("ids_tts_voice");
	
	if (!VOICE_enabled()) {
	 var ctlP = ctl_by_id("ed-menu");
	 var ctlO = ctl_by_id("ttsOptions");
	 ctlP.removeChild( ctlO );

	 ctlO = ctl_by_id("ttsTalk");
	 ctlP.removeChild( ctlO );
	 return;
	}

	// Initialize the Voices and AudioOutput Select boxes
	var VoicesToken = UI_SAPI_voice.GetVoices();

	// Add correct strings to Voice Select box
	for( var i=0; i<VoicesToken.Count; i++ )
	{
		var oOption = document.createElement("OPTION");
		ctl.options.add(oOption);
		oOption.innerText = VoicesToken.Item(i).GetDescription();
		oOption.value = i;
	}
}

function get_cookie ( cookie_name )
{
  var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)' );

  if ( results )
    return ( unescape ( results[2] ) );
  else
    return null;
}                    	


function ui_tts_set_options(val)
{
     var vals = val.split("#");

     VOICE_set_volume(vals[0]);
     VOICE_set_rate(vals[1]);
     VOICE_set_voice_by_name(vals[2]);

     UI_tts_language = vals[3];
     UI_tts_enabled =  vals[4];
}

function ui_tts_read_options()
{
  if (!VOICE_enabled()) {
     return;
  }

  var cookie = get_cookie( 'ghotit-tts-settings' );

  if (cookie != null) {
     ui_tts_set_options( cookie );	
  }  
}

function ui_tts_current_options()
{
   var val = VOICE_get_volume() + "#" + VOICE_get_rate() + "#" + VOICE_get_voice() + "#" + UI_tts_language + "#" + UI_tts_enabled;
   return val;
}


var ui_voice_settings_dialog = null;



function ui_tts_cancel()
{
   ui_tts_set_options( ui_tts_coptions );

   // hide dialog
   ui_voice_settings_dialog.close();     
   ui_voice_settings_dialog = null;

}

function ui_tts_apply()
{  
   if (!VOICE_enabled()) {
     return;
   }

   var val = ui_tts_current_options();
   var date = new Date( 2015, 01, 01 );
   document.cookie = 'ghotit-tts-settings=' + escape(val) + ' ;expires=' + date.toGMTString();

 	
   // hide dialog
   ui_voice_settings_dialog.close();     
   ui_voice_settings_dialog = null;

}

function ui_tts_enable()
{
   UI_tts_enabled = ctl_by_id("ids_tts_enable").checked == true ? 1 : 0;
}


function ui_tts_test()
{
  VOICE_ui_speak("The quick brown fox jumps over the lazy dog.");
}

function ui_tts_change_rate(dir)
{
   var rate = VOICE_get_rate();

   if (dir > 0) {
	rate += 2;
	if (rate >= 10) {
	  rate = 10;
	}
   } else {
	rate -= 2;
	if (rate <= -10) {
	  rate = -10;
	}
   }
   
   ctl_set_text("ids_tts_rate", rate );
   VOICE_set_rate( rate );
}

function ui_tts_change_volume(dir)
{
   var rate = VOICE_get_volume();

   if (dir > 0) {
	rate += 10;
	if (rate >= 100) {
	  rate = 100;
	}
   } else {
	rate -= 10;
	if (rate <= 0) {
	  rate = 0;
	}
   }

   ctl_set_text("ids_tts_volume", rate );
   VOICE_set_volume( rate );
}

function ui_tts_change_lang()
{
   var ctl = ctl_by_id( "ids_tts_lang" );
   UI_tts_language = ctl.value;
}


function ui_tts_change_voice()
{
	var ctl = ctl_by_id( "ids_tts_voice" );
	var i = parseInt( ctl.value );
	VOICE_set_voice( i );
}

var ui_tts_coptions;


function ui_tts_init_dialog()
{
	ui_tts_coptions =  ui_tts_current_options(); 

	var ctl = ctl_by_id( "ids_tts_voice" );
        var i;
	var vname = VOICE_get_voice();
	
	for(i =0; i< ctl.options.length; i++) {
	    if ( ctl.options(i).text ==  vname) {
               ctl.selectedIndex = i;
	       break;
	    }
 	}

	ctl = ctl_by_id( "ids_tts_lang" );
	ctl.value =  UI_tts_language;

        ctl_set_text("ids_tts_volume", VOICE_get_volume() );
   
	ctl_set_text("ids_tts_rate", VOICE_get_rate() );


	ctl_by_id("ids_tts_enable").checked = UI_tts_enabled != 0 ? true : false;


}


/*
function cleanup_editor_page()
{
  DynarchMenu._cleanUp();
  clear_suggestions(1);
}
*/



function init_editor_page()
{
  //VOICE_init();

  ui_add_tts_voice_options();
  ui_tts_read_options();
  
  toolbar_menu = DynarchMenu.setup('ed-menu', 
			{   toolbar: true , 
			    onCloseDown: ui_close_main_menu , 
			    onPopup: ui_before_main_menu 
			});



//toolbar_menu_alt = DynarchMenu.setup('ed-menu-alt', { toolbar: true });	

  var icon = toolbar_menu.items["foreground"].icon;
  icon.className = "color-black";
	
  UI_init_state(0); 
}

var UI_prev_char;

function init_classify_char()
{
  UI_prev_char = -1;
}

var convert_table = new Array();

convert_table[ 0x2018 ] =  String.fromCharCode( 39 ); // "'";
convert_table[ 0x2019 ] =  String.fromCharCode( 39 ); // "'";
convert_table[ 0x201c ] =  String.fromCharCode( 34 ); // '"';
convert_table[ 0x201d ] =  String.fromCharCode( 34 ); // '"';

/*
   classify a character during parsing/tokenization of user text.
 */
function classify_char(ch, next_ch)
{
  var chCode = ch.charCodeAt( 0 );
  if (convert_table[ chCode ] != undefined ) {
    ch = convert_table[ chCode ];
  }
  
  if (ch == ' ' || ch == '\t' || ch =='\r' || ch == '\n') {
    UI_prev_char = 1;
    return 1; // whitespace
  }  

  if (ch == ':' || ch ==';' || ch ==',' || ch =='.' || ch == '!' || ch == '?' || ch == '>' || ch == '<' || ch == '|' || ch == '\\' || ch == '/') {
     UI_prev_char = 2;
     return 2; // separator token
  }

  // ever-green => ever <brace> green
  if ( ch == '-' && UI_prev_char == 4) {
      return 3;
  }    

  // that's will not break the current token; 
  if ( ch == "'" ) {
     UI_prev_char = (UI_prev_char == 4 && classify_char( next_ch, ' ') == 4) ? 4 : 3;
     return UI_prev_char;
  }

  if (ch == '(' || ch == ')' || ch == '{' || ch == '}' || ch == '[' || ch ==']'  || 
      ch == '\"' || ch == '`') {
     UI_prev_char = 3;
     return 3; // brace
  } 

 

  UI_prev_char = 4;
  return 4; // anything else is a word token ??? (should not be)
}


// dom construct that will replace the edit pane for selection of spelling errors.
var UI_root_elm;

function UI_init_state(state)
{
  // enter edit mode
  if (state == 0) {
    UI_page_state = 0;
    ui_status_show_message("Please enter your text");
    on_text_change(); 
    toolbar_menu.items['edit-text'].disable(1); 
    ctl_by_id("content").focus();
  }

  // enter correction mode
  if (state == 1) {
    UI_page_state = 1;
    
    ui_status_show_message("Please make your corrections. ");
    toolbar_menu.items['edit-text'].disable(0); 
  
     if (UI_suggestion_count == 0) {
	enter_edit_mode();
	ui_status_show_message("Ghotit is done."); 
	//ui_status_show_message("The spelling corrections have been made."); 
     }
   
  }
}  

function ui_emit_token_init()
{
  UI_root_elm = document.createElement("div");
  UI_root_elm.setAttribute("id","suggestion_pane");
  UI_root_elm.style.width = '84%';
  UI_root_elm.style.height =  '180px';  //ctl_by_id('content').style.width
  
  UI_root_elm.style.borderWidth = '2px';
  UI_root_elm.style.borderStyle = 'dashed';
  UI_root_elm.style.borderColor = '#eee';
  
  UI_root_elm.style.color  = UI_edit_text_color; 
  UI_root_elm.style.backgroundColor = UI_edit_background_color;  
  UI_root_elm.style.fontSize = UI_edit_font_size; 
  UI_root_elm.style.fontFamily = UI_edit_font_face; 
  UI_root_elm.style.overflow = "auto";

   
 
/* 
  ///([^p]*)pt/.test(UI_edit_font_size);
  var height = UI_root_elm.style.lineHeight;
  //height += 1;
  UI_root_elm.style.lineHeight =  height + "pt"; //UI_edit_font_size
*/ 
}

function ui_add_tag_txt(stag,stext)
{
   var elm = document.createElement( stag );
   UI_root_elm.appendChild( elm );
   
   if (stext != null) {
      var txt = document.createTextNode( stext );
      elm.appendChild( txt );
   }  
   return elm;
}

function ui_add_tab()
{
   var elm = document.createElement( "SPAN" );
   UI_root_elm.appendChild( elm );
   
   var txt = document.createTextNode("\u00a0\u00a0\u00a0\u00a0" );
   elm.appendChild(txt);
}

function ui_add_text(stext)
{
  var txt = document.createTextNode( stext );
  UI_root_elm.appendChild( txt );
} 

function ui_add_tag(stag)
{
  return ui_add_tag_txt(stag,null);
}

function set_menu(next_word,wid)
{
		next_word.onclick = next_word.oncontextmenu = function(ev) { UI_delayed_context_menu(ev, wid ); }; 
}
 
function ui_emit_token(stext,type,word_id)
{
  if (type == 1) { // whitespace character
    if (stext == ' ') {
       ui_add_text(" ");
    }
    if (stext == '\t') {
       //ui_add_text("   ");
       ui_add_tab();
    }
    if (stext == '\n') {
      ui_add_tag("br"); 
    }
  }
  
  if (type == 4) { // a word word
     var t = ui_add_tag_txt("div", stext);

     t.setAttribute("id", "w_" + word_id);
     set_menu(t,word_id);
     t.style.display = "inline";
 }
  
  if (type >= 2 && type <= 3) { // separator or tag
     var t = ui_add_tag_txt("div", stext);
    
     t.style.display = "inline";
  }
}

// globals for forming of xml request
var request_text;
var request_word_id = 0;

function emit_init(type, open)
{
   if (type == 0) {
     if (open) {
        ui_emit_token_init();

        request_text = "<submitText>";
        request_word_id = 1;
    } else {
        request_text = request_text + "</submitText>";
     }
   }
   if (type == 1) {
     if (open) {
       request_text = "<userChoices>";
     } else {
       request_text = request_text + "</userChoices>";  
     }
   }  
}

function emit_user_choice(action,wid,sid)
{
  if (action == 1) {
    request_text += "<sel wid=\"" + escape(wid) + "\" sid=\"" + escape(sid) + "\"/>";
  }
  if (action == 2) {
    request_text += "<ign wid=\"" + escape(wid) + "\"/>";
  }
  if (action == 3 || action == 5) {
    request_text += "<skipnow wid=\"" + escape(wid) + "\"/>";
  }
  if (action == 4) {
    request_text += "<modifyword wid=\"" + escape(wid) + "\" val=\"" + escape(sid) + "\"/>";
  }  
}

function emit_token(stext,type)
{
  if (type == 4) { // word
    request_text = request_text + "<wd id='" + escape( request_word_id ) + 
				  "' val='" +  escape( stext ) + "'/>";
    ui_emit_token(stext,type,request_word_id);
	    
    request_word_id ++;
   }
  
  if (type == 2) { // separator
    request_text = request_text  + "<sep val='" + escape( stext ) + "'/>";
   
    ui_emit_token(stext,type,request_word_id);
  }

  if (type == 1) {
    ui_emit_token(stext,type,request_word_id);
  }
  
  if (type == 3) { // brace
    ui_emit_token(stext,type,request_word_id);
    
    if (stext == '"') {
       stext = "\"";
    }
    // <sep used to be <brace
    request_text = request_text  + "<sep val='" + escape( stext ) + "'/>";
  }
}

var convert_table_web = new Array();
convert_table_web[ '%u2018' ] =  escape("'");
convert_table_web[ '%u2019' ] =  escape("'");
convert_table_web[ '%u201c' ] =  escape('"');
convert_table_web[ '%u201d' ] =  escape('"');

function parse_text(stext)
{
  var i;
  var state = 0;
  var word = "";
  var umlen;
 
   
   umlen = stext.length - 1;

  emit_init(0,1);

  init_classify_char();

  for(i = 0; i < stext.length; i++) {
     var ch = stext.charAt( i );
     var ty = classify_char(ch, i < umlen ? stext.charAt(i+1) : ' ');
    
     if (state == 0) { // not in a word 
	if (ty  >=1 && ty <= 3) {
	  emit_token(ch, ty);
	}
	if (ty == 4) {
	  state = 1;
	}  
     }
     if (state == 1) { // in word
	if (ty == 4) {
	  word = word.concat( ch );
	}
	if (ty >= 1 && ty <= 3) {
	  emit_token(word, 4);
	  word = "";
	  emit_token(ch, ty);
	  state = 0;
	}
     }      
  } 
  if (word != "") {
    emit_token(word, 4);
  }  
  emit_init(0,0);

  request_text = request_text.replace(/(\%u\S\S\S\S)/g,
	function($0) { 
	    var lc = $0.toLowerCase();
	    if (convert_table_web[ lc ] != undefined) {
	      return convert_table_web[ lc ]; 
	    }  
	    return $0; 
	} );
 
    return request_text; 
}

var UI_user_id="kuku";
var UI_in_post_request = 0;

var UI_wait_update_timeout_id;
var UI_wait_update_counter;

function updateWaitMessage()
{
  var txt = ctl_get_text("status_pane");
  var lastCh =  txt.charAt( txt.length - 1 ) ;

  if (lastCh == ')') {
    txt = txt.substr( 0, txt.lastIndexOf( ' ' ) ); 
  } 
  
  txt +=  " (" + UI_wait_update_counter + ")";

  ctl_set_text("status_pane", txt);
  
  UI_wait_update_counter ++;
  
  UI_wait_update_timeout_id = window.setTimeout("updateWaitMessage()",1000);

}


/*
    parameters: 
      surl
      vars
      onDatatCallback
      onError

    returns
      non zero if request has been sent but result has not yet arrived.
 
 */
function send_xml_ajax_post_requext(surl, vars, onDataCallback, onErrorCallback )
{
  var request;

  if (UI_in_post_request  != 0) {
     return;
  }
  UI_in_post_request =  1;

  if (window.XMLHttpRequest) {
    request = new XMLHttpRequest();
  } else {  
    request =  new ActiveXObject("MSXML2.XMLHTTP");
  }

  ui_status_show_message("Checking in progress. please wait.");
  
  UI_wait_update_counter = 1;
  UI_wait_update_timeout_id = window.setTimeout("updateWaitMessage()",1000);

  request.open("POST", surl, true );
  request.setRequestHeader("Content-Type", "text/xml") ;

  request.onreadystatechange = function() {
     if (request.readyState == 4) {
       	 UI_in_post_request = 0;
	 
	 ui_status_show_message("");
           
	 window.clearTimeout( UI_wait_update_timeout_id );
	 
	 if (request.status == 200) {

	   
	     if (request.responseXML) {
	       onDataCallback( request.responseXML );
	     }  else {
	       onErrorCallback( -1 );
	     }  
	     
	 }
	 if (request.status >= 400) {
	      if (onErrorCallback) {
                 onErrorCallback( request.status );
	      }
         }	
      }
   }
   request.send( vars );

   return request.readyState >= 2 && request.readyState < 4;
}


// the selected action per word
var UI_action_per_word = [];
// after data is received, each word gets its element entry here (first refers to xml, later to menu object)
var UI_xml_per_word = [];


// constructor - 
// ACTION
//  values
function UI_Menu_Action(action, wid, sid) 
{
   this.action = action;
   this.wid = wid;
   this.sid = sid;
}   

function ui_menu_item_clear_text(it) 
{
   var label = it.label;

   label = label.replace( /\_/, "" );
   label = label.replace( /<b unselectable='on'>/, "<EMPH>" );
   label = label.replace( /<\/b>/, "</EMPH>" );
   label = label.replace( /<u unselectable='on'>/, "" );
   label = label.replace( /<\/u>/, "" );
     
   return label;
}

function ui_tell_menu_item( item)
{
   VOICE_ui_speak( ui_menu_item_clear_text(item) );
}

function ui_tell_submenu( menu )
{
    if (!VOICE_enabled()) {
      return;
    }
    
    var first = menu.getFirstItem(); 	
    var it = first;
    var text = "";

    do {
      text += ui_menu_item_clear_text( it );

      if (text.length > 0 && text.charAt( text.length - 1 ) != '.') {
        text += '.'; 
      } 
      text += ' ';
				    
      it = menu.getNextItem( it ); 
    } while(it != first );

     VOICE_ui_speak( text );

}

function ui_close_main_menu( menu )
{
  ui_voice_settings_dialog = null;
}


function ui_before_main_menu( menu,item,pos )
{
  if ( item != null && item.label == "Settings" ) {
        ui_voice_settings_dialog = item.submenu;
	ui_tts_init_dialog();
  }

}

function on_close_ctx_menu( menu )
{
  VOICE_stop(); 
}

function ui_on_mouse_over( menu,item,pos ) 
{
  ui_tell_menu_item( item ); 
}

function ui_before_ctx_menu( menu,item,pos )
{
  
  window.is_khtml = false;
  if (!menu || !menu.id) {
    return;
  }  
 
  if (UI_in_post_request) {
     // if servicing request, then we don't want to see the menu - show it somewhere near alpha-centaurus.
     pos.y = 100000;
     pos.x = 100000;
   } else if (pos) {
    
  	
    var ctl = ctl_by_id( menu.id );
    var edit = ctl_by_id( 'suggestion_pane' ); //'content' );

    if (window.is_ie) {
     
       pos.y = ctl.offsetHeight; 
       while(ctl != document && ctl != null) {
	 pos.y += ctl.offsetTop;
	 ctl = ctl.offsetParent;
 	
       }
     } else if (window.is_khtml) {
       pos.y = ctl.offsetTop + ctl.offsetHeight;
       ctl_debug_output("I am on safari");
     } else {
       pos.y = ctl.offsetTop + ctl.offsetHeight;
       pos.y += ctl.offsetParent.offsetTop;//offsetHeight;
     }
    
     pos.y += 1;
     pos.y -= edit.scrollTop;
 
   } 
    
   //ctl_debug_output( "pos: " + pos.x + " " + pos.y );
}

function ui_on_edit_word( ctl, newText )
{
   if (newText == "" ) {
     return 0;
   }

   if (/w_(.*)/.test(ctl.getAttribute('id') ) ) {
     var word = RegExp.$1;

     ctl.style.color = UI_edit_text_color;
     ctl.style.fontWeight = 'bold'; 
     
					// action: word has been edited.
     UI_action_per_word[ word ]  = new UI_Menu_Action( 4, word, newText );
 
     // remove context menu from the word.
     //ctl.onclick = null;
     //ctl.oncontextmenu = null; 	
     //ctl.onmousedown = null;
     
     return 1;
   }  
   
   return 0;
}
 
function close_down_editor( wid, accept_changes )
{
  var ctl = ctl_by_id( wid );
  var pctl = ctl_by_id( "suggestion_pane" );
  
  // remove handlers (leaks)
  ctl.onblur = null;
  ctl.onkeypress = null;
  ctl.onkeydown = null; 
 
  pctl.replaceChild( ctl.oldCtl, ctl ); 
 
  if ( accept_changes && ui_on_edit_word( ctl.oldCtl, ctl.value )) {
     ctl_set_text( wid, ctl.value);

     ctl_by_id( wid ).style.color =  UI_edit_text_color;
     ctl_by_id( wid ).style.textDecoration = "underline";
  }
}

/*
function on_edit_word_blur(wid)
{
  close_down_editor( wid, 0 );
}
*/

function on_edit_word_key(ev,wid) 
{
  var key;

  if (ev) {
     if (ev.which) { 
       key = ev.which;
     } else {
       key = ev.keyCode;
     }
  } else {
     key = event.keyCode;
  }

  ctl_debug_output( key ); 

  // on enter - apply changes.
  if (key == 13) {
     close_down_editor( wid, 1 ); 
  }

  // on escape = bring down editor.
  if (key == 27) {
     close_down_editor( wid, 0 ); 
  }
}

function on_edit_word_text_change(wid)
{
  var ctl = ctl_by_id(wid);

  var svalue = ctl.value;
  var idx;
  
  // remove spaces
  //while( (idx = svalue.indexOf( ' ' )) != -1 ) {
  //   svalue = svalue.substring( 0, idx) + svalue.substring( idx+1, svalue.length );
  //}

  init_classify_char();

  var umlen = svalue.length - 1;

  //remove chars that would generate a new token
  var ret = "";
  for(idx = 0; idx < svalue.length; idx ++ ) {
   var ch = svalue.charAt( idx );
   if (classify_char( ch, idx < umlen ? svalue.charAt(idx+1) : ' '  ) == 4) {
     ret = ret + ch;
   }
  }

  ctl.value = ret;
}

function edit_word( word_id )
{
  var ctl = ctl_by_id( word_id );
  var pctl = ctl_by_id( "suggestion_pane" );

  var w = ctl.style.width;
  var h = ctl.style.height;
  var t = ctl_get_text( word_id );
  
  var input = document.createElement( "input" );
  input.setAttribute("id", word_id );
  input.setAttribute("type","text");

  // strange - onblur on mozilla has to be a closure - now way to pass parameters.
  input.onblur = function() { close_down_editor( word_id, 0 ); };
  input.onkeypress = function(event) {  on_edit_word_key( event, word_id ); };
  input.onkeydown = function(event) { on_edit_word_text_change( word_id); }; 
  
  input.value = t;
  input.style.width = w;
  input.style.height = h;
  
  // store away the old control
  input.oldCtl = ctl;

  pctl.replaceChild( input , ctl );
  
  input.focus();
}

var UI_last_selected_word = 0;

// suggestion menu item has been chosen
function ui_click_on_word( action )
{
  var title = action.params.title;
 
  /([^:]+):([^:]+):(.*):(.*)/.test(title);

  var word_id = RegExp.$1;
  var suggestion_id = RegExp.$2;
  var description_id =  RegExp.$3;
  var word_value = RegExp.$4;
     

  if (/w_(.*)/.test(word_id) ) {
     var word = RegExp.$1;
  
     UI_last_selected_word = word;
     
     var has_user_choice = 0;

     //alert( title + "~" + suggestion_id );
     if (suggestion_id >= 1000) {  // standard action

        if (suggestion_id == 1000) { // edit word
	   edit_word( word_id );
	}
        else if (suggestion_id ==  1001) {  // ignore suggestions
	  UI_action_per_word[ word ]  = new UI_Menu_Action( 2, word, null ); 
	  has_user_choice = 1; 
	}
	else if (suggestion_id == 1002) { // no suggestions relevant
	  UI_action_per_word[ word ]  = new UI_Menu_Action( 3, word, null ); 
	  has_user_choice = 1; 
	}
	else if (suggestion_id == 1003) { // undo suggestion
	 UI_action_per_word[ word ]  = null;
	} 
	else if (suggestion_id == 1004) { // search word in google 
          var sword = "define: " +  description_id;
          var url = "http://www.google.co.il/search?hl=en&q=" + escape( sword ) + "&btnG=Google+Search&meta="; 
 
	  try {
	    //Ghotit! - search word in google" 
            window.open( url, "Ghres", "height=600,width=600,toolbar=no,scrollbars=yes,status=yes");
          } catch(e) {
	    alert(e);
	  }
	} else if (suggestion_id == 1005) {
	     UI_action_per_word[ word ] =  new UI_Menu_Action(1, word, "1");
	     ctl_set_text(word_id,word_value);
	     has_user_choice = 1; 

	     // in addition delete next word.
	     var next_word = "w_" + (parseInt(word) + 1);
	     ctl_set_text(next_word,"");

	     
	}

     } else {  // select a given suggestion
	 UI_action_per_word[ word ] =  new UI_Menu_Action(1, word, suggestion_id);
	 ctl_set_text(word_id,word_value);
	 has_user_choice = 1; 

     }
     if (has_user_choice) { 
	 
	 var ctl = ctl_by_id(word_id);
	 
	 ctl.style.color =  UI_edit_text_color;
	 ctl.style.textDecoration = "underline";
	 ctl.style.borderBottom='none';
     
	 // count actual user choices done.
	 var uchoice = 0;
         for(var key in UI_action_per_word) {
	   if (UI_action_per_word[ key ].action != 5) {
	     uchoice += 1;
	   }
	 }
    
         if (uchoice >= UI_suggestion_count ) {
	    ui_check_spelling();
	 }
     }
    
  } 
}

// data definition for context menues - these are also built in DOM before passing it to menu system.
var UI_menu_root;

function ui_ctx_root_menu_init(ctlid)
{
  var mid = "rmenu_" + ctlid;

  var ctl = ctl_by_id(ctlid); 
  
  var old_menu = ctl_by_id(mid);
  
  if (old_menu) {
    ctl.removeChild( old_menu );
  }
  
  UI_menu_root = document.createElement("ul");
  UI_menu_root.setAttribute("id", mid );
  UI_menu_root.setAttribute("onclick",'ui_click_on_word( this );'); 
  UI_menu_root.style.display = 'none';

  ctl.appendChild(UI_menu_root);

  return "rmenu_" + ctlid; 
}

function ui_ctx_menu_init(parentMenu, sid, stext)
{
  var item_menu;
  var menu;

  item_menu = document.createElement("li");

  if (sid != null) {
     item_menu.setAttribute("id","menu_" + sid);
  }   
  parentMenu.appendChild(item_menu);

  if (stext != null) {
    var dtxt = document.createTextNode( stext );
    item_menu.appendChild( dtxt );
  }  

  menu = document.createElement("ul");
  item_menu.appendChild( menu );  
  return menu;
}


function ui_ctx_menu_add_item( menu, actionid, wid, stext, boldText )
{
  var item = document.createElement("li");

  if (actionid != null) {

    item.setAttribute("title", actionid + ":" + wid );
 
    if ( boldText != null) {

        stext = "$" + boldText + " " + stext;
    
      /*
	var aelm = document.createElement("a");
	var uelm = document.createElement("b"); 
	aelm.appendChild( uelm );

	var telm = document.createTextNode(boldText);
	aelm.appendChild( telm );

	item.appendChild(aelm);
       */	

    }  	
   
    var txt = document.createTextNode( stext );
    item.appendChild(txt);
     
    
  }  
  
  menu.appendChild(item);
}

function ui_make_menu_header( menu )
{
  var item = document.createElement("li");
  var cont = document.createElement("div");

  cont.style.color = 'blue';
  cont.style.fontWeight = 'bold';
  cont.style.fontSize = "10pt";
  cont.style.backgroundColor = 'white';
  
  item.appendChild(cont);

  var telm = document.createTextNode("Select one of the following suggestions");
  cont.appendChild( telm );

  menu.appendChild( item );  
}

function ui_make_default_menu(ctlid,wid)
{
   var menu = ui_ctx_menu_init( UI_menu_root, ctlid, null );
   var value = ctl_get_text(ctlid);

   ui_ctx_menu_add_item( menu, ctlid, "1000:0:a", "_Edit Word", null);
   ui_ctx_menu_add_item( menu, ctlid, "1004:" + value + ":a", "find definition of $" + value + " in google ", null );
}



function ui_make_menu( ctlid, suggestion, wid )
{
   var menu = ui_ctx_menu_init( UI_menu_root, ctlid, null );
     
   var is_merged_word = 0;
   if ( suggestion.getAttribute("errType")  == "nm" ) {
	
       is_merged_word = 1;
   }
   
  
   // iterate on each suggestion 
   var n = suggestion.firstChild;
   var suggestion_count = 0;

   while( n != null && suggestion_count < 5) {
       if (n.nodeName == "sugg") { //suggestion 
            var value = n.getAttribute("val");

	    // iterate on each description of a suggestion 
	    var s = n.firstChild;
	    var d_id = 1;
	    var desc_count = 0;
	    var smenu = ui_ctx_menu_init( menu, 0, "$" + value ); 
	    var is_first = 1;

	    //ui_make_menu_header( smenu ); 
	   
	    if (is_merged_word) {
	      ui_ctx_menu_add_item( smenu, ctlid, "1005:" + d_id + ":" + value, "Select $" + value); 
	    } else {
	      ui_ctx_menu_add_item( smenu, ctlid, n.getAttribute("id") + ":" + d_id + ":" + value, "Select $" + value); 
	    }
 

	    while( s != null && desc_count < 3) {
	        if (s.nodeName == "desc") { //description 
		  var dtxt = "";

		  if (s.firstChild) {
		    dtxt = s.firstChild.nodeValue;
		  }  

	          // add separator
		  if (is_first) {
		  // ui_ctx_menu_add_item( smenu, ctlid, n.getAttribute("id") + ":" + d_id + ":" + value, "Select $" + value); 
		     ui_ctx_menu_add_item( smenu, null, null, null, null );
		  }


	  	  ui_ctx_menu_add_item( smenu, ctlid, n.getAttribute("id") + ":" + d_id + ":" + value, " " + dtxt, value); 
		  
		  d_id ++;
		  desc_count ++;
	          is_first = 0; 
		}  
	        s = s.nextSibling;

	    }
	    
	    // add separator
	    ui_ctx_menu_add_item( smenu, null, null, null, null );

            ui_ctx_menu_add_item( smenu, ctlid, "1004:" + value + ":a", "find definition of $" + value + " in google ", null );
 	    
	    suggestion_count ++;
       }
       n = n.nextSibling;
   }


   // add separator
   ui_ctx_menu_add_item( menu, null, null, null, null );
/*
   var gmenu = ui_ctx_menu_init( menu, null, "_Search word in google" );
   n = suggestion.firstChild;
   while( n != null) {
       if (n.nodeName == "sugg") {
         var value = n.getAttribute("value");

         ui_ctx_menu_add_item( gmenu, ctlid, "1004:" + value + ":a", value, null );
       }
       n = n.nextSibling;
   }     
*/
   ui_ctx_menu_add_item( menu, ctlid , "1000:0:a", "_Edit Word", null);
   ui_ctx_menu_add_item( menu, ctlid , "1001:0:a", "_Ignore suggestions", null);
   ui_ctx_menu_add_item( menu, ctlid , "1002:0:a", "_No suggestions are relevant", null); 
   
   if (UI_action_per_word[ wid ] != null) {
     ui_ctx_menu_add_item( menu, ctlid , "1003:0:a", "_Undo Selection", null);
   }
   
}




function get_correction_text()
{
  var i;
  var res = "";
  var ret_val = -1;
  var ctl;
  
  ctl = ctl_by_id("suggestion_pane").firstChild;
  i = 1;
  while(ctl) {
     
    if ( i == UI_last_selected_word) {
     ret_val = res.length;
    } 
    
    if (ctl.nodeName == "BR") {
      res += "\n";
    } else if (ctl.nodeName == "SPAN") {
      res += "\t"; 	
    } else if (ctl.nodeName == "DIV") {
      if (ctl.firstChild) {
        res += ctl.firstChild.nodeValue;
      } 
      if (ctl.id != "") {
        i+= 1;
      }	
    } else {
      res += " ";
    }	
    ctl = ctl.nextSibling;
    
  }
  /*
  for(i=1;i<request_word_id;i++) {
    if ( i == UI_last_selected_word) {
      ret_val = res.length;
    }  
    res += ctl_get_text("w_" + i) + " ";

  }
  */
  if (ret_val != -1) {
    UI_last_selected_word = ret_val;
  } 
  return res;
}

    
// when clicking on a word this handler is called, here we build the context menu. (delayed untill now)
function UI_delayed_context_menu(ev,wid)
{
  var ctlid = "w_" + wid;
  var ctl = ctl_by_id( ctlid );
  

  if (!ev) {
    ev = window.event;
  }

  if (typeof ctl.__is_ghotit_marked  != "undefined" && ctl.__is_ghotit_marked  == 1) {
 
    ctl.__is_ghotit_marked  = 2;    
    
    var rootm = ui_ctx_root_menu_init(ctlid);
    
    if (typeof UI_xml_per_word[ ctlid ] != "undefined") {
       // menu with suggestions
       ui_make_menu( ctlid, UI_xml_per_word[ ctlid ], wid );
 
    } else {
       // default menu
       ui_make_default_menu(ctlid, wid); 
    }
    UI_menu_root = null;

    ctl.old_context_menu = ctl.oncontextmenu;

    UI_xml_per_word[ ctlid ] = DynarchMenu.setup(rootm, 
			{ context: true , 
			  onCloseDown: on_close_ctx_menu, 
			  onPopup: ui_before_ctx_menu,
			  onMouseOver: ui_on_mouse_over
			});
    ctl.className = 'dynarch-menu-ctxbutton-both'; 
    
    var sub_menu = UI_xml_per_word[ ctlid ].items[ "menu_" + ctlid ]; 
	 
    	 
    DynarchMenu.setupContext( ctl, sub_menu  ); 
    
    //DynarchMenu._stopEvent( ev );
    
    ctl.oncontextmenu(ev);
    return 1;
  }  

  return false;
}


// handle xml response - argument: spelling suggestions xml
function ui_on_spell_check_results( xml_doc )
{    
//profile_T3 = new Date().getTime();

    var root = xml_doc.documentElement;


    if (root.nodeName == "spellCheckSuggestions" ) {

     // set content of suggestion pane content 
     if (!UI_page_state) {
       ctl_set_visible("content", 0);
       
       // set content of spell check suggestion pane
       var cc = ctl_by_id("suggestion_pane");  
       var pp = ctl_by_id("editor_container");
       pp.replaceChild( UI_root_elm, cc );
 
     }

 
     clear_suggestions(0);

     // highligh spelling suggestions
     var n = root.firstChild;
     UI_suggestion_count = 0;
     while( n != null) {
       if (n.nodeName == "wd") { // word
          
	  var sstyle = n.getAttribute("errType"); //errorType 
	  var wid =  n.getAttribute("id"); 
          var ctlid = "w_" + wid;
          var ctl = ctl_by_id( ctlid );

	  if (sstyle == "nm") {
	     //ctl.style.textDecoraration = 'underline';
	     ctl.style.borderBottom='medium solid red';
	     
	     var next_id  = parseInt(wid) + 1;  
             var next_word = ctl_by_id( "w_" + next_id );
	     if (next_word != null) {
		//next_word.style.textDecoration = 'underline';
	        next_word.style.borderBottom='medium solid red';
	        set_menu(next_word,wid);
	     }	  
       
	  }  
          if (sstyle == "m")  { //misspelled 
            ctl.style.color = UI_mark_misspelled_words_color;
	    ctl.style.fontWeight = 'bold'; 
	  }  
	  if (sstyle == "c") { //confused 
	    ctl.style.color = UI_mark_confused_words_color;
	    ctl.style.fontWeight = 'bold'; 
	  } 
	  
	  UI_xml_per_word[ ctlid ] = n;
          UI_action_per_word[ wid ]  = new UI_Menu_Action( 5, wid, null ); 
	  
          ctl.__is_ghotit_marked = 1; 
          UI_suggestion_count += 1; 
       }
       n = n.nextSibling;
     }

     // page is now in correcting spelling mistake state.
     UI_init_state(1)
  }

   if (root.nodeName == "errors") {
     ui_status_show_error( root.text );	
   }

   //profile_T4 = new Date().getTime();
   //alert("parse " + (profile_T2 -profile_T1) + " net " + (profile_T3-profile_T2) + " build " + (profile_T4 - profile_T3));

}

function clear_suggestions(no_reuse)
{
     // if repeated spell checking then clear the current spelling suggestions.
     if (UI_page_state) {
        var i;

	for(i=1;i<request_word_id;i++) {
	    var ctlid = "w_" + i;
            var ctl = ctl_by_id( ctlid );

	    if (typeof ctl.__is_ghotit_marked!="undefined" && ctl.__is_ghotit_marked ) {
	        ctl.style.color = UI_edit_text_color; 
	        ctl.style.fontWeight = ''; 
		
	      //ctl.onclick = null;
	      //ctl.oncontextmenu = null; 	
	      //ctl.onmousedown = null; 


		if (ctl.__is_ghotit_marked == 2) { 
		  UI_xml_per_word[ ctlid ].destroy( );

		
		  if (no_reuse) {
		    ctl.old_context_menu = null; 
		  } else {
		    //!!!
		    ctl.onclick = ctl.oncontextmenu =  ctl.old_context_menu;
		    ctl.old_context_menu = 0;  
		  }  
		}  
	    	ctl.__is_ghotit_marked = 0; 
		UI_xml_per_word[ ctlid ] = null; 

	    }	
	    if (ctl.style.textDecoration != "none") { //== "underline") { 
	       ctl.style.textDecoration = "none"; 
	    }
	    ctl.style.borderBottom = "none";
	}
     }
     UI_action_per_word = null;
     UI_xml_per_word = null;
     
     UI_action_per_word = [];
     UI_xml_per_word = [];
}     



function ui_status_show_message_ok(stext)
{
  ctl_set_text("status_pane",' ' + stext);
  ctl_by_id("status_pane").style.borderColor = "#eee";
  ctl_by_id("status_pane").style.color = "black";    

  VOICE_ui_speak( stext );    
}


function ui_status_show_message(stext)
{
  ctl_set_text("status_pane",' ' + stext);
  ctl_by_id("status_pane").style.borderColor = "#eee";
  ctl_by_id("status_pane").style.color = "black";    

  VOICE_ui_speak( stext );    

}


function ui_status_show_error(stext)
{
  ctl_set_enabled("content",1); 
  ctl_set_text("status_pane"," Error: " + stext); 
  ctl_by_id("status_pane").style.borderColor = "red";
  ctl_by_id("status_pane").style.color = "red";

  VOICE_ui_speak( stext );    
}

function get_user_choices()
{
   emit_init(1,1);
    
   for(var key in UI_action_per_word) {
      // add entry

      var obj = UI_action_per_word[ key ];
      emit_user_choice(obj.action,obj.wid,obj.sid);
   }
   
   emit_init(1,0);

   return request_text; 
 

}

// command handler - check spelling of text.
function ui_check_spelling()
{
   var f_err = function(ncode) {
     ui_status_show_error("the server is not responding, please try later. (" + ncode + ")" );   
   }

   var f_ok = function( xml_doc ) {
     ui_on_spell_check_results( xml_doc );
   }
   
   // if in edit mode
   if (UI_page_state == 0) {
       
//profile_T1 = new Date().getTime();
	
       // parse text in build request xml.	    
       var req = parse_text( ctl_by_id("content").value );
      
       UI_last_selected_word = 0; 
 
//profile_T2 = new Date().getTime();

       // send http request (xml built in parse_text) to server.	
       // on success: response handled by ui_on_spell_check_results.
       if (send_xml_ajax_post_requext( "/ghotit/cgi/wizbridge" /*?user_id" + UI_user_id*/, req, f_ok, f_err )) {
	  ctl_set_enabled("edit_ctl",0); 
       }
  }

  // if in correction mode
  if (UI_page_state == 1) {
	var req = get_user_choices();

        if (send_xml_ajax_post_requext( "/ghotit/cgi/wizbridge" /*?user_id" + UI_user_id*/, req, f_ok, f_err )) {
	    
        }
  }
}

var UI_to_many_text = 0; 

function on_text_change()
{
  var ctl = ctl_by_id('content');  
  
  var txt = ctl.value; 
  var tlength = txt.length;
 
  if (tlength >= UI_text_length_limit) {
    ctl_set_text( "text_length", 0 );  

    ui_status_show_error("please remove some text");
    UI_to_many_text = 1;
    ctl.value = ctl.value.substring( 0, UI_text_length_limit ); 
  }  else {
    var rem = UI_text_length_limit - tlength; 
    ctl_set_text( "text_length",  rem );  
   
    if (UI_to_many_text) {
     ui_status_show_message(""); 
     UI_to_many_text = 0; 
    }
  }
  
}


// utility functions for dealing with DOM/CSS.

function ctl_by_id(sid)
{
  return document.getElementById(sid);
}

function ctl_is_visible(sid)
{  
  return ctl_by_id( sid ).style.display != "none";
}

function ctl_set_visible(sid,status)
{
  if (status) {
     ctl_by_id( sid ).style.display = "block";
  } else {
     ctl_by_id( sid ).style.display = "none";
  }
}

function ctl_set_enabled(sid,status)
{
  if (status) {
     ctl_by_id( sid ).disabled = false;
  } else {
     ctl_by_id( sid ).style.display = true;
  }
}     
 

function ctl_get_text(sid)
{
  var ctl = ctl_by_id( sid );   
  if (ctl.firstChild) {
    return ctl.firstChild.nodeValue;
  }
  return "";
}
function ctl_set_text(sid,stext)
{
  var ctl = ctl_by_id( sid );   
  var txt = document.createTextNode( stext );
  if (ctl.firstChild) {
    ctl.replaceChild( txt, ctl.firstChild );
  } else {
    ctl.appendChild( txt );
  }   
}


function ctl_set_sel( sid, start, end)
{
 ctl_debug_output("set_sel " + sid + ' ' + start + ' ' + end); 
  var ctl = ctl_by_id(sid);
  if (ctl.setSelectionRange) {
    ctl.focus();
    ctl.setSelectionRange( start, end );
  }
  if (ctl.createTextRange) {
    var r = ctl.createTextRange();
    r.collapse(true);
    r.moveEnd('character',end);
    r.moveStart('character',start);
    r.select();
  }  
}


var ctl_is_dbg_enabled = 1;
var ctl_dbg_output = null;

function ctl_debug_output( str )
{
  if (ctl_is_dbg_enabled == 0) {
      ctl_dbg_output = ctl_by_id("dbg_output");
      if (ctl_dbg_output != null) {
	 ctl_is_dbg_enabled = 1;
      } else {
         ctl_is_dbg_enabled = 2;
      }	 
  } 
  if (ctl_is_dbg_enabled == 1) {
     ctl_set_text( "dbg_output", "> " + str + ' | ' + ctl_get_text( "dbg_output") );
  }   
}


function ctl_get_cursor (sid) 
{
  var ctl = ctl_by_id(sid); 

  if (typeof ctl.selectionStart != "undefined")
     return el.selectionStart;
  else if (document.selection) {
     ctl.focus();
     var sel = document.selection.createRange();
     sel.select();
     var ret = sel.move("character",-1);
     return ret;
   }
/*
  var iCaretPos = 0;

  // IE Support
  if (document.selection) {

    // Set focus on the element
    ctl.focus ();

    // To get cursor position, get empty selection range
    var oSel = document.selection.createRange ();

    // Move selection start to 0 position
    oSel.moveStart ('character', -ctl.value.length);

	// The caret position is selection length
    iCaretPos = oSel.text.length;
  }

  // Firefox support
  else if (oField.selectionStart || oField.selectionStart == '0') {
    iCaretPos = ctl.selectionStart;
  }

    // Return results
  return iCaretPos;
*/  
}

