// Railfence encoding

// This code was written by Tyler Akins and placed in the public domain.
// It would be nice if you left this header intact.  http://rumkin.com


// Railfence
// encdec = -1 for decode, 1 for encode
// text = the text to encode/decode
// rails = The number of rails in the fence ( >= 1 and <= text.length )
// offset = Starting position (from 0 to rails * 2 - 2)
function Railfence(encdec, text, rails, offset)
{
   rails = rails * 1;
   
   if (rails < 2)
      return "You must have at least 2 rails.  I suggest 3 or more.";
   if (rails >= text.length)
      return "You need less rails or more text.";
      
   offset = offset * 1;
   while (offset < 0)
   {
      offset += rails * 2 - 2;
   }
   offset = offset % (rails * 2 - 2);
   
   if (encdec * 1 < 0)
   {
      return rail_decode(text, rails, offset * 1);
   }
   return rail_encode(text, rails, offset * 1);
}


function rail_encode(t, r, o)
{
   var o_idx = new Array(r * 2 - 2);
   var out_a = new Array(r);
   var i, j;
   
   for (i = 0; i < r; i ++)
   {
      o_idx[i] = i;
      out_a[i] = ""
   }
   for (j = 0; j < r - 2; j ++)
   {
      o_idx[i + j] = i - (j + 2);
   }
   
   for (i = 0; i < t.length; i ++)
   {
      out_a[o_idx[o]] += t.charAt(i);
      o = (o + 1) % o_idx.length
   }
   
   j = "";
   for (i = 0; i < r; i ++)
   {
      j += out_a[i];
   }
   
   return j;
}


function rail_decode(t, r, o)
{
   var o_idx = new Array((r - 1) * 2);
   var out_a = new Array(r);
   var i, j, k;

   for (i = 0; i < o_idx.length; i ++)
   {
      j = (o + i) % o_idx.length;
      if (j < r)
      {
         o_idx[i] = j;
      }
      else
      {
         o_idx[i] = (2 * (r - 1)) - j;
      }
   }
   
   for (i = 0; i < out_a.length; i ++)
   {
      out_a[i] = 0;
   }
   
   for (i = 0; i < t.length; i ++)
   {
      out_a[o_idx[i % o_idx.length]] ++;
   }
   
   j = 0;
   for (i = 0; i < out_a.length; i ++)
   {
      out_a[i] = t.slice(j, j + out_a[i]);
      j += out_a[i].length;
   }
   
   j = "";
   for (i = 0; i < t.length; i ++)
   {
      k = o_idx[i % o_idx.length];
      j += out_a[k].charAt(0);
      out_a[k] = out_a[k].slice(1, out_a[k].length);
   }
   
   return j;
}

document.Railfence_Loaded = 1;


function start_update()
{
   if (! document.getElementById)
   {
      alert('Sorry, you need a newer browser.');
      return;
   }

   if ((! document.Railfence_Loaded) || (! document.Util_Loaded) ||
       (! document.getElementById('output')))
   {
      window.setTimeout('start_update()', 100);
      return;
   }
   upd();
}


function upd()
{
   var e, r;

   if (IsUnchanged(document.encoder.text) *
       IsUnchanged(document.encoder.encdec) *
       IsUnchanged(document.encoder.rails) *
       IsUnchanged(document.encoder.offset))
   {
      window.setTimeout('upd()', 100);
      return;
   }

   ResizeTextArea(document.encoder.text);

   if (document.encoder.text.value== '')
   {
      e = document.getElementById('output');
      e.innerHTML = 'Enter a message and see the results here!';
      e = document.getElementById('rails');
      e.innerHTML = 'There is no message to show.';
      setTimeout('upd()', 100);
      return;
   }

   r = Railfence(document.encoder.encdec.value * 1, 
      document.encoder.text.value, document.encoder.rails.value * 1, 
      document.encoder.offset.value * 1);
   
   e = document.getElementById('output');
   e.innerHTML = HTMLEscape(r);
   
   e = document.getElementById('rails');
   if (document.encoder.encdec.value * 1 > 0)
   {
      e.innerHTML = FormatRails(document.encoder.text.value, 
         document.encoder.rails.value * 1, document.encoder.offset.value * 1);
   }
   else
   {
      e.innerHTML = FormatRails(r, document.encoder.rails.value * 1, 
         document.encoder.offset.value * 1);
   }
   
   window.setTimeout('upd()', 100);
}


function FormatRails(text, rails, offset)
{
   var o = new Array(rails), off = new Array(2 * (rails - 1));
   var i, j, off, pos;
   
   for (i = 0; i < rails; i ++)
   {
      o[i] = "";
      off[i] = i;
   }
   
   for (i = rails; i < 2 * (rails - 1); i ++)
   {
      off[i] = (2 * (rails - 1)) - i;
   }
   
   pos = offset % (2 * (rails - 1));
   
   for (i = 0; i < text.length; i ++)
   {
      for (j = 0; j < rails; j ++)
      {
         if (off[pos] == j)
	 {
	    o[j] += text.charAt(i);
	 }
	 else
	 {
	    o[j] += '&nbsp;';
	 }
      }
      pos = (pos + 1) % (2 * (rails - 1));
   }
   
   
   j = "";
   for (i = 0; i < rails; i ++)
   {
      if (i)
      {
         j += "<br>\n";
      }
      j += o[i];
   }
   
   return '<tt><b>' + j + '</b></tt>';
}

toggle = 0;
function ToggleRails()
{
   var Link, Vis;
   
   if (toggle == 0)
   {
      toggle = 1;
      Link = "Hide the rails";
      Vis = "block";
   }
   else
   {
      toggle = 0;
      Link = "Show the rails";
      Vis = "none";
   }
   
   e = document.getElementById('rails_link');
   e.innerHTML = Link;
   
   e = document.getElementById('rails');
   e.style.display = Vis;
}

window.setTimeout('start_update()', 100);
      

