home *** CD-ROM | disk | FTP | other *** search
- UNIT jobs; {$project vt }
- { Job-Verwaltung zum Programm VideoText }
-
- INTERFACE; FROM vt USES datei;
-
- VAR editor: str80;
- toplevel: Integer;
- active: Byte; { aktive Jobs in der Seitensuche }
- maxwait, burst,shuffle: Integer;
-
- PROCEDURE uhrzeit(VAR zeit: zeiteintrag);
- FUNCTION diff_time(alt, neu: zeiteintrag): Long;
- PROCEDURE sleep;
- PROCEDURE wakeup;
- PROCEDURE kill_queue;
- PROCEDURE handle_queue;
- PROCEDURE handle_jobs;
- PROCEDURE attempt_input(job: Integer);
- PROCEDURE pgstr2numbers(s: str80; VAR pg, sp: Integer);
- PROCEDURE add_job(entry: str80; blind: Boolean);
- PROCEDURE kill_job(nr: Integer);
- PROCEDURE cancel_job(page: Integer);
- PROCEDURE hurricane;
- FUNCTION do_retry: Integer;
- PROCEDURE page_grabber(mode: Byte);
- PROCEDURE topgrab(pg0: p_onepage);
- PROCEDURE getconfig(nr: Integer);
- FUNCTION ed_config(hint: p_onepage): Boolean;
- FUNCTION ed_stations: Boolean;
- PROCEDURE dump_numbers;
- PROCEDURE dump_title(seite: p_onepage);
-
- { ---------------------------------------------------------------------- }
-
- IMPLEMENTATION;
-
- {$ opt q,s+,i+} { keine Laufzeitprüfungen außer Stack und Feldindizes }
-
- VAR bedtime: zeiteintrag;
- wanted: ARRAY [$100..$8FF] OF Boolean; STATIC;
-
- PROCEDURE uhrzeit{(VAR zeit: zeiteintrag)};
- BEGIN
- telltime(zeit.tage,zeit.min,zeit.tics);
- END;
-
- PROCEDURE add_time(delta: zeiteintrag; VAR zeit: zeiteintrag);
- BEGIN
- IF zeit.tics + delta.tics>=3000 THEN Inc(zeit.min);
- zeit.tics := (zeit.tics + delta.tics) MOD 3000;
- IF zeit.min + delta.min>=1440 THEN Inc(zeit.tage);
- zeit.min := (zeit.min + delta.min) MOD 1440;
- zeit.tage := zeit.tage + delta.tage;
- END;
-
- PROCEDURE sub_time(delta: zeiteintrag; VAR zeit: zeiteintrag);
- BEGIN
- IF zeit.tics - delta.tics<0 THEN Dec(zeit.min);
- zeit.tics := (zeit.tics - delta.tics + 3000) MOD 3000;
- IF zeit.min - delta.min<0 THEN Dec(zeit.tage);
- zeit.min := (zeit.min - delta.min + 1440) MOD 1440;
- zeit.tage := zeit.tage - delta.tage;
- END;
-
- FUNCTION diff_time{(alt, neu: zeiteintrag): Long};
- { liefert die Differenz zwischen zwei Zeitpunkten in Ticks (1/50-Sekunden) }
- BEGIN
- diff_time := neu.tics - alt.tics + 3000 * ( (neu.min - alt.min)
- + 1440 * (neu.tage - alt.tage) );
- END;
-
- PROCEDURE sleep;
- { wird vor Unterbrechung der Hauptschleife (z. B. durch FileRequester) }
- { aufgerufen }
- BEGIN
- uhrzeit(bedtime);
- END;
-
- PROCEDURE wakeup;
- { Verhindert in Zusammenarbeit mit sleep, daß Zeiten, während derer der }
- { VT-Decoder gar nicht abgefragt wird, zum Löschen von Jobs wegen }
- { Zeitüberschreitung führen. }
- VAR delta: zeiteintrag;
- j: Integer;
- BEGIN
- uhrzeit(delta);
- sub_time(bedtime,delta);
- FOR j := 0 TO maxactive-1 DO
- add_time(delta,activejobs[j].lastaction);
- END;
-
- PROCEDURE kill_queue;
- VAR i: Integer;
- BEGIN
- queued := 0;
- IF thisjob<0 THEN thisjob := 0;
- FOR i := 0 TO maxactive-1 DO BEGIN
- activejobs[i].pg := 0; sperren(i);
- END;
- END;
-
- PROCEDURE count_them;
- { durchzählen, wer in der Seitensuche alles bedient werden will: }
- VAR j: Integer;
- BEGIN
- active := 0;
- FOR j := 0 TO maxactive-1 DO
- IF (activejobs[j].pg>0) THEN Inc(active);
- END;
-
- PROCEDURE handle_queue;
- { Verwaltet das Aufrücken wartender Jobs. }
- { Jobs mit unbestimmter Unterseitennummer, also mit /0, /*, /., /! können }
- { aktive Jobs mit gleicher Seitennummer aus der Seitensuche verdrängen }
- VAR i,j,killer,moved: Integer;
- BEGIN
- moved := 0;
- REPEAT
- j := -1;
- IF queued>0 THEN BEGIN
- { Soll ein aktiver Job verdrängt werden? }
- IF queue[firstinq].sp<1 THEN
- FOR i := 0 TO maxactive-1 DO
- IF activejobs[i].pg=queue[firstinq].pg THEN j := i;
- { Oder ist ein Platz in der Seitensuche frei? }
- IF j<0 THEN
- FOR i := maxactive-1 DOWNTO 0 DO
- IF activejobs[i].pg=0 THEN j := i;
- END;
- IF j>=0 THEN BEGIN
- { Empfangseinheit <j> mit wartendem Job belegen }
- { Ein wartender Job besteht nur aus Seiten- und Unterseitennummer, }
- { jetzt kommen eine Menge Informationen dazu. }
- WITH activejobs[j] DO BEGIN
- pg := queue[firstinq].pg; sp := queue[firstinq].sp;
- sp_count := 0; sp_max := 0;
- holen := False; erledigt := False;
- FOR i := 0 TO maxsubpage DO sp_check[i] := False;
- uhrzeit(lastaction);
- anfordern(j,pg,0,%111);
- END;
- IF i2c_status<>0 THEN BEGIN { Oh Mann! Dummer I²C-Bus! }
- activejobs[j].pg := 0; { Kommando zurück }
- j := -1; { hier ist nichts mehr zu holen }
- END ELSE BEGIN
- { Warteschlange aufrücken: }
- Dec(queued); Inc(firstinq); IF firstinq>qlen THEN firstinq := 1;
- { Auswahlzeiger des Benutzers dem Aufrücken entsprechend nachführen: }
- IF thisjob=-1 THEN thisjob := j
- ELSE IF thisjob<0 THEN Inc(thisjob);
- IF thisjob>=0 THEN
- display_select(thisjob);
- Inc(moved);
- END;
- END;
- UNTIL j=-1;
- IF moved>0 THEN redraw_queue(-1);
- count_them;
- END;
-
- PROCEDURE requeue(i: Integer; fifo: Boolean);
- { einen aktiven Job in die Warteschlange zurückstellen }
- VAR j: Integer;
- BEGIN
- IF (queued<qlen) AND (activejobs[i].pg>0) THEN BEGIN
- IF fifo THEN BEGIN
- j := firstinq+queued; IF j>qlen THEN j := 1;
- END ELSE BEGIN
- Dec(firstinq); IF firstinq=0 THEN firstinq := qlen; j := firstinq;
- END;
- Inc(queued);
- queue[j].pg := activejobs[i].pg; queue[j].sp := activejobs[i].sp;
- END;
- activejobs[i].pg := 0; sperren(i);
- END;
-
- PROCEDURE rearrange;
- { ersten und zweiten Platz der Warteschlange vertauschen }
- VAR i, j, hilf: Integer;
- BEGIN
- IF queued>1 THEN BEGIN
- i := firstinq; j := i+1; IF j>qlen THEN j := 1;
- hilf := queue[i].pg; queue[i].pg := queue[j].pg; queue[j].pg := hilf;
- hilf := queue[i].sp; queue[i].sp := queue[j].sp; queue[j].sp := hilf;
- END;
- END;
-
- PROCEDURE rausschmeisser;
- { Prüfen, ob ein Job wegen Zeitüberschreitung gestrichen werden kann. }
- { Passend zum gelöschten Job wird anschließend eine Dummy-Seite mit }
- { teilnahmsvoller Meldung in die Liste eingereiht. }
- VAR i, j: Integer;
- jetzt: zeiteintrag;
- seite: p_onepage;
- BEGIN
- uhrzeit(jetzt);
- FOR j := 0 TO maxactive-1 DO WITH activejobs[j] DO
- IF (pg<>0) AND (diff_time(lastaction,jetzt) > 50*maxwait)
- AND (sp>-2) THEN BEGIN { aber keine "festgehaltenen" Seiten! }
- i := sp; IF i<0 THEN i := 0;
- seite := hunt_in_list(pg,i,True);
- IF seite=Nil THEN BEGIN
- New(seite);
- seite^.pg := pg; seite^.sp := i; init_page(seite);
- ins_to_list(seite); update_list(seite,1);
- END ELSE BEGIN
- seite^.pg := pg; seite^.sp := i; init_page(seite);
- END;
- write_to_page(0,2,' Seite '+hexstr(pg,3)
- +' nicht gefunden - Sorry',3,1,seite);
- write_to_page(0,3,' Suche nach '+IntStr(diff_time(lastaction,
- jetzt) DIV 50)+' Sek. abgebrochen',4,6,seite);
- write_to_page(0,5,' Nochmal anfordern: f8',3,1,seite);
- write_to_page(0,6,' oder diese Seite wegwerfen: Del',4,6,seite);
- IF thispage=seite THEN
- writepage(seite,True);
- pg := 0; sperren(j); redraw_queue(j);
- END;
- count_them;
- END;
-
- PROCEDURE handle_jobs;
- { Überprüft, ob in einem der Empfangskreise eine Seite eingetroffen ist, und }
- { wenn ja, ob sie aufgrund ihrer Unterseitennummer überhaupt eingelesen }
- { werden muß. Es wird auch entschieden, ob der Job durch die eingetroffene }
- { Seite erledigt ist. Kriterium für 'erledigt': }
- { Ein Job mit sp>0 ist erledigt, sobald die eine angeforderte Unterseite }
- { da ist. Ein Job mit sp=0 ist erst dann erledigt, wenn alle seine }
- { Unterseiten eingelesen wurden. Wann das ist, läßt sich nur raten, aber }
- { ganz gut raten. Und es gibt noch einige Sonderfälle mit sp<0 ... }
- VAR j: Integer;
- dummy: p_onepage;
- sp_decval: Integer;
- BEGIN
- rausschmeisser;
- { Schauen, ob irgendwo das Eintreffen einer Kopfzeile gemeldet wurde: }
- FOR j := 0 TO maxactive-1 DO WITH activejobs[j] DO
- IF (pg>0) AND NOT holen THEN IF seite_da(j) THEN BEGIN
- New(dummy);
- uhrzeit(lastaction);
- getpage(j,dummy,False); { *nur* Status und Seitennummer holen }
- akt_sp := dummy^.sp;
- sp_decval := get_bcd(akt_sp);
- { *** Schauen, ob die Seite eingelesen werden muß. Gründe, weswegen }
- { man eine Seite evtl. nicht haben will: }
- { 1.: Unterseite wurde bereits eingelesen. }
- { (Bei zu großen Unterseitennummern kann das nur über ein etwas }
- { armseliges Hilfskriterium festgestellt werden.) }
- IF (sp_decval<=maxsubpage) THEN holen := NOT sp_check[sp_decval]
- ELSE holen := (akt_sp>sp_max);
- { 2.: Nur eine Unterseite war angefordert, und zwar nicht diese. }
- IF sp>0 THEN holen := (akt_sp=sp);
- { Selbstnumerierende Unterseiten werden blind alle eingelesen, bis }
- { der Job erledigt ist: }
- IF sp<=-10 THEN BEGIN
- holen := True; akt_sp := make_bcd(sp_count+1);
- IF sp IN [-10,-11] THEN akt_sp := 0;
- sp_decval := get_bcd(akt_sp);
- END;
- IF holen THEN BEGIN
- { *** Unterseitenverwaltung aktualisieren: }
- Inc(sp_count);
- IF (sp_decval<=maxsubpage) THEN sp_check[sp_decval] := True;
- IF akt_sp>sp_max THEN sp_max := akt_sp;
- redraw_queue(j);
- { *** Schauen, ob magazinserielle oder -gemischte Übertragung }
- { vorliegt und danach die Wartezeit festlegen: }
- IF (dummy^.cbits AND PF_SERMAG)=0 THEN
- wartezeit := shuffle ELSE wartezeit := burst;
- END ELSE
- anfordern(j,pg,0,%111); { blöde Unterseite, Suche fortsetzen }
- { *** Prüfen, ob der Job durch die eingetroffene Seite erledigt ist. }
- { Das geht z. B. durch Unterseite 0 (= einzige Unterseite). }
- { auf keinen Fall aber durch eine Unterseite mit der bislang }
- { höchsten Nummer. }
- IF sp_check[0] THEN
- erledigt := sp_count>get_bcd(sp_max)
- ELSE IF akt_sp<sp_max THEN
- erledigt := sp_count=get_bcd(sp_max);
- { Auch möglich: die einzig geforderte Unterseite ist da. }
- IF ((sp>0) OR (sp=-1)) AND holen THEN
- erledigt := True;
- { Oder es sind genauso viele selbstnumerierende Unterseiten }
- { eingetroffen, wie angefordert waren. }
- IF (sp<-10) THEN
- erledigt := (sp_count=-sp-10);
- { überwachte Seiten sind aus kosmetischen Gründen immer "erledigt": }
- IF sp IN [-2,-3,-10] THEN
- erledigt := True;
- Dispose(dummy);
- { Evtl. noch eine Vergeltungsmaßnahme: einzelne Unterseiten- }
- { anforderung, zu der eine *falsche* Unterseite eingetroffen ist, }
- { muß eine andere vorbeilassen: }
- IF (sp>0) AND NOT holen AND (queued>0) THEN BEGIN
- requeue(j,False); rearrange; redraw_queue(-1);
- END;
- END;
- END;
-
- PROCEDURE attempt_input{(job: Integer)};
- { Das Einlesen geschieht in einem zweiten Schritt, da nach Eintreffen der }
- { Kopfzeile erst eine Weile gewartet werden muß. }
- { Evtl. wird die Seite auch gleich ausgegeben: auf dem Bildschirm, falls }
- { <thisjob> auf den zugehörigen Job zeigt oder wenn eine festgehaltene }
- { Seite aktualisiert wurde; in die Ausgabedatei, falls es eine zu }
- { protokollierende Seite war. }
- { Jobs, die nach diesem Einlesen erledigt sind, wurden bereits entsprechend }
- { gekennzeichnet und werden aus der Liste gestrichen. }
- VAR dummy,seite: p_onepage;
- jetzt: zeiteintrag;
- exciting: Boolean;
- i: Integer;
- BEGIN
- { Prüfen, ob die Wartezeit für eine einzulesende Seite um ist: }
- WITH activejobs[job] DO
- IF (pg>0) AND holen THEN BEGIN
- uhrzeit(jetzt);
- IF diff_time(lastaction,jetzt) >= wartezeit THEN BEGIN
- { Seite einlesen: }
- { Ist bereits eine alte Version dieser Seite in der Liste, die dann }
- { lediglich überschrieben werden müßte? }
- seite := hunt_in_list(pg,akt_sp,True);
- IF seite=Nil THEN BEGIN
- New(seite);
- getpage(job,seite,True);
- IF sp<=-10 THEN seite^.sp := akt_sp; { selbstnumerierende Seite! }
- add_sp_number(seite);
- IF i2c_status<>0 THEN BEGIN Dispose(seite); Exit; END;
- ins_to_list(seite);
- update_list(seite,1);
- END ELSE BEGIN
- getpage(job,seite,True);
- IF sp<=-10 THEN seite^.sp := akt_sp; { selbstnumerierende Seite! }
- add_sp_number(seite);
- IF i2c_status<>0 THEN Exit;
- IF seite<>thispage THEN update_list(seite,0);
- END;
- { bildschirmüberwachte Seiten sind interessant, wenn sie das erste }
- { Mal eintreffen oder wenn sich der Inhalt geändert hat: }
- exciting := (sp=-2) AND ((sp_count=1) OR (seite^.cbits AND PF_RENEW<>0))
- AND (seite^.cbits AND PF_STITLE=0) AND (seite^.sp=0);
- { Untertitel und Mehrfachseiten aber ausgenommen! }
- { bildschirmüberwachte Seite anzeigen: }
- IF (seite=thispage) OR exciting THEN BEGIN
- IF exciting THEN showscreen(2);
- IF seite<>thispage THEN BEGIN
- short_msg('neuer Inhalt S. '+hexstr(pg,3)+'!',0);
- writepage(seite,True);
- short_msg('bitte Leertaste drücken',0);
- END ELSE
- writepage(seite,True);
- END;
- { dateiüberwachte Seite abspeichern: }
- IF sp=-3 THEN
- IF (sp_count=1) OR (seite^.cbits AND PF_RENEW<>0) THEN BEGIN
- sleep;
- IF save_action(seite,1)<>0 THEN
- { nach fehlgeschlagenem Speichern sofort neuen Versuch: }
- sp_count := 0;
- wakeup;
- END ELSE
- short_msg('',0);
- holen := False; { beendet auch "Schonfrist" für erledigte Jobs }
- anfordern(job,pg,0,%111); { um PBLF wieder zu setzen }
- END;
- END;
- { Erledigten (und eingelesenen) Job löschen: }
- WITH activejobs[job] DO
- IF (pg>0) AND erledigt AND NOT holen THEN BEGIN
- IF (sp IN [-2,-3,-10]) THEN BEGIN { Sonderfälle: niemals erledigt }
- { nur die Zähler zurücksetzen, außer sp_count }
- sp_max := 0; erledigt := False;
- FOR i := 0 TO maxsubpage DO sp_check[i] := False;
- END ELSE BEGIN
- pg := 0; sperren(job); { löschen }
- END;
- redraw_queue(job);
- END;
- count_them;
- END;
-
- PROCEDURE pgstr2numbers{(s: str80; VAR pg, sp: Integer)};
- VAR i,j,k: Integer;
- BEGIN
- i := Pos('/',s);
- j := Pos('*',s); IF j = 0 THEN j := Pos('-',s); { zwei Varianten ;-| }
- k := Length(s);
- IF i > 0 THEN BEGIN
- pg := hexval(Copy(s,1,i-1));
- sp := hexval(Copy(s,i+1,k-i));
- IF s[i+1]='*' THEN sp := -1;
- IF s[i+1]='.' THEN sp := -2;
- IF s[i+1]='!' THEN sp := -3;
- END ELSE IF j > 0 THEN BEGIN
- pg := hexval(Copy(s,1,j-1));
- Val(Copy(s,j+1,k-j),sp,j); { "*"-Anzahl nicht als BCD! }
- sp := -10-sp;
- END ELSE BEGIN
- pg := hexval(s);
- sp := 0;
- END;
- END;
-
- PROCEDURE add_job{(entry: Str80; blind: Boolean)};
- { Eine Eingabe, die eine Seitennummer darstellt (oder auch nicht), in die }
- { Warteschlange einzureihen versuchen. }
- { Bei blind=False wird noch überprüft, ob sich vielleicht bereits ein }
- { identischer Job in der Seitensuche befindet. }
- { Anschließend zeigt <thisjob> auf die neu besetzte Stelle. }
- VAR i,j,page,subpage: Integer;
- ok: Boolean;
- BEGIN
- pgstr2numbers(entry, page, subpage);
- ok := (page>=$100) AND (page<$900);
- { evtl. weitere Einschränkung: mit bereits vorhandenen Jobs vergleichen }
- { und keinen Job zulassen, der ein Verdrängen bewirken würde }
- IF NOT blind THEN BEGIN
- FOR j := 0 TO maxactive-1 DO
- IF (activejobs[j].pg=page) AND (subpage<1) THEN ok := False;
- FOR j := 1 TO queued DO BEGIN
- i := (firstinq + j - 2) MOD qlen + 1;
- IF (queue[i].pg=page) AND (subpage<1) THEN ok := False;
- END;
- END;
- IF ok AND (queued<qlen) THEN BEGIN
- Inc(queued);
- IF fifo THEN BEGIN
- j := firstinq+queued-1; IF j>qlen THEN j := 1;
- thisjob := -queued;
- END ELSE BEGIN
- Dec(firstinq); IF firstinq=0 THEN firstinq := qlen; j := firstinq;
- thisjob := -1;
- END;
- queue[j].pg := page; queue[j].sp := subpage;
- END;
- END;
-
- PROCEDURE kill_job{(nr: Integer)};
- { einen Job löschen, <thisjob> nachführen, Bildschirm aber *nicht* }
- { aktualisieren }
- VAR j: Integer;
- BEGIN
- IF nr>=0 THEN BEGIN { aktiver Job }
- activejobs[nr].pg := 0;
- sperren(nr);
- END ELSE IF (-nr<=queued) THEN BEGIN { wartender Job }
- FOR j := -nr TO queued-1 DO
- queue[(firstinq+j-2) MOD qlen + 1] :=
- queue[(firstinq+j-1) MOD qlen + 1];
- Dec(queued);
- IF fifo AND (thisjob<=nr) THEN Inc(thisjob); { normal: thisjob=nr }
- IF -thisjob>queued THEN Inc(thisjob);
- END;
- END;
-
- PROCEDURE cancel_job{(page: Integer)};
- { Als Erleichterung gegenüber kill_job() wird nicht die Position in der }
- { Warteschlange sondern der 'Name' des Jobs angegeben. }
- VAR j: Integer;
- BEGIN
- FOR j := 0 TO maxactive-1 DO
- IF activejobs[j].pg=page THEN kill_job(j);
- FOR j := -queued TO -1 DO
- IF queue[(-j+firstinq-2) MOD qlen + 1].pg=page THEN kill_job(j);
- END;
-
- PROCEDURE hurricane;
- { Die Seiten aus der Seitensuche zurück in die Warteschlange fegen. }
- VAR j: Integer;
- BEGIN
- FOR j := 0 TO maxactive-1 DO
- requeue(j,False);
- END;
-
- FUNCTION do_retry{: Integer};
- { Nicht gefundene Seiten aus der Seitenliste entfernen und neu anfordern. }
- { Rückgabewert ist die Anzahl betroffener Seiten. }
- VAR refresh: Boolean;
- pg1, pg2: p_onepage;
- hits: Integer;
- s: String[20];
- BEGIN
- hits := 0; refresh := False;
- pg1 := root;
- WHILE pg1<>Nil DO BEGIN
- pg2 := pg1^.next;
- IF (pg1^.cbits AND PF_LOCAL<>0) AND (pg1^.pg<$900) THEN BEGIN
- Inc(hits);
- IF pg1=visblpage THEN refresh := True;
- s := hexstr(pg1^.pg,3); s := s + '/'+hexstr(pg1^.sp,1)
- add_job(s, False);
- del_from_list(pg1); update_list(pg2,-1);
- END;
- pg1 := pg2;
- END;
- redraw_queue(-1); IF refresh THEN writepage(thispage, True);
- do_retry := hits;
- END;
-
- PROCEDURE page_grabber{(mode: Byte)};
- { Rechenzeitintensive Variante der Seitensuche: alle Seiten einlesen, wie }
- { sie kommen. Mode=0: alle Seiten, mode=1: keine Pseudoseiten, mode=2: nur }
- { Seiten, die gerade in der Warteschlange stehen }
- { Prinzip des Algorithmus: }
- { Kreis 3 Kreis 2 Kreis 1 Kreis 0 (nach aufsteigender Priorität) }
- { * x x x | }
- { ===== * | === Kopfzeile * anfordern }
- { ----- | --- Folgezeile x sperren }
- { ----- | ^^^ Seite komplett }
- { ^^^^^ ===== * | }
- { ----- | Gesucht wird i. a. nach Seite }
- { ----- | "???", bei magazinparalleler }
- { ^^^^^ ===== * | Übertragung dagegen nach "X??", }
- { ----- | wobei X=1..8 für alle 4 Kreise }
- { ----- | gleich sein muß. }
- { ^^^^^ ===== | }
- { Jetzt sind die Seiten in 3, 2 und 1 stabil und komplett und können }
- { ausgelesen werden. }
- { Eine ganz naheliegende Idee wäre es, 3 und 2 bereits auszulesen, noch }
- { während man in 1 bzw. 0 auf Kopfzeilen wartet. }
- { Andererseits ist es wichtig, bereits die erste Seite, die nach der }
- { Anforderung eintrifft, im jeweiligen Kreis einzufrieren. Für alle }
- { danach eintreffenden Seiteninhalte wird der Speicher nämlich nicht mehr }
- { extra gelöscht, so daß unvollständig definierte Seiten (Schlagzeilen }
- { z. B.) mit ihren Vorgängern verschmelzen, was nicht so toll aussieht. }
- { Diese zeitoptimale Methode ist darum nur bei magazinparalleler }
- { Übertragung bedenkenlos möglich. Dort treffen aufeinanderfolgende }
- { Seiten eines Magazins nur ca. alle 0.8 sec ein, und so schnell geht das }
- { Einlesen über den I²C-Bus noch allemal (ca. 0.4 sec/Seite). }
- VAR i, j, mag, anz, neu, lastq: Integer;
- seite, dummy: p_onepage;
- timeout, parmode, redraw: Boolean;
- datei: Text;
- sender, zeile, name: str80;
- PROCEDURE waitforpg(unit: Integer);
- { max. 5 Sekunden auf das Eintreffen einer Seite warten }
- VAR t0,t: zeiteintrag;
- BEGIN
- uhrzeit(t0);
- REPEAT
- uhrzeit(t); timeout := diff_time(t0,t)>250;
- UNTIL seite_da(unit) OR timeout;
- END;
- PROCEDURE einlesen(unit: Integer);
- { neue Seite einlesen (sofern nicht schon vorhanden) und einreihen }
- VAR style: Integer;
- BEGIN
- style := 0;
- getpage(unit,dummy,False); Inc(anz);
- IF wanted[dummy^.pg] THEN BEGIN
- seite := hunt_in_list(dummy^.pg,dummy^.sp,True);
- IF seite=Nil THEN BEGIN
- New(seite); Inc(neu); style := 1;
- getpage(unit,seite,True); add_sp_number(seite);
- ins_to_list(seite); update_list(seite, 1);
- IF (mode=2) AND (dummy^.sp IN [0,1]) THEN cancel_job(dummy^.pg);
- END;
- END;
- IF unit=3 THEN short_msg('Stichprobe:',0);
- add_msg(' '+hexstr(dummy^.pg,3), style);
- END;
- BEGIN
- hurricane; redraw_queue(-1); { Seitensuche freimachen }
- { Suchfilter festlegen: }
- FOR i := $100 TO $8FF DO wanted[i] := (mode=0);
- IF mode=1 THEN
- FOR i := 100 TO 899 DO wanted[make_bcd(i)] := True;
- IF mode=2 THEN BEGIN
- anz := 0;
- FOR i := 0 TO queued-1 DO BEGIN
- j := firstinq + i; IF j>qlen THEN j := 1;
- j := queue[j].pg;
- IF (j IN [$100..$8FF]) AND NOT wanted[j] THEN BEGIN
- wanted[j] := True; Inc(anz);
- END;
- END;
- short_msg(IntStr(anz)+' gesuchte Seitennummern',0);
- END;
- New(dummy);
- anz := 0; neu := 0;
- REPEAT
- redraw := (root=Nil); lastq := queued;
- FOR i := 0 TO 2 DO sperren(i);
- anfordern(3,$100,0,%000);
- waitforpg(3); getpage(3,dummy,False);
- parmode := (dummy^.cbits AND PF_SERMAG)=0;
- IF parmode THEN BEGIN { magazinparallele Sendefolge ;-\ }
- FOR i := 3 DOWNTO -1 DO IF NOT timeout THEN BEGIN
- { indirektes Sperren von (i+1): }
- IF i>-1 THEN anfordern(i,dummy^.pg,0,%100)
- { Die Seite in (i+2) ist bereits komplett und stabil: }
- IF i<2 THEN einlesen(i+2);
- { jetzt auf die zuletzt angeforderte Seite warten: }
- IF i>-1 THEN waitforpg(i);
- END
- END ELSE BEGIN { normale, magazinserielle Sendefolge }
- FOR i := 2 DOWNTO 0 DO IF NOT timeout THEN BEGIN
- { (i+1) sperren und auf die nächste Seite warten: }
- anfordern(i,$100,0,%000); waitforpg(i);
- END;
- { alle kompletten Seiten einlesen: }
- IF NOT timeout THEN
- FOR i := 3 DOWNTO 1 DO einlesen(i);
- END;
- IF redraw AND NOT timeout THEN writepage(thispage, True);
- IF queued<lastq THEN redraw_queue(-1);
- event_scan(True);
- UNTIL newevent OR timeout;
- IF timeout THEN BEGIN
- short_msg('keine neuen Seiten - Abbruch',0);
- END;
- Dispose(dummy);
- FOR i := 0 TO 3 DO sperren(i);
- END;
-
- PROCEDURE topgrab{(pg0: p_onepage)};
- { alle laut TOP-Text verfügbaren Seiten anfordern, allerdings nur bis zu }
- { der durch <toplevel> vorgegebenen Priorität }
- CONST interleave=10;
- VAR i,j,n,level: Integer;
- pri: ARRAY[0..17] OF Char;
- BEGIN
- pri := '-KABCDEFHGJI-----';
- FOR level := 1 TO toplevel DO
- FOR i := 0 TO interleave-1 DO
- FOR j := 0 TO 799 DIV interleave DO BEGIN
- n := 100 + j*interleave + i;
- IF (n<900) THEN BEGIN
- IF Ord(pri[topcode[pg0^.chars[n-60]]])-64=level THEN
- add_job(IntStr(n),True); { nach absteigender Priorität }
- END;
- END;
- redraw_queue(-1);
- END;
-
- PROCEDURE getconfig{(nr: Integer)};
- VAR datei: Text;
- sender, zeile, name: str80;
- save_fifo: Boolean;
- t,block: Integer;
- BEGIN
- gethead(name); name2dosname(name,sender);
- name := configpath+sender;
- Reset(datei,name);
- IF IOResult<>0 THEN BEGIN
- short_msg('keine Auswahl für "'+sender+'" vorhanden',2);
- add_job('100',False);
- redraw_queue(-1);
- Exit;
- END;
- Buffer(datei,500);
- short_msg('hole ',0); IF nr>1 THEN add_msg(IntStr(nr)+'. ',0);
- add_msg('Seitenauswahl für "'+sender+'"',0);
- block := 1;
- save_fifo := fifo; fifo := True;
- WHILE NOT EoF(datei) DO BEGIN
- ReadLn(datei,zeile);
- t := Length(zeile); WHILE t>0 DO BEGIN
- IF zeile[t]=' ' THEN zeile[t] := #0; Dec(t);
- END;
- IF zeile='' THEN
- Inc(block) { Leerzeile trennt Blöcke }
- ELSE IF block=nr THEN
- add_job(zeile,True);
- END;
- Close(datei);
- fifo := save_fifo;
- redraw_queue(-1);
- END;
-
- LIBRARY DosBase: { Include-Files nein danke }
- -222 : FUNCTION Execute(D1: Str; D2,D3: Long): Boolean;
- END;
-
- FUNCTION ed_config{(hint: p_onepage): Boolean};
- { Seitenvorauswahl für den aktuellen Sender editieren }
- VAR fenster: Text;
- s,datei: Str80;
- i: Integer;
- BEGIN
- s[25] := #0;
- IF hint=Nil THEN
- gethead(s)
- ELSE FOR i := 1 TO 24 DO BEGIN
- s[i] := Chr(hint^.chars[i+7]);
- IF s[i]<' ' THEN s[i] := ' ';
- END;
- name2dosname(s,datei);
- showscreen(0);
- Reset(fenster,'CON:100/100/440/80/VT-Ausgabefenster');
- s := editor + configpath + datei;
- ed_config := Execute(s,0,FileHandle(fenster));
- Close(fenster);
- showscreen(2);
- END;
-
- FUNCTION ed_stations{: Boolean};
- { Editoraufruf für die ".stations"-Liste }
- VAR fenster: Text;
- s: Str80;
- BEGIN
- showscreen(0);
- Reset(fenster,'CON:100/100/440/80/VT-Ausgabefenster');
- s := editor + configpath + '.stations';
- ed_stations := Execute(s,0,FileHandle(fenster));
- Close(fenster);
- showscreen(2);
- END;
-
- PROCEDURE dump_numbers;
- { Seitennummern ins Clipboard schreiben, Hilfe beim Ändern der Vorauswahlen }
- VAR anz,nextnr: Integer;
- hilf: p_onepage;
- ok: Boolean;
- s: str80;
- BEGIN
- IF root=Nil THEN Exit;
- anz := 0;
- hilf := root;
- WHILE hilf<>Nil DO BEGIN
- IF hilf^.next=Nil THEN nextnr := -1 ELSE nextnr := hilf^.next^.pg;
- IF (hilf^.pg<$900) AND (hilf^.pg<>nextnr) THEN Inc(anz);
- hilf := hilf^.next;
- END;
- start_clip(4*anz);
- hilf := root;
- WHILE hilf<>Nil DO BEGIN
- IF hilf^.next=Nil THEN nextnr := -1 ELSE nextnr := hilf^.next^.pg;
- IF (hilf^.pg<$900) AND (hilf^.pg<>nextnr) THEN BEGIN
- s := hexstr(hilf^.pg,3)+#10; clip_it(s,4);
- END;
- hilf := hilf^.next;
- END;
- end_clip;
- END;
-
- PROCEDURE dump_title{(seite: p_onepage)};
- { Sendernamen ins Clipboard schreiben }
- VAR s: str80;
- i: Integer;
- BEGIN
- start_clip(24);
- IF seite=Nil THEN
- gethead(s)
- ELSE FOR i := 1 TO 24 DO BEGIN
- s[i] := Chr(seite^.chars[i+7]);
- IF s[i]<' ' THEN s[i] := ' ';
- END;
- s[25] := #0;
- clip_it(s,24);
- end_clip;
- END;
-
- BEGIN { Initialisierungen }
- editor := 'c:Ed '; { Editor für configs }
- toplevel := 4; { nur Programm- und Blockseiten }
- maxwait := 80;
- burst := 0;
- shuffle := 20;
- END.
-