## # GILD: Gopher in LDPL include "ldpl_socket/ldpl_socket.ldpl" include "compat43.ldpl" extension "gild.cpp" DATA: # externals defined in gild.cpp window.rows is external number window.cols is external number gopher.url is text gopher.host is text gopher.port is number gopher.selector is text gopher.response is text gopher.socket is number # page navigation gopher.links is text map gopher.history is text map gopher.hp is number # history pointer gopher.parse-link-input is text gopher.overflow is number gopher.link-num is number gopher.type is text gopher.status is text # arg argc is number # generic locals index is number input is text lines is number line is text char is text i is number len is number buf is text out is text tabs is number parts is text list # dictionaries colormap is text map linktypes is number map help-cmd is number map # cache cache is text map cache.key is text PROCEDURE: store "\e[32m" in colormap:"0" # file store "\e[34m" in colormap:"1" # dir store "\e[33m" in colormap:"i" # info store "\e[31m" in colormap:"3" # err store "\e[37m" in colormap:"7" # search store "\e[36m" in colormap:"h" # html store "\e[37m" in colormap:0 # nada store "\e[35m" in colormap:"L" # link store 1 in linktypes:"0" # file store 1 in linktypes:"1" # dir store 1 in linktypes:"7" # search store 1 in help-cmd:"h" store 1 in help-cmd:"help" store 1 in help-cmd:"?" store 1 in help-cmd:"#" store "1" in gopher.type # gets gopher response sub-procedure gopher-get LOCAL DATA: res is text PROCEDURE: in cache.key join gopher.host ":" gopher.port gopher.selector store cache:cache.key in gopher.response if gopher.response is not equal to "" then return end if store "" in gopher.response join gopher.selector and crlf in gopher.selector socket connect to gopher.host at gopher.port in gopher.socket call gopher-check-for-errors socket send gopher.selector to gopher.socket call gopher-check-for-errors socket read from gopher.socket in res call gopher-check-for-errors while res is not equal to "" do in gopher.response join gopher.response res socket read from gopher.socket in res call gopher-check-for-errors repeat store gopher.response in cache:cache.key end sub-procedure # prints the content of gopher.response to the screen sub-procedure gopher-print display "\e[2J\e[H" # clear screen store 0 in index store "" in char store "" in line store "" in buf store "" in out store 0 in lines store gopher.overflow in index # regular file if gopher.type is equal to "0" then get char or empty at index from gopher.response in char while char is not equal to "" do if lines is greater than window.rows then store index in gopher.overflow break end if if char is equal to "\n" then add 1 and lines in lines end if in out join out char add 1 and index in index get char or empty at index from gopher.response in char repeat display out crlf return end if get char or empty at index from gopher.response in char while char is not equal to "" do if lines is greater than or equal to window.rows then store index in gopher.overflow break end if if char is equal to "\r" then add 1 and index in index get char or empty at index from gopher.response in char end if if char is equal to "\n" then add 1 and lines in lines get char or empty at 0 from line in char if linktypes:char is equal to 1 then in out join out colormap:"L" " " add 1 and gopher.link-num in gopher.link-num if gopher.link-num is less than 10 then in out join out " " gopher.link-num else in out join out gopher.link-num end if in out join out ". " store line in gopher.links:gopher.link-num else in out join out " " end if store colormap:char in char if char is equal to "" then store colormap:0 in char end if in out join out char store 1 in i get length of line in len store "" in buf while i is less than len do get char or empty at i from line in char if char is equal to "\t" then break end if join buf and char in buf add 1 and i in i repeat in out join out buf crlf store "" in line else join line and char in line end if add 1 and index in index get char or empty at index from gopher.response in char repeat display out end sub-procedure # parses a single line from a gopher.response into the gopher.host # gopher.port and gopher.selector variables. # also adds the parsed link to the history. sub-procedure gopher-parse-link store 1 in i store 0 in tabs store "" in buf get length of gopher.parse-link-input in len if gopher.parse-link-input is not equal to gopher.history:gopher.hp then add 1 and gopher.hp in gopher.hp store gopher.parse-link-input in gopher.history:gopher.hp end if get char or empty at 0 from gopher.parse-link-input in gopher.type while i is less than len do get char or empty at i from gopher.parse-link-input in char add 1 and i in i if char is equal to "\t" then add 1 and tabs in tabs if tabs is equal to 2 then store buf in gopher.selector end if if tabs is equal to 3 then store buf in gopher.host end if store "" in buf else join buf and char in buf end if repeat store buf in gopher.port end sub-procedure # prompts the user for navigation. # uses gopher.links and gopher.history for navigation sub-procedure gopher-prompt display "\e[36;1m[\e[37m" if gopher.status is equal to "" then if gopher.link-num is greater than 0 then display "# to open, " end if if gopher.hp is greater than 1 then display "0 to go back, " end if if lines is greater than or equal to window.rows then display "SPACE for more, - to go up, " else if gopher.overflow is greater than 0 then display "- to go up, " end if display "Ctrl-C to quit" else display "\e[31m" display gopher.status store "" in gopher.status end if display "\e[36m]: \e[0m" accept input if input is equal to "q" then # quit exit end if if help-cmd:input is equal to 1 then # explain store "Navigate using the numbers next to links" in gopher.status end if if input is equal to "0" then # back in history store 0 in gopher.link-num store 0 in gopher.overflow if gopher.hp is less than or equal to 1 then return end if subtract 1 from gopher.hp in gopher.hp store gopher.history:gopher.hp in gopher.parse-link-input call sub-procedure gopher-parse-link return end if if input is equal to "-" then # pageup end if if input is equal to " " then # pagedown if lines is greater than or equal to window.rows then return end if end if store 0 in gopher.link-num store 0 in gopher.overflow store input in i # convert to number if i is greater than 0 then store gopher.links:i in gopher.parse-link-input call sub-procedure gopher-parse-link end if # search prompt store input in i # convert to number get char or empty at 0 from gopher.links:i in char if char is equal to "7" then display "Search: " accept input in gopher.selector join gopher.selector "\t" input end if end sub-procedure # prints error and exits, if one occurred sub-procedure gopher-check-for-errors if ErrorCode is less than 0 then display "ERR: " ErrorText crlf exit end if end sub # remove leading /1/ or /0/ from gopher selector. we don't support it. sub-procedure gopher-clean-selector substring gopher.selector from 0 length 2 in buf get length of gopher.selector in len if buf is equal to "/1" or buf is equal to "/0" then substring gopher.selector from 2 length len in gopher.selector end if end sub # splits gopher.url into gopher.host, gopher.port, gopher.selector sub-procedure gopher-split-url-into-parts # strip leading "gopher://" from URLs substring gopher.url from 0 length 9 in buf if buf is equal to "gopher://" then get length of gopher.url in len substring gopher.url from 9 length len in gopher.url end if get index of "/" from gopher.url in i if i is greater than -1 then get length of gopher.url in len substring gopher.url from 0 length i in gopher.host substring gopher.url from i length len in gopher.selector else store gopher.url in gopher.host end if get index of ":" from gopher.host in i if i is greater than -1 then split gopher.host by ":" in parts store parts:0 in gopher.host store parts:1 in gopher.port else store 70 in gopher.port end if end sub-procedure sub-procedure print-usage display "Usage: gild [gopher-url]" crlf exit end sub-procedure # MAIN: get length of argv in argc if argc is equal to 0 then call print-usage end if if argc is greater than 0 and argv:0 is equal to "-h" then call print-usage end if if argc is greater than 0 and argv:0 is equal to "--help" then call print-usage end if if argc is equal to 1 then store argv:0 in gopher.url call gopher-split-url-into-parts else if argc is greater than 0 then store argv:0 in gopher.host end if if argc is greater than 1 then store argv:1 in gopher.port end if if argc is greater than 2 then store argv:2 in gopher.selector end if if gopher.port is equal to 0 then store 70 in gopher.port end if # strip leading /1 or /0 from selector. we don't support it yet. call gopher-clean-selector # store initial site in history add 1 and gopher.hp in gopher.hp in gopher.history:gopher.hp join "1null\t" gopher.selector "\t" gopher.host "\t" gopher.port # run loop call external gopher-init while 1 is greater than 0 do call sub-procedure gopher-get call sub-procedure gopher-print call sub-procedure gopher-prompt repeat