UNIT jobs; {$project vt } { Job-Verwaltung zum Programm VideoText } INTERFACE; FROM vt USES global,sys,bildschirm,datei,cct,pagelist; PROCEDURE sleep; PROCEDURE wakeup; PROCEDURE handle_queue; PROCEDURE handle_jobs; PROCEDURE attempt_input(job: Integer); PROCEDURE add_job(entry: Str80); PROCEDURE getconfig; { ---------------------------------------------------------------------- } IMPLEMENTATION; {$opt b-} CONST SUBTITLE = $0040; { C6 } SERMAG = $0800; { C11 } VAR bedtime: zeiteintrag; PROCEDURE uhrzeit(VAR zeit: zeiteintrag); BEGIN telltime(zeit.tage,zeit.min,zeit.tics); END; PROCEDURE sleep; { wird vor Unterbrechung der Hauptschleife (z. B. durch Prozedur displayhelp) } { 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 handle_queue; { Wird aus der Hauptschleife heraus aufgerufen. Verwaltet das Aufrücken } { wartender Jobs und das Entfernen überalterter Seitenanforderungen. } { Ein Job besteht zunächst aus einer Seitennummer pg und einer Unterseiten- } { nummer sp, plus zusätzlichen Informationen, sobald er aktiv ist. } VAR i, j: Integer; jetzt: zeiteintrag; BEGIN { Prüfen, ob Jobs aus der Warteschlange in die aktiven Plätze nachrücken } { können, erkennbar an 'aktiven' Jobs mit pg=0. } FOR j := 0 to maxactive-1 DO IF (activejobs[j].pg=0) AND (queued>0) THEN BEGIN { freie Empfangseinheit mit wartendem Job belegen } WITH activejobs[j] DO BEGIN pg := queue[1].pg; sp := queue[1].sp; sp_count := 0; sp_max := 0; holen := False; erledigt := False; ist_UT := 0; FOR i := 0 TO anzsubpage DO sp_check[i] := False; uhrzeit(lastaction); anfordern(j,pg,sp,'!!!'); END; { Warteschlange aufrücken: } Dec(queued); FOR i := 1 TO queued DO queue[i] := queue[i+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 BEGIN aktspeicher := thisjob; display_select(aktspeicher); END; redraw_queue(-1); END; { Prüfen, ob ein Job wegen Zeitüberschreitung gestrichen werden kann. } { Wenn der Job allerdings so lange wartet, weil er sich auf eine einzelne } { Unterseite bezieht, ist ihm verziehen und er wird lediglich ans Ende der } { Warteschlange gesetzt. Und für Jobs, die sich auf Untertitel beziehen, } { findet eine Prüfung auf Zeitüberschreitung gar nicht erst statt. } uhrzeit(jetzt); FOR j := 0 TO maxactive-1 DO WITH activejobs[j] DO IF (pg<>0) AND (diff_time(lastaction,jetzt) > 50*maxwait) AND (ist_UT=0) THEN IF activejobs[j].sp = 0 THEN BEGIN { einfache Seitennummer streichen } activejobs[j].pg := 0; sperren(j); redraw_queue(j); END ELSE { Unterseitenanforderung nur hintenanstellen } IF queued>0 THEN BEGIN IF queued0) AND NOT holen THEN IF seite_da(j) THEN BEGIN { write(#7); } New(dummy); uhrzeit(lastaction); getpage(j,dummy,false); { *nur* Status und Seitennummer holen } { *** 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 (dummy^.sp<=anzsubpage) THEN holen := NOT sp_check[dummy^.sp] ELSE holen := (dummy^.sp>sp_max); { Und für UT-Seiten ist "bereits eingelesen" überhaupt kein } { Hinderungsgrund: } IF ist_UT<>0 THEN holen := True; { 2.: Nur eine Unterseite war angefordert, und zwar nicht diese. } { Das dürfte allerdings kaum vorkommen, da der CCT ausdrücklich auf } { die eine Unterseite programmiert wurde. } IF (sp>0) THEN holen := (dummy^.sp=sp) { *** Unterseitenverwaltung aktualisieren: } IF holen THEN BEGIN Inc(sp_count); IF (dummy^.sp<=anzsubpage) THEN sp_check[dummy^.sp] := True; IF dummy^.sp>sp_max THEN sp_max := dummy^.sp; akt_sp := dummy^.sp; redraw_queue(j); END; { *** 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>sp_max ELSE IF dummy^.sp0) AND holen THEN erledigt := True; { *** Schauen, ob magazinserielle oder -gemischte Übertragung vorliegt } { und danach die Wartezeit festlegen: } IF (dummy^.cbits AND SERMAG)=0 THEN wartezeit := shuffle ELSE wartezeit := burst; IF NOT holen THEN anfordern(j,pg,sp,'!!!'); { Suche geht weiter, PBLF setzen } Dispose(dummy); 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 auf den zugehörigen } { Job zeigt; in die Protokolldatei, falls es eine Untertitelseite ist und } { Protokollierung erwünscht war. } { Erledigte Jobs werden auch gestrichen, sobald keine zu holende Seite mehr } { aussteht. } { 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. Ein Job, der sich auf eine Untertitelseite } { bezieht (Flag C5), ist niemals erledigt und muß anderweitig entfernt } { werden. } VAR dummy,seite: p_onepage; jetzt: zeiteintrag; 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: } busy_pointer; { 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); ins_to_list(seite); normal_pointer; redraw_list; END ELSE BEGIN getpage(job,seite,True); normal_pointer; END; IF seite=thispage THEN writepage(seite,True); { notieren, ob das eine Untertitelseite war: } ist_UT := ist_UT SHR 1; { Bits altern lassen } IF (seite^.cbits AND SUBTITLE)<>0 THEN ist_UT := ist_UT OR $04; IF protokoll AND (ist_UT<>0) THEN BEGIN mainline; Write('Untertitelseite ',seite^.pg,' ...'); IF savebox(seite,outputname,True) THEN Write(' gespeichert.') ELSE BEGIN mainline; Write(#155'33mDateifehler - sorry!'); END; END; holen := False; { Wichtig !!! } anfordern(job,pg,sp,'!!!'); { um PBLF wieder zu setzen } END; END; { Erledigten Job löschen, außer er bezieht sich auf Untertitel } WITH activejobs[job] DO IF (pg>0) AND erledigt AND NOT holen THEN IF (ist_UT<>0) THEN BEGIN { nicht löschen } sp_check[0] := False; sp_count := 0; redraw_queue(job); END ELSE BEGIN { löschen } pg := 0; redraw_queue(job); sperren(job); END; END; PROCEDURE add_job{(entry: Str80)}; { Eine Eingabe, die eine Seitennummer darstellt (oder auch nicht), in die } { Warteschlange einzureihen versuchen. } var j,ok,page,subpage: integer; s: str80; begin j := pos('/',entry); if j > 0 then begin s := copy(entry,1,j-1); val(s,page,ok); s := copy(entry,j+1,length(entry)-j); val(s,subpage,ok); end else begin val(entry,page,ok); subpage := 0; end; if (ok=0) AND (page>=100) AND (page<900) AND (queued0 THEN anfordern(0,pg,sp,'!!!') ELSE sperren(0); Reset(datei,'VT.config'); IF IOResult<>0 THEN BEGIN Reset(datei,'s:VT.config'); IF IOResult<>0 THEN BEGIN Write(#155'33m"VT.config" nicht gefunden!'); Exit; END; END; found := False; anything := False; WHILE NOT EoF(datei) DO BEGIN ReadLn(datei,zeile); is_job := True; FOR t := 1 TO Length(zeile) DO IF NOT (zeile[t] IN ['0'..'9','/']) THEN is_job := False; IF is_job THEN BEGIN IF found THEN add_job(zeile); IF queued=maxactive THEN handle_queue; { Jobs evtl. aufrücken } END ELSE BEGIN found := (Pos(zeile,sender)>0) AND (zeile<>''); IF found THEN BEGIN mainline; Write('hole Seitenauswahl f}r "',zeile,'"'); anything := true; END; END; END; IF NOT anything THEN Write('unbekannter Sender: "',Copy(sender,5,10),'"'); Close(datei); redraw_queue(-1); END; BEGIN { Initialisierungen } END.