For the german challenged: This is an email I sent someone explaining
some concepts of AleVT.  Don't use the quoted C sources.  They wont work.
Look at t1.c instead.

Da die Mail so lang geworden ist und einige Konzepte von AleVT erlaeutert
die auch fuer andere interessant sein koennten, pack ich es einfach mal
mit ins Archiv.  Das dazugehoerige Programm ist in t1.c

-------------------------------------------------------------------------------

Date: Thu, 17 Dec 1998 23:33:49 +0100
From: Edgar Toernig <froese@gmx.de>
To: egon@pr-kaapke2.do.eunet.de
Subject: Re: alevt

Hi,

>...
> Einzelne Seiten tuen es auch. Ich bastele gerade daran.
>
> Ich habe folgendes "miniprogramm (vtx-get) geschrieben":
> -----------------------8<-------------------------------
> void main() {
>   struct vbi *vbi;
>   struct vt_page *vtp;
>   fdset_init(fds);                              // Warum brauche ich das?
>   vbi = vbi_open("/dev/vbi");
>   while( vbi_query_page(vbi,  100, ANY_SUB) == -1 ) {
>         // wie komme ich jetzt an die Seiten ran ????
>   }
>   vtp = cache_get(vbi->cache, 100, ANY_SUB);
>   printf("Page: %i \n",vtp->pgno);
>   // jetzt die Seite rausschreiben (nach stdout) [kein Problem denke ich]
>   vbi_close(vbi);
>   exit(0);
> }
> -----------------------8<-------------------------------
> Es laeuft nicht :-) D.h. es liest keine Seiten. Kannst Du mir vieleicht einen
> Tipp geben ?

Ganz so einfach ist es nicht *g*.  Ein paar Erlaeuterungen voraus:
AleVT kann gleichzeitig mehrere /dev/vbi bedienen, Fenster auf mehreren
X-Servern oeffnen usw.  Das bedeutet, das Programm muss auf Ereignisse
von mehreren Quellen reagieren.  Weiterhin sind fast alle Ereignisse
asynchron.  Aus diesem Grunde gibt es eine zentrale Stelle, die
auf ein neues Ereignis wartet und dann entsprechende callback Funktionen
aufruft.

Die zentrale Stelle ist in fdset.c.  Mit fdset_add_fd() kann man
Ereignis generierende file descriptoren (fd) registrieren lassen.
fdset_select() ist die zentrale Routine, die auf Ereignisse auf
den bisher registrierten fd wartet und dann die dazugehoerigen
callback Funktionen aufruft.

Beispiel vbi.c:  vbi_open() oeffnet das /dev/vbi und macht nen paar
Initialisierungen.  Wenn soweit alles ok ist, folgt dann der Aufruf
von fdset_add_fd(fds, vbi->fd, vbi_handler, vbi).  Das Bedeutet, dass
immer, wenn sich auf vbi->fd was tut, vbi_handler() aufgerufen werden
soll.  Dieser holt dann die Daten von /dev/vbi (via read()) und
dekodiert sie via vbi_line().  vbi_line macht dann alles moegliche und
verschickt dann, je nachdem was in der Zeile drin war, events an die
durch vbi_add_handler() registrierten Module.  Hoert sich alles
sehr kompliziert an, hat aber seinen Sinn *g*

Zu vbi_query_page(): Ich hatte bei dem Design von AleVT immer im Kopf,
dass sowohl unterschiedliche Anzeige als auch Input Geraete implementiert
werden koennen/sollen.  So sollte der High-Level (ui.c) nichts ueber
das Konzept des VideoText liefernden SubSystems wissen.  So liefern
z.B. Karten mit Hardware VideoText Decodern nicht laufend Seiten, sondern
diese muessen angefordert werden und kommen dann irgendwann spaeter
(aehnlich wie beim normalen Fernseher).  Oder die Daten kommen per
Broadcast uebers Netzwerk.  Weiterhin ist dem High-Level auch nichts
von dem Page-Cache bekannt (mit einer aergerlichen Ausnahme beim Suchen).

vbi_query_page teilt deswegen dem VT-subsystem nur mit, dass man gerne
die Seite x haben moechte.  Das Resultat ist, dass irgendwann der
eventhandler (vtwin_event) mit einem entsprechenden EV_PAGE event
aufgerufen wird.  In der Implementation von vbi_query_page sieht das
so aus, dass kurz in den Cache geschaut wird ob die Seite drin ist.
Ist das der Fall, wird sofort (von vbi_query_page aus) ein EV_PAGE
verschickt.  (Dass vbi_query_page evtl eine Referenz auf den Cache
zurueckliefert, sollte ignoriert werden.)  Ist die angefragte Seite
nicht im Cache, brauch ich im Falle des /dev/vbi nichts zu machen,
da sowieso alle Seiten Empfangen und per Broadcast an alle Clients
verschickt werden.

Puh, hab ich geschwafelt *g*.  Ich hab dir mal ein kleines Beispiel
angehaengt.  Hmm, vielleicht sollte ich diese Mail noch gleich mit
ins contrib-dir packen.

Viel Spass beim Hacken, ET.
