// ==UserScript==
// @name Linkify text files
// @author Arve Bersvendsen 
// @namespace http://userjs.org/ 
// @version 1.4.1
// @description  Improves display of text files by making
//			http/https/ftp URLs in text documents
//			clickable.
// @ujs:category browser: enhancements
// @ujs:published 2005-10-25 21:12
// @ujs:modified 2005-10-25 22:13
// @ujs:documentation http://userjs.org/scripts/browser/enhancements/linkify-text-files 
// @ujs:download http://userjs.org/scripts/download/browser/enhancements/linkify-txt.js 
// @include *
// ==/UserScript==

/* 
 * Copyright © 2005 by Arve Bersvendsen
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */


// Enable the script if we're displaying txt, css, js, and nfo files 
if (window.location.href.match(/\.(txt|js|css|nfo)$/i) ){
  // Cannot check directly on top, since that will throw errors
  // for all inline frames living on a different server; AdSense ads
  document.addEventListener('load',function(e){

    //option - show a "reformatting" notice - set to false to disable
    var showNotice = true;
    
    // Test to see that we're actually using this 
    // on documents Opera are displaying as text
    if( (document.body) && (document.body.childNodes.length == 1) && (document.body.firstChild.nodeName == "PRE")){
      var self=this;

      this.toggleNumbers = function(){
        if (document.getElementById('ol').className ==  "not_numbered"){
          document.getElementById('ol').className = "numbered";
        } else {
          document.getElementById('ol').className = "not_numbered";
        }
      }
      
      this.highlightRow = function(){ 
        var li, lists =document.getElementsByTagName("li");
        var num = prompt("Go to line:")-1;
        if (lists[num]) {
          for (var i = 0; li = lists[i]; i++) {
            li.removeAttribute("class");
          }
          lists[num].setAttribute("class","highlight");
          window.scrollTo(0,lists[num].offsetTop);
          // force Reflow:
          document.body.className = document.body.className;
        }
      }

      String.prototype.rStrip = function(){
        var endval = "";
        var link = arguments[0];
        // try to deal with ampersands, quotes and similar in a nice fashion
        if (link.substr(-6).indexOf("&quot;") != -1) {
          endval = "&quot;"
          link = link.substring(0,link.length-6);
        } else if (link.substr(-4).indexOf("&gt;") != -1) {
          endval = "&gt;"
          link = link.substring(0,link.length-4);
        } else if (link.substr(-1).match(/[,.!?\)\']$/)) {
          endval = link.substr(-1);
          if (link.substr(-7,6).indexOf("&quot;") != -1) {
            endval = "&quot;"+endval;
            link = link.substring(0,link.length-7);
          } else if (link.substr(-5,4).indexOf("&gt;") != -1) {
            endval = "&gt;"+endval;
            link = link.substring(0,link.length-5);
          } else {
            link = link.substring(0,link.length-1);
          }
        }
      return "<a href=\""+link+"\">"+link+"</a>"+endval;
      }
      
      // get original white-space. Used for a terrible hack to prevent 
      // blank lines on copy/paste operations
      var whitespace = getComputedStyle(document.getElementsByTagName('pre')[0]).whiteSpace;
      // Append style sheet
      var style = (
         "pre,ol,li { white-space: normal;}\n"
       + "span { white-space: "+whitespace+"; color: black; }\n"
       + "span,ol,li {line-height:inherit; }\n"
       + "li { color: #999; }\n"
       + "span { color: #000; display:inline}\n"
       + "ol.not_numbered { margin: 0; padding: 0 }\n"
       + "ol.not_numbered li { display: block}\n"
       + "ol.numbered li { display: list-item}\n"
       + "li.highlight { background: #eee;}"
      );
      var s = document.createElement("style");
      var s_content = document.createTextNode(style);
      s.appendChild(s_content);
      document.documentElement.appendChild(s);
      
      // Append clickable wave
      var mode = document.createElement("a");
      mode.style="position: fixed; top: 0; right: 0; padding: 0.2em; border: solid black; border-width: 0 0 1px 1px;";
      mode.addEventListener("click",self.toggleNumbers,false);
      s_content = document.createTextNode("\u21D4");
      mode.appendChild(s_content);
      document.body.appendChild(mode);

      // Append reformatting notice
      if( showNotice ) {
        var showNotice = document.createElement("div");
        showNotice.style="position: fixed; top: 50%; left: 50%; margin: -1em 0 0 -6em; padding: 0.2em; border: 1px solid black; background-color: #ddd;";
        showNotice.appendChild(document.createTextNode('Reformatting and finding links.'));
        showNotice.appendChild(document.createElement('br'));
        showNotice.appendChild(document.createTextNode('Please wait ...'));
        document.body.appendChild(showNotice);
      }

      // Search for http/https/ftp URLs and make them clickable
      // Wrap a line around every line

      var urlRegex = /\b(((https?|ftp|irc|telnet|nntp|gopher|file):\/\/|(mailto|news|data):)[^\s\"<>\{\}\'\(\)]*)/g;
      var doc = document.getElementsByTagName('pre')[0];
      
      doc.innerHTML = "<ol id=\"ol\" class=\"not_numbered\">"+doc.innerHTML.replace(/\%0C/g,"&#13;").replace(/([^\r\n]*)(\r?\n|\r)/gi,"<li><span>$1 </span></li>").replace(urlRegex,RegExp.$1.rStrip)+"</ol>";

      if( showNotice ) { showNotice.parentNode.removeChild(showNotice); }

      // Listen to the "l" key to toggle line number visibility
      document.onkeypress=function(e){
        switch (e.keyCode) {
          case 103: 
            self.highlightRow();
            break;
          case 108:
            self.toggleNumbers();
            break;
          default:
            break;
        }
      }
    }
  },false)
}
