#!/usr/bin/env python
## Free Libraries Gopher Client (see version number in below tuple)
## Jul 2012
## License: Public Domain
## Very Very Beta

geo=(80, 24, "<-' go <- back ^ v scroll    Free Libraries Gopher Client 0.1 (Public Domain)")
import curses
from os import popen
from os import system
from sys import argv

yescurl = int(popen("which curl | wc -l").readline())
if not yescurl:
   print "This program will not work without curl."
   print
   print "Suggestion: sudo apt-get install curl (for Debian/Ubuntu/Trisquel/GNewSense)"
   print "                sudo yum install curl (for Fedora/Freedora/etc)"
   print ""
   exit()
text = ""

url = ""
try:
   url = argv[1]
except:
   pass
if url == "":
   print "enter the name of a gopher site:", ; url = raw_input().strip()

def c(p):
   global url
   if not "gopher://" in url.lower():
       url = "gopher://" + url
   if url.lower()[:9] != "gopher://":
       url = "gopher://" + url
   global text # for debugging output
   text = url
   history = []
   yescaca = int(popen("which cacaview | wc -l").readline())
   x = 0
   while x not in [27, ord("x"), ord("q"), ord("Q"), ord("X")]:
       yindex = 0
       yib = 0
       global geo
       thistype = "1"
       rurl = url
       if rurl[:9].lower() == "gopher://":
           rurl = rurl[9:]
       try:
           thistype = rurl.split("/")[1]
           text = thistype
       except:
           pass
       f = list(popen("curl -s \"" + url + "\" 2> /dev/null").readlines())
       history += [url]
       if len(history) > 50:
           history = history[-50:] ## conservative ; try 1000 or even remove
       for lenf in range(3):
           f = [""] + f
       if len(f) < geo[1]:
           while len(f) < geo[1]:
               f += [""]
       for lenf in range(geo[1]):
           f += [""]
       x = 0
       while x not in [27, curses.KEY_ENTER, 10, ord("x"), ord("X"), ord("q"), ord("Q")]:
           ## because curses.KEY_ENTER wasn't being trapped; LF was, go figure
           if x == curses.KEY_PPAGE:
               yindex -= (geo[1] - 1)
               if yindex < 0:
                   yindex = 0
           if x == curses.KEY_NPAGE:
               yindex += geo[1] - 1
               if yindex > len(f) - geo[1]:
                   yindex = len(f) - geo[1]
           if x == curses.KEY_UP:
               yindex -= 1
               if yindex < 0:
                   yindex = 0
           if x == curses.KEY_DOWN:
               yindex += 1
               if yindex > len(f) - geo[1]:
                   yindex = len(f) - geo[1]
           if x == curses.KEY_HOME:
               yindex = 0
           if x == curses.KEY_LEFT:
               if len(history) > 1:
                   try: ## lazy
                       history = history[:-1]
                       newurl = history[len(history) - 1]
                       history = history[:-1]
                       url = newurl
                       text = newurl
                   except:
                       pass
               else:
                   x = 126
           if x == curses.KEY_END:
               yindex = len(f) - geo[1] -1
           if yindex != yib or yib == 0:
               p.clear()
               for pp in range(0, geo[1] - 1):
                   thisline = f[pp + yindex].rstrip()
                   if thistype == "1" and len(thisline):
                       hint = ""
                       if thisline[0] == "0":
                           hint = "(TEXT) "
                       elif thisline[0] == "1":
                           hint = " (DIR) "
                       elif thisline[0] == "i":
                           hint = ""
                       elif thisline[0] == "I":
                           hint = " (IMG) "
                       if thisline[0] in "01iI":
                           thisline = hint + thisline.split("\t")[0][1:]
                   if pp == 3:
                       bar = thisline + (" " * geo[0])
                       ## for whatever reason, this doesn't exactly
                       p.addstr(pp, 0, bar[:geo[0]], curses.A_REVERSE)
                       p.addstr(pp + 1, 0, " " * geo[0])
                   else:
                       p.addstr(pp, 0, thisline[:geo[0]])
               yib = yindex
               p.refresh()
           p.addstr(geo[1] - 1, 0, " " * (geo[0] - 1), curses.A_REVERSE)
           p.addstr(geo[1] - 1, 0, " " + geo[2], curses.A_REVERSE)
           p.addstr(geo[1] - 1, geo[0] - 1, "", curses.A_REVERSE)
           p.refresh()
           spaghetti = 0
           if x != curses.KEY_LEFT:
               x = p.getch()
           else:
               spaghetti = 1 ## sorry
               x = 10
           if x == 10 or x == curses.KEY_ENTER:
               if spaghetti == 0:
                   rstr = f[yindex + 3] ## the contents of the selected line
                   typifany = ""
                   ## typifany: derived from link you're hovering over
                   ## thistype: type / page you're already viewing
                   if len(rstr) and thistype == "1":
                       ## if thistype isn't 1,  ^ parsed line doesn't count
                       ## (i.e. because you're viewing type 0)
                       typifany = rstr[0] ## get gophertype, (or " ", or "")
                   if typifany == "0":
                       if len(rstr.split("\t")) > 3:
                           typs = "/" + typifany
                           desc = rstr.split("\t")[0][1:]
                           rsel = rstr.split("\t")[1]
                           serv = rstr.split("\t")[2]
                           ## port field is often last, so remove \r\n
                           port = rstr.split("\t")[3].rstrip()
                           newurl = "gopher://" + serv + ":" + port + typs + rsel
                           url = newurl
                   elif typifany == "1":
                       if len(rstr.split("\t")) > 3:
                           typs = "/" + typifany
                           desc = rstr.split("\t")[0][1:]
                           rsel = rstr.split("\t")[1]
                           serv = rstr.split("\t")[2]
                           ## port field is often last, so remove \r\n
                           port = rstr.split("\t")[3].rstrip()
                           newurl = "gopher://" + serv + ":" + port + typs + rsel
                           url = newurl
                   elif typifany == "I":
                       if len(rstr.split("\t")) > 3:
                           typs = "/" + typifany
                           desc = rstr.split("\t")[0][1:]
                           rsel = rstr.split("\t")[1]
                           serv = rstr.split("\t")[2]
                           ## port field is often last, so remove \r\n
                           port = rstr.split("\t")[3].rstrip()
                           newurl = "gopher://" + serv + ":" + port + typs + rsel
                           system("curl -s \"" + newurl + "\" > /tmp/cacav 2> /dev/null ; cacaview /tmp/cacav 2> /dev/null")
                       else:
                           x = 126 ## pretend enter wasn't pressed
                   else:
                       x = 126 ## no plans to map this
curses.wrapper(c)