#!/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)

    (PF "Unknown command!\n")           ;there is a ball in the soup
  )

  (cgi:end :validity 15)
)

(defun show-main-page ()
  (PF <HTML>
<HEAD><TITLE>%2</TITLE></HEAD>
<BODY BGCOLOR="%3"><H1>%2</H1>
<a href="nph-colas-modelines">English version</a> Cette version a été traduite en Francais par <a href="http://www.linux-france.com/">Nat Makarevitch</a>
<P>
Ce programme détermine, par calcul, plusieurs lignes de ModeLines à placer
dans le fichier <em>XF86Config</em> de XFree86.

<p><b>Attention</b>: 
J'ai développé ce programme en fonction d'essais d'optimisation de la
fréquence de rafraîchissement effectués grâce à des moniteurs performants
(diagonale comprise entre 17 et 24 pouces, multisynchronisation et bande
passante supérieure à 135 MHz). 

Des <a href= "http://www.inria.fr/koala/colas/modelines-comments.html">
commentaires en anglais</a> traitent des raisons pour lesquelles tout cela
n'a guère de sens sur un moniteur moins imposant (15 pouces et moins).
<br><b>nouveau</b>: 1er Juillet 98: ce script utilise désormais de meilleurs
algorithmes.

<p>Caractéristiques techniques de votre moniteur et de votre carte graphique
<hr>
<p> Il vous faut tout d'abord déterminer les fréquences maximales tolérées
par votre carte graphique et votre moniteur. Consulter pour cela leurs
documentations techniques.
<form method="post" action="%0/list-all">
<table>
<tr>
  <td align="right">Bande passante maximum (Max Bandwidth) : </td>
  <td><input name=bw size=10 type=text></td>
  <td><small><i>par défaut : 200</i><br>Saisir ici la bande passante maximale  tolérée. Déterminer pour cela la BP de la carte graphique (parfois appelée <em>dot clock</em>) et celle du moniteur, puis saisir la plus petite valeur. Unité : le MHz.</small></td>
</tr>
<tr>
  <td align="right">Fréquence verticale maximum : </td>
  <td><input name=vf size=10 type=text></td>
  <td><small><i>par défaut : 150</i><br>Saisir ici la fréquence verticale
maximum tolérée par le moniteur. Unité : le Hz.
  </small></td>
</tr>
<tr>
  <td align="right">Fréquence horizontale maximum : </td>
  <td><input name=hf size=10 type=text></td>
  <td><small><i>par défaut : 100</i><br>Saisir ici la fréquence horizontale
maximum tolérée par le moniteur. Unité : le KHz.
  </small></td>
</tr>
</table><hr>
Préciser ici la fréquence de rafraîchissement minimale souhaitée. Le
programme ne produira pas de ModeLine correspondant à une fréquence de
rafraîchissement inférieure.
<table>
<tr>
  <td align="right">Fréquence de rafraîchissement minimale souhaitée : </td>
  <td><input name=rr size=10 type=text></td>
  <td><small><i>par défaut : 70</i><br>Cette valeur indique le nombre minimum
d'images produites par seconde. Le comité VESA préconise d'éviter les valeurs
inférieures à 72 et je recommande la plage 75-80. 90 est chouette :-)
  </small></td>
</tr>
</table><hr>
Valeurs minimales. Elles ne sont pas très importantes car permettent seulement d'engendrer les spécifications des plus basses résolutions possibles.
<table>
<tr>
  <td align="right">Bande passante minimum (Min Bandwidth) : </td>
  <td><input name=mbw size=10 type=text></td>
  <td><small><i>par défaut : 20</i><br>Saisir ici la bande passante minimale  tolérée. Déterminer pour cela la BP de la carte graphique (parfois appelée <em>dot clock</em>) et celle du moniteur, puis saisir la plus grande valeur. Unité : le MHz.</small></td>
</tr>
<tr>
  <td align="right">Min Horizontal Frequency: </td>
  <td><input name=mhf size=10 type=text></td>
  <td><small><i>par défaut : 30</i><br>Saisir ici la fréquence horizontale
minimum tolérée par le moniteur. Unité : le KHz.
  </small></td>
</tr>
</table><hr>
<input type=submit value="List Modelines">
<hr>

Cette section ne concerne que ceux qui ne souhaitent pas employer une
résolution de type 4x3, où chaque ligne compte 1/3 de pixels de plus que
chaque colonne. Cette approche n'est conseillée qu'à condition de disposer
d'un tube 16/9 ou 16/10 (car les pixels n'y apparaissent sinon pas carrés).

<br>Entrez ici 
<input name=ratio size=10 type=text>
le ratio de l'écran (normalement "4/3", mais peut être aussi 
"16/10", "16/9"...
), pour avoir la liste des modelines, ou si vous n'en voulez qu'une, remplissez plutôt les champs ci-dessous:

Saisir tout d'abord la <b>largeur (nombre de pixels/ligne) : </b>
<input name=X size=10 type=text> puis la <b>hauteur : </b>
<input name=Y size=10 type=text>
<hr>
Si les timings obtenus sont trop serrés (image noire, déformée ou tremblante),
essayez de corriger de <input name=correction size=3 type=text><b>pourcents</b>
ces timings. (essayez 10 puis 20, 30...)
<hr>

Le calcul est assuré par un script CGI rédigé en langage <a
href="ftp://koala.inria.fr/pub/Klone/">Klone</a> dont voici le
<A href="%0/script">
source</A>. Ce script invoque, lui, un programme de calcul :
<A href="%0/script-standalone">xfree-modelines</a>.
<br>Auteur : <a href="http://www.inria.fr/koala/colas">Colas Nahaboo</a>
</form>
</BODY>
</HTML>

    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 (>= m-HF M-HF) (setq m-HF (- M-HF 1)))
  (if (> 1 m-HF) (setq m-HF 30))
  (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 <HTML><HEAD><TITLE>%0 results</TITLE></HEAD>
    <BODY BGCOLOR="%6"><H1>%0 results</H1>
    Calculé par <a href="%5">%5</a><br>
    BP maximum : <b>%1</b> Mhz<br>
    Fréquence verticale maximum : <b>%2</b> Hz<br>
    Fréquence horizontale maximum: <b>%3</b> Khz<br>
    Fréquence de rafraîchissement minimale : <b>%4</b> Hz
    BP minimum : <b>%7</b> Mhz<br>
    Fréquence horizontale minimale : <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 "# RéSOLUTION TROP BASSE : %0 x %1" X Y) ;too low, continue
          (PF "# RÉSOLUTION TROP ÉLEVÉE : %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>Erreur provoquée par le script CGI</TITLE>
<BODY BGCOLOR=\"#FFAAAA\">
Ce script CGI vient d'avorter. Merci de m'en avertir grâce à un message
électronique :
<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: ***
