#!/usr/local/bin/klone
(setq max-level *maxint*)
(setq title "Colas XFree Modeline Generator")
(setq color "CCFFCC")
(catch 'Ok (dolist (path '(
	"/htdocs/cgi-bin/nph-colas-modelines-aux"
      "/net/koala/bin/sh/xfree-modelines" "/usr/local/bin/xfree-modelines"
    ))
    (if (file-stats path) (throw 'Ok (setq script-path path)))
  )
  (setq script-path "xfree-modelines")
)

;; a sample script to show modelines

(defun main (&aux
  )
  (cgi:init :error "/tmp/colas-klone-cgi-errors")

  ;; first, decide what want the user?
  (if
    (= cgi:path-info "")		;no subpart? mainpage
    (show-main-page)
    
    (= cgi:path-info "/list-all")	;list all possible modelines
    (show-modelines)

    (= cgi:path-info "/script")	; show oneself
    (show-script #[*arguments* 0])
    (= cgi:path-info "/script-standalone")	; show oneself
    (show-script script-path)
    
    (= cgi:path-info "/kill")	; show oneself
    (wait (system "echo killing...;/usr/ucb/ps -axw | grep '[m]odelines'| ( while read P R;do echo \"killing $P $R\";kill $P;done )"))

    (PF "Unknown command!\n")		;there is a ball in the soup
  )
  
  (cgi:end :validity 15)
)


(defun show-main-page ()
  (PF <HEAD><TITLE>%2</TITLE></HEAD>
<BODY BGCOLOR="%3"><H1>%2</H1>
<a href="nph-colas-modelines-fr">Version française</a>
<P>
This script will compute many possible values for the graphic modes of Xfree86,
to be put in the ModeLines section of XF86Config.

<p><b>Warning</b>: This script is based on my experience on high-end monitors
(17"-24" multisync with more than 135Mhz of bandwidth), trying to squeeze the
most refresh rate at the highest resolution, and will <b>not</b> work for
lower specs monitors (15" and lower). See these <a href=
"http://www.inria.fr/koala/colas/modelines-comments.html"> comments by Koen
Gadeyne</a> on why this script cannot be used for all purposes.
<br><b>new</b> July 1st 1998: this script implements now better heuristics

<p>Please indicate the specs of your monitor and graphic card:
<hr>
<p> First, the maximal values that you should find in your graphic card and 
monitor specs (or on the internet). Important to determine the best resolutions
and refresh rates you can get.
<form method="post" action="%0/list-all">
<table>
<tr>
  <td align="right">Max Bandwidth: </td>
  <td><input name=bw size=10 type=text></td>
  <td><small><i>default: 200</i><br>Enter here the minimum of the max bandwidth
  of your graphic card (or dot clock) and the max bandwidth of your monitor
    (in Mhz) </small></td>
</tr>
<tr>
  <td align="right">Max Vertical Frequency: </td>
  <td><input name=vf size=10 type=text></td>
  <td><small><i>default: 150</i><br>Enter here the max vertical frequency
  of your monitor (in Hz)
  </small></td>
</tr>
<tr>
  <td align="right">Max Horizontal Frequency: </td>
  <td><input name=hf size=10 type=text></td>
  <td><small><i>default: 100</i><br>Enter here the max horizontal frequency
  of your monitor (in Khz)
  </small></td>
</tr>
</table><hr>
Then how low you want to get in refresh rate. It just tell the script when to 
stop showing you resolutions.
<table>
<tr>
  <td align="right">Min Refresh rate desired: </td>
  <td><input name=rr size=10 type=text></td>
  <td><small><i>default: 70</i><br>Enter here the minimum refresh rate
    (number of images per second) you tolerate. Should be at least 72 for eye 
    confort (in Hz) according to the VESA comitee, I personnaly recommend 75 
    to 80. 90 is nice :-)
  </small></td>
</tr>
</table><hr>
Minimal values, this is not very important, it determines only the lowest
resolutions you can display, not the best ones.
<table>
<tr>
  <td align="right">Min Bandwidth: </td>
  <td><input name=mbw size=10 type=text></td>
  <td><small><i>default: 20</i><br>Enter here the maximum of the minimum 
  bandwidth of your graphic card (or dot clock) and the minimum bandwidth 
  of your monitor (in Mhz) </small></td>
</tr>
<tr>
  <td align="right">Min Horizontal Frequency: </td>
  <td><input name=mhf size=10 type=text></td>
  <td><small><i>default: 30</i><br>Enter here the min horizontal frequency
  of your monitor (in Khz)
  </small></td>
</tr>
</table><hr>
<input type=submit value="List Modelines">
<hr>
If you want a non-4x3 resolution (such as 1280x1024, but I do not recommend
it as you will either waste space or have non-square pixels, the only valid 
use could be on new 16/9 or 16/10 monitors), 
please enter also desired <b>width:</b>
<input name=X size=10 type=text> and <b>heigth:</b>
<input name=Y size=10 type=text> in pixels
<br>Leave the above field blank for a list of all 
4x3 resolutions, or enter the <b>desired screen ratio</b> here:
<input name=ratio size=10 type=text> (default "4/3", can be x/y such as 16/10, 16/9...)
<hr>
If the timings given are too tight (your monitor is black or the image is 
deformed or flickering), you may want to relax the timings by 
<input name=correction size=3 type=text><b>percent</b>. (try 10, 20, 30...) 
<hr>
Everything is done by a <a href="ftp://koala.inria.fr/pub/Klone/">Klone</a>
cgi script that can <A href="%0/script">
display itself</A>. This wrapper actually calls a standalone Klone script: 
<A href="%0/script-standalone">xfree-modelines</a>.
<br>Author: <a href="http://www.inria.fr/koala/colas">Colas Nahaboo</a>
</form>
</BODY>

    cgi:script-name			; %0
    *version*				; %1
    title				; %2
    color				; %3
  )
)

(defun show-modelines (&aux
    s (x 320) (y 240)
    (re-sm (regcomp "#[ \t]*([0-9]+)[ \t]*Hz"))
    (re-num (regcomp "^([0-9]+)$"))
  )
  (with (*arguments* (list script-path "-load"))
    (load script-path)
  )
  ;; get form values, set defaults
  (setq M-BW (Number (get cgi:arguments "bw" 200)))
  (if (> 1 M-BW) (setq M-BW 200))
  (setq M-VF (Number (get cgi:arguments "vf" 150)))
  (if (> 1 M-VF) (setq M-VF 150))
  (setq M-HF (Number (get cgi:arguments "hf" 100)))
  (if (> 1 M-HF) (setq M-HF 100))
  (setq M-RR (Number (get cgi:arguments "rr" 100)))
  (if (> 1 M-RR) (setq M-RR 70))
  (setq m-BW (Number (get cgi:arguments "mbw" 20)))
  (if (> 1 m-BW) (setq m-BW 20))
  (if (>= m-BW M-BW) (setq m-BW (- M-BW 1)))
  (setq m-HF (Number (get cgi:arguments "mhf" 30)))
  (if (> 1 m-HF) (setq m-HF 30))
  (if (>= m-HF M-HF) (setq m-HF (- M-HF 1)))
  (if (and (regexec re-num (get cgi:arguments "X" ""))
      (regexec re-num (get cgi:arguments "Y" ""))) (progn
      (setq X (Number (get cgi:arguments "X" 640)))
      (if (> 1 X) (setq x 640))
      (setq Y (Number (get cgi:arguments "Y" 480)))
      (if (> 1 Y) (setq Y 480))
    )
    (setqn X () Y ())
  )
  (setq ratio (get cgi:arguments "ratio" "4/3"))
  (setq re-ratio (regcomp "^([0-9]+)[/]([0-9]+)$"))
  (if (regexec re-ratio ratio) (progn
      (setq ratio (vector (Int (regsub re-ratio 1))(Int (regsub re-ratio 2))))
    )
    t (setq ratio [4 3])
  )
  (setq correction (Number (get cgi:arguments "correction" 0)))
  
  (PF <HEAD><TITLE>%0 results</TITLE></HEAD>
    <BODY BGCOLOR="%6"><H1>%0 results</H1>
    Computed by <a href="%5">%5</a><br>
    Max Bandwidth: <b>%1</b> Mhz<br>
    Max Vertical Frequency: <b>%2</b> Hz<br>
    Max Horizontal Frequency: <b>%3</b> Khz<br>
    Minimun Refresh Rate: <b>%4</b> Hz
    Min Bandwidth: <b>%7</b> Mhz<br>
    Min Horizontal Frequency: <b>%8</b> Khz<br>
    <p>
    ModeLine "name" dotclock width x x x heigth y y y #RefreshRate
    <hr>
    <PRE>
    title M-BW M-VF M-HF M-RR (getenv "HTTP_REFERER") color m-BW m-HF
  )
  (if (and X Y) (progn
      (setq s (copy ""))
      (with (*standard-output* (open s :type :string :direction :io))
	(process-modeline (PF String "\"%0x%1\"" X Y) X Y M-VF)
      )
      (if (and (regexec re-sm s) (>= (Number (regsub re-sm 1)) M-RR))
	(write-string s)
	(if (= "" s)
	  (PF "# RESOLUTION TOO LOW: %0 x %1" X Y) ;too low, continue
	  (PF "# RESOLUTION TOO HIGH: %0 x %1" X Y)
    )))
    
    (catch 'Done (while t
	(setq s (copy ""))
	(setq y (/ (* (getn ratio 1) x) (getn ratio 0)))
	(with (*standard-output* (open s :type :string :direction :io))
	  (process-modeline (PF String "\"%0x%1\"" x y) x y M-VF)
	)
	(if (and (regexec re-sm s) (>= (Number (regsub re-sm 1)) M-RR))
	  (write-string s)
	  (if (= "" s)
	    ()				;too low, continue
	    (throw 'Done)			;ok, end there
	))
	(incf x 8)
  )))
  (PF "</PRE><hr></BODY></HTML>")
)

(defun show-script (path)
  (PF "<HEAD><TITLE>%3 source</TITLE></HEAD>
<BODY BGCOLOR=\"%4\"><H1>%3 source</H1><P>
This is my body... Click <A HREF=\"%2\">here</a> to see my output.
<hr><pre>%0</pre><hr></body>
" 
    (html:quote-pre (String (open path))) ; %0
    *version*				; %1
    (+ "http://" (getenv "SERVER_NAME") ":" (getenv "SERVER_PORT") 
      cgi:script-name
    )					; %2
    title				; %3
    color				; %4
    "\n"				; %5
))


;;=============================================================================
;;                    error handler
;;=============================================================================

(defun print-stack-dump:pre-handler (&rest args &aux 
    (date (html:date))
    s
    (dump (open (copy "") :type :string :direction :io))
  )
  (with (print-stack-dump:output dump
      print-stack-dump:exit-after ()
      print-stack-dump:print-local-vars t
      print-stack-dump:print-all-vars t
    ) 
    (apply print-stack-dump args)
  )
  (setq cgi:out-string
    (print-format String "<HTML><TITLE>Script Error!</TITLE>
<BODY BGCOLOR=\"#FFAAAA\">
Sorry, this cgi-script crashed in error. Please mail the maintainer:
<br><b>%2</b>
<br>that an error occured in
<br><b>%0</b>
<br>on
<br><b>%1</b><hr><pre>
%3
</pre>
</BODY></HTML>\n" cgi:script-name date %maintainer (Q (String dump))))

  (cgi:end)
      
  (print-format *standard-error* "\n%2\n### ERROR in %0\n### on %1\n"
     cgi:script-name date
    "========================================================================="
  )
)

(defun print-stack-dump:post-handler () (flush ())(sh sleep 2) (exit 0) )

(main)

;;; EMACS MODES
;;; Local Variables: ***
;;; mode:lisp ***
;;; End: ***

