home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / VIDEOTEXT.LZX / VTsrc / jobs.p < prev    next >
Encoding:
Text File  |  1996-04-19  |  23.5 KB  |  673 lines

  1. UNIT jobs; {$project vt }
  2. { Job-Verwaltung zum Programm VideoText }
  3.  
  4. INTERFACE; FROM vt USES datei;
  5.  
  6. VAR editor,configpath: str80;
  7.     toplevel: Integer;
  8.     active: Byte; { aktive Jobs in der Seitensuche }
  9.     maxwait, burst,shuffle: Integer;
  10.     i2c_snooze: Boolean;
  11.  
  12. PROCEDURE sleep;
  13. PROCEDURE wakeup;
  14. PROCEDURE kill_queue;
  15. PROCEDURE handle_queue;
  16. PROCEDURE handle_jobs;
  17. PROCEDURE attempt_input(job: Integer);
  18. PROCEDURE add_job(entry: str80; blind: Boolean);
  19. PROCEDURE kill_job(nr: Integer);
  20. PROCEDURE cancel_job(entry: str80);
  21. PROCEDURE hurricane;
  22. PROCEDURE page_grabber(filter: Boolean);
  23. PROCEDURE topgrab(pg0: p_onepage);
  24. PROCEDURE getconfig(nr: Integer);
  25. FUNCTION edconfig(nr: Integer): Boolean;
  26. PROCEDURE dump_numbers;
  27.  
  28. { ---------------------------------------------------------------------- }
  29.  
  30. IMPLEMENTATION;
  31.  
  32. {$ opt q,s+,i+} { keine Laufzeitprüfungen außer Stack und Feldindizes }
  33.  
  34. CONST SERMAG = $0800; { C11 }
  35.       RENEW  = $0100; { C8 }
  36.       STITLE = $0040; { C6 }
  37.       HEADLN = $0020; { C5 }
  38.  
  39. VAR bedtime: zeiteintrag;
  40.  
  41. PROCEDURE uhrzeit(VAR zeit: zeiteintrag);
  42. BEGIN
  43.   telltime(zeit.tage,zeit.min,zeit.tics);
  44. END;
  45.  
  46. PROCEDURE add_time(delta: zeiteintrag; VAR zeit: zeiteintrag);
  47. BEGIN
  48.   IF zeit.tics + delta.tics>=3000 THEN Inc(zeit.min);
  49.   zeit.tics := (zeit.tics + delta.tics) MOD 3000;
  50.   IF zeit.min + delta.min>=1440 THEN Inc(zeit.tage);
  51.   zeit.min := (zeit.min + delta.min) MOD 1440;
  52.   zeit.tage := zeit.tage + delta.tage;
  53. END;
  54.  
  55. PROCEDURE sub_time(delta: zeiteintrag; VAR zeit: zeiteintrag);
  56. BEGIN
  57.   IF zeit.tics - delta.tics<0 THEN Dec(zeit.min);
  58.   zeit.tics := (zeit.tics - delta.tics + 3000) MOD 3000;
  59.   IF zeit.min - delta.min<0 THEN Dec(zeit.tage);
  60.   zeit.min := (zeit.min - delta.min + 1440) MOD 1440;
  61.   zeit.tage := zeit.tage - delta.tage;
  62. END;
  63.  
  64. FUNCTION diff_time(alt, neu: zeiteintrag): Long;
  65. { liefert die Differenz zwischen zwei Zeitpunkten in Ticks (1/50-Sekunden) }
  66. BEGIN
  67.   diff_time := neu.tics - alt.tics + 3000 * ( (neu.min - alt.min)
  68.                + 1440 * (neu.tage - alt.tage) );
  69. END;
  70.  
  71. PROCEDURE sleep;
  72. { wird vor Unterbrechung der Hauptschleife (z. B. durch FileRequester) }
  73. { aufgerufen }
  74. BEGIN
  75.   uhrzeit(bedtime);
  76. END;
  77.  
  78. PROCEDURE wakeup;
  79. { Verhindert in Zusammenarbeit mit sleep, daß Zeiten, während derer der }
  80. { VT-Decoder gar nicht abgefragt wird, zum Löschen von Jobs wegen }
  81. { Zeitüberschreitung führen. }
  82. VAR delta: zeiteintrag;
  83.     j: Integer;
  84. BEGIN
  85.   uhrzeit(delta);
  86.   sub_time(bedtime,delta);
  87.   FOR j := 0 TO maxactive-1 DO
  88.     add_time(delta,activejobs[j].lastaction);
  89. END;
  90.  
  91. PROCEDURE kill_queue;
  92. VAR i: Integer;
  93. BEGIN
  94.   queued := 0;
  95.   IF thisjob<0 THEN thisjob := 0;
  96.   FOR i := 0 TO maxactive-1 DO BEGIN
  97.     activejobs[i].pg := 0; sperren(i);
  98.   END;
  99. END;
  100.  
  101. PROCEDURE count_them;
  102. { durchzählen, wer in der Seitensuche alles bedient werden will: }
  103. VAR j: Integer;
  104. BEGIN
  105.   active := 0;
  106.   FOR j := 0 TO maxactive-1 DO
  107.     IF (activejobs[j].pg>0) THEN Inc(active);
  108. END;
  109.  
  110. PROCEDURE handle_queue;
  111. { Verwaltet das Aufrücken wartender Jobs. }
  112. { Jobs mit unbestimmter Unterseitennummer, also mit /0, /*, /., /! können }
  113. { aktive Jobs mit gleicher Seitennummer aus der Seitensuche verdrängen }
  114. VAR i,j,killer,moved: Integer;
  115. BEGIN
  116.   moved := 0;
  117.   REPEAT
  118.     j := -1;
  119.     IF queued>0 THEN BEGIN
  120.       { Soll ein aktiver Job verdrängt werden? }
  121.       IF queue[firstinq].sp<1 THEN
  122.         FOR i := 0 TO maxactive-1 DO
  123.           IF activejobs[i].pg=queue[firstinq].pg THEN j := i;
  124.       { Oder ist ein Platz in der Seitensuche frei? }
  125.       IF j<0 THEN
  126.         FOR i := maxactive-1 DOWNTO 0 DO
  127.           IF activejobs[i].pg=0 THEN j := i;
  128.     END;
  129.     IF j>=0 THEN BEGIN
  130.       { Empfangseinheit <j> mit wartendem Job belegen }
  131.       { Ein wartender Job besteht nur aus Seiten- und Unterseitennummer, }
  132.       { jetzt kommen eine Menge Informationen dazu. }
  133.       WITH activejobs[j] DO BEGIN
  134.         pg := queue[firstinq].pg; sp := queue[firstinq].sp;
  135.         sp_count := 0; sp_max := 0;
  136.         holen := False; erledigt := False;
  137.         FOR i := 0 TO maxsubpage DO sp_check[i] := False;
  138.         uhrzeit(lastaction);
  139.         anfordern(j,pg,sp,%111);
  140.       END;
  141.       IF i2c_status<>0 THEN BEGIN  { Oh Mann! Dummer I²C-Bus! }
  142.         activejobs[j].pg := 0;   { Kommando zurück }
  143.         j := -1;  { hier ist nichts mehr zu holen }
  144.       END ELSE BEGIN
  145.         { Warteschlange aufrücken: }
  146.         Dec(queued); Inc(firstinq); IF firstinq>qlen THEN firstinq := 1;
  147.         { Auswahlzeiger des Benutzers dem Aufrücken entsprechend nachführen: }
  148.         IF thisjob=-1 THEN thisjob := j
  149.           ELSE IF thisjob<0 THEN Inc(thisjob);
  150.         IF thisjob>=0 THEN BEGIN
  151.           aktspeicher := thisjob; display_select(aktspeicher); END;
  152.         Inc(moved);
  153.       END;
  154.     END;
  155.   UNTIL j=-1;
  156.   IF moved>0 THEN redraw_queue(-1);
  157.   count_them;
  158. END;
  159.  
  160. PROCEDURE requeue(i: Integer; fifo: Boolean);
  161. { einen aktiven Job in die Warteschlange zurückstellen }
  162. VAR j: Integer;
  163. BEGIN
  164.   IF (queued<qlen) AND (activejobs[i].pg>0) THEN BEGIN
  165.     IF fifo THEN BEGIN
  166.       j := firstinq+queued; IF j>qlen THEN j := 1;
  167.     END ELSE BEGIN
  168.       Dec(firstinq); IF firstinq=0 THEN firstinq := qlen; j := firstinq;
  169.     END;
  170.     Inc(queued);
  171.     queue[j].pg := activejobs[i].pg; queue[j].sp := activejobs[i].sp;
  172.   END;
  173.   activejobs[i].pg := 0; sperren(i);
  174. END;
  175.  
  176. PROCEDURE rausschmeisser;
  177. { Prüfen, ob ein Job wegen Zeitüberschreitung gestrichen werden kann. }
  178. { Wenn der Job allerdings so lange wartet, weil er sich auf eine einzelne }
  179. { Unterseite bezieht, ist ihm verziehen und er wird lediglich ans Ende der }
  180. { Warteschlange gesetzt. Und für festgehaltene Seitennummern findet eine }
  181. { Prüfung auf Zeitüberschreitung gar nicht erst statt. }
  182. VAR i, j: Integer;
  183.     jetzt: zeiteintrag;
  184. BEGIN
  185.   uhrzeit(jetzt);
  186.   FOR j := 0 TO maxactive-1 DO WITH activejobs[j] DO
  187.     IF (pg<>0) AND (diff_time(lastaction,jetzt) > 50*maxwait)
  188.     AND (sp>-2) THEN  { keine "festgehaltenen" Seiten! }
  189.       IF sp IN [0,-1] THEN BEGIN
  190.         { einfache Seitennummer streichen }
  191.         pg := 0; sperren(j); redraw_queue(j);
  192.       END ELSE IF queued>0 THEN BEGIN
  193.         { Unterseitenanforderung nur hintenanstellen }
  194.         requeue(j,True); redraw_queue(-1);
  195.       END;
  196.   count_them;
  197. END;
  198.  
  199. PROCEDURE handle_jobs;
  200. { Überprüft, ob in einem der Empfangskreise eine Seite eingetroffen ist, und }
  201. { wenn ja, ob sie aufgrund ihrer Unterseitennummer überhaupt eingelesen }
  202. { werden muß. Es wird auch entschieden, ob der Job durch die eingetroffene }
  203. { Seite erledigt ist. Kriterium für 'erledigt': }
  204. { Ein Job mit sp>0 ist erledigt, sobald die eine angeforderte Unterseite }
  205. { da ist. Ein Job mit sp=0 ist erst dann erledigt, wenn alle seine }
  206. { Unterseiten eingelesen wurden. Wann das ist, läßt sich nur raten, aber }
  207. { ganz gut raten. Und es gibt noch einige Sonderfälle mit sp<0 ... }
  208. VAR j: Integer;
  209.     dummy: p_onepage;
  210.     sp_decval: Integer;
  211. BEGIN
  212.   rausschmeisser;
  213.   { Schauen, ob irgendwo das Eintreffen einer Kopfzeile gemeldet wurde: }
  214.   FOR j := 0 TO maxactive-1 DO WITH activejobs[j] DO
  215.     IF (pg>0) AND NOT holen THEN IF seite_da(j) THEN BEGIN
  216.       New(dummy);
  217.       uhrzeit(lastaction);
  218.       getpage(j,dummy,False); { *nur* Status und Seitennummer holen }
  219.       akt_sp := dummy^.sp;
  220.       sp_decval := get_bcd(akt_sp);
  221.       { *** Schauen, ob die Seite eingelesen werden muß. Gründe, weswegen }
  222.       {   man eine Seite evtl. nicht haben will: }
  223.       { 1.: Unterseite wurde bereits eingelesen. }
  224.       {   (Bei zu großen Unterseitennummern kann das nur über ein etwas }
  225.       {   armseliges Hilfskriterium festgestellt werden.) }
  226.       IF (sp_decval<=maxsubpage) THEN holen := NOT sp_check[sp_decval]
  227.         ELSE holen := (akt_sp>sp_max);
  228.       { 2.: Nur eine Unterseite war angefordert, und zwar nicht diese. }
  229.       {   Das dürfte allerdings kaum vorkommen, da der CCT ausdrücklich auf }
  230.       {   die eine Unterseite programmiert wurde. }
  231.       IF sp>0 THEN holen := (akt_sp=sp);
  232.       { Selbstnumerierende Unterseiten werden blind alle eingelesen, bis }
  233.       { der Job erledigt ist: }
  234.       IF sp<-10 THEN BEGIN
  235.         holen := True; akt_sp := make_bcd(sp_count+1);
  236.         IF sp=-11 THEN akt_sp := 0;
  237.         sp_decval := get_bcd(akt_sp);
  238.       END;
  239.       IF holen THEN BEGIN
  240.         { *** Unterseitenverwaltung aktualisieren: }
  241.         Inc(sp_count);
  242.         IF (sp_decval<=maxsubpage) THEN  sp_check[sp_decval] := True;
  243.         IF akt_sp>sp_max  THEN sp_max := akt_sp;
  244.         redraw_queue(j);
  245.         { *** Schauen, ob magazinserielle oder -gemischte Übertragung }
  246.         {   vorliegt und danach die Wartezeit festlegen: }
  247.         IF (dummy^.cbits AND SERMAG)=0 THEN
  248.           wartezeit := shuffle ELSE wartezeit := burst;
  249.       END ELSE
  250.         anfordern(j,pg,sp,%111); { blöde Unterseite, Suche fortsetzen }
  251.       { *** Prüfen, ob der Job durch die eingetroffene Seite erledigt ist. }
  252.       {   Das geht z. B. durch Unterseite 0 (= einzige Unterseite). }
  253.       {   auf keinen Fall aber durch eine Unterseite mit der bislang }
  254.       {   höchsten Nummer. }
  255.       IF sp_check[0] THEN
  256.         erledigt := sp_count>get_bcd(sp_max)
  257.       ELSE IF akt_sp<sp_max THEN
  258.         erledigt := sp_count=get_bcd(sp_max);
  259.       { Auch möglich: die einzig geforderte Unterseite ist da. }
  260.       IF ((sp>0) OR (sp=-1)) AND holen THEN
  261.         erledigt := True;
  262.       { Oder es sind genauso viele selbstnumerierende Unterseiten }
  263.       { eingetroffen, wie angefordert waren. }
  264.       IF (sp<-10) THEN
  265.         erledigt := (sp_count=-sp-10);
  266.       { überwachte Seiten sind aus kosmetischen Gründen immer "erledigt": }
  267.       IF (sp=-2) OR (sp=-3) THEN
  268.         erledigt := True;
  269.       Dispose(dummy);
  270.     END;
  271. END;
  272.  
  273. PROCEDURE attempt_input{(job: Integer)};
  274. { Das Einlesen geschieht in einem zweiten Schritt, da nach Eintreffen der }
  275. { Kopfzeile erst eine Weile gewartet werden muß. }
  276. { Evtl. wird die Seite auch gleich ausgegeben: auf dem Bildschirm, falls }
  277. { <thisjob> auf den zugehörigen Job zeigt oder wenn eine festgehaltene }
  278. { Seite aktualisiert wurde; in die Ausgabedatei, falls es eine zu }
  279. { protokollierende Seite war. }
  280. { Jobs, die nach diesem Einlesen erledigt sind, wurden bereits entsprechend }
  281. { gekennzeichnet und werden aus der Liste gestrichen. }
  282. VAR dummy,seite: p_onepage;
  283.     jetzt: zeiteintrag;
  284.     exciting: Boolean;
  285.     i: Integer;
  286. BEGIN
  287.   { Prüfen, ob die Wartezeit für eine einzulesende Seite um ist: }
  288.   WITH activejobs[job] DO
  289.     IF (pg>0) AND holen THEN BEGIN
  290.       uhrzeit(jetzt);
  291.       IF diff_time(lastaction,jetzt) >= wartezeit THEN BEGIN
  292.         { Seite einlesen: }
  293.         IF i2c_snooze THEN busy_pointer;
  294.         { Ist bereits eine alte Version dieser Seite in der Liste, die dann }
  295.         { lediglich überschrieben werden müßte? }
  296.         seite := hunt_in_list(pg,akt_sp,True);
  297.         IF seite=Nil THEN BEGIN
  298.           New(seite);
  299.           getpage(job,seite,True);
  300.           IF i2c_snooze THEN normal_pointer;
  301.           IF sp<-10 THEN seite^.sp := akt_sp; { selbstnumerierende Seite! }
  302.           add_sp_number(seite);
  303.           IF i2c_status<>0 THEN BEGIN Dispose(seite); Exit; END;
  304.           ins_to_list(seite);
  305.           update_list(seite,1);
  306.         END ELSE BEGIN
  307.           getpage(job,seite,True);
  308.           IF i2c_snooze THEN normal_pointer;
  309.           IF sp<-10 THEN seite^.sp := akt_sp; { selbstnumerierende Seite! }
  310.           add_sp_number(seite);
  311.           IF i2c_status<>0 THEN Exit;
  312.           IF seite<>thispage THEN update_list(seite,0);
  313.         END;
  314.         { bildschirmüberwachte Seiten sind interessant, wenn sie das erste }
  315.         { Mal eintreffen oder wenn sich der Inhalt geändert hat: }
  316.         exciting := (sp=-2) AND ((sp_count=1) OR (seite^.cbits AND RENEW<>0))
  317.             AND (seite^.cbits AND STITLE=0) AND (seite^.sp=0);
  318.         { Untertitel und Mehrfachseiten aber ausgenommen! }
  319.         { bildschirmüberwachte Seite anzeigen: }
  320.         IF (seite=thispage) OR exciting THEN BEGIN
  321.           mainline;
  322.           IF exciting THEN showscreen(True);
  323.           IF seite<>thispage THEN BEGIN
  324.             Write('neuer Inhalt S. ',hexstr(pg,3),'!');
  325.             writepage(seite,True);
  326.             mainline; Write('bitte Leertaste dr}cken');
  327.           END ELSE
  328.             writepage(seite,True);
  329.         END;
  330.         { dateiüberwachte Seite abspeichern: }
  331.         IF sp=-3 THEN
  332.           IF (sp_count=1) OR (seite^.cbits AND RENEW<>0) THEN BEGIN
  333.             sleep; IF save_action(seite,1)=0 THEN BEGIN
  334.               { nach einmal genehmigtem Überschreiben auf Anhängen umschalten: }
  335.               overwrite := False; fileinfo;
  336.             END ELSE
  337.               sp_count := 0; { nach fehlgeschlagenem Speichern }
  338.               { sofort beim nächsten Mal wieder versuchen lassen }
  339.             wakeup;
  340.           END ELSE
  341.             mainline;
  342.         holen := False;  { beendet auch "Schonfrist" für erledigte Jobs }
  343.         anfordern(job,pg,sp,%111);   { um PBLF wieder zu setzen }
  344.       END;
  345.     END;
  346.   { Erledigten (und eingelesenen) Job löschen: }
  347.   WITH activejobs[job] DO
  348.     IF (pg>0) AND erledigt AND NOT holen THEN BEGIN
  349.       IF (sp IN [-2,-3]) THEN BEGIN   { Sonderfälle: niemals erledigt }
  350.         { nur die Zähler zurücksetzen, außer sp_count }
  351.         sp_max := 0; erledigt := False;
  352.         FOR i := 0 TO maxsubpage DO sp_check[i] := False;
  353.       END ELSE BEGIN
  354.         pg := 0; sperren(job);  { löschen }
  355.       END;
  356.       redraw_queue(job);
  357.     END;
  358.   count_them;
  359. END;
  360.  
  361. PROCEDURE add_job{(entry: Str80; blind: Boolean)};
  362. { Eine Eingabe, die eine Seitennummer darstellt (oder auch nicht), in die }
  363. { Warteschlange einzureihen versuchen. }
  364. { Bei blind=False wird noch überprüft, ob sich vielleicht bereits ein }
  365. { identischer Job in der Seitensuche befindet. }
  366. { Anschließend zeigt <thisjob> auf die neu besetzte Stelle. }
  367. VAR i,j,page,subpage: Integer;
  368.     s: str80;
  369.     ok: Boolean;
  370. BEGIN
  371.   i := Pos('-',entry);
  372.   j := Pos('/',entry);
  373.   IF i > 0 THEN BEGIN
  374.     page := hexval(Copy(entry,1,i-1));
  375.     Val(Copy(entry,i+1,Length(entry)-i),subpage,i); { Anzahl nicht als BCD! }
  376.     subpage := -10-subpage;
  377.   END ELSE IF j > 0 THEN BEGIN
  378.     page := hexval(Copy(entry,1,j-1));
  379.     subpage := hexval(Copy(entry,j+1,Length(entry)-j));
  380.     IF entry[j+1]='*' THEN subpage := -1;
  381.     IF entry[j+1]='.' THEN subpage := -2;
  382.     IF entry[j+1]='!' THEN subpage := -3;
  383.   END ELSE BEGIN
  384.     page := hexval(entry);
  385.     subpage := 0;
  386.   END;
  387.   ok := (page>=$100) AND (page<$900);
  388.   { evtl. weitere Einschränkung: mit bereits vorhandenen Jobs vergleichen }
  389.   { und keinen Job zulassen, der ein Verdrängen bewirken würde }
  390.   IF NOT blind THEN BEGIN
  391.     FOR j := 0 TO maxactive-1 DO
  392.       IF (activejobs[j].pg=page) AND (subpage<1) THEN ok := False;
  393.     FOR j := 1 TO queued DO BEGIN
  394.       i := (firstinq + j - 2) MOD qlen + 1;
  395.       IF (queue[i].pg=page) AND (subpage<1) THEN ok := False;
  396.     END;
  397.   END;
  398.   IF ok AND (queued<qlen) THEN BEGIN
  399.     Inc(queued);
  400.     IF fifo THEN BEGIN
  401.       j := firstinq+queued-1; IF j>qlen THEN j := 1;
  402.       thisjob := -queued;
  403.     END ELSE BEGIN
  404.       Dec(firstinq); IF firstinq=0 THEN firstinq := qlen; j := firstinq;
  405.       thisjob := -1;
  406.     END;
  407.     queue[j].pg := page; queue[j].sp := subpage;
  408.   END;
  409. END;
  410.  
  411. PROCEDURE kill_job{(nr: Integer)};
  412. { einen Job löschen, <thisjob> nachführen, Bildschirm aber *nicht* }
  413. { aktualisieren }
  414. VAR j: Integer;
  415. BEGIN
  416.   IF nr>=0 THEN BEGIN  { aktiver Job }
  417.     activejobs[nr].pg := 0;
  418.     sperren(nr);
  419.   END ELSE IF (-nr<=queued) THEN BEGIN  { wartender Job }
  420.     FOR j := -nr TO queued-1 DO
  421.       queue[(firstinq+j-2) MOD qlen + 1] :=
  422.         queue[(firstinq+j-1) MOD qlen + 1];
  423.     Dec(queued);
  424.     IF fifo AND (thisjob<=nr) THEN Inc(thisjob);  { normal: thisjob=nr }
  425.     IF -thisjob>queued THEN Inc(thisjob);
  426.   END;
  427. END;
  428.  
  429. PROCEDURE cancel_job{(entry: str80)};
  430. { Als Erleichterung gegenüber kill_job() wird nicht die Position in der }
  431. { Warteschlange sondern der 'Name' des Jobs angegeben. }
  432. VAR page,j: Integer;
  433. BEGIN
  434.   page := hexval(Copy(entry,1,3));
  435.   FOR j := 0 TO maxactive-1 DO
  436.     IF activejobs[j].pg=page THEN kill_job(j);
  437.   FOR j := -queued TO -1 DO
  438.     IF queue[(-j+firstinq-2) MOD qlen + 1].pg=page THEN kill_job(j);
  439. END;
  440.  
  441. PROCEDURE hurricane;
  442. { Die Seiten aus der Seitensuche zurück in die Warteschlange fegen. }
  443. VAR j: Integer;
  444. BEGIN
  445.   FOR j := 0 TO maxactive-1 DO
  446.     requeue(j,False);
  447. END;
  448.  
  449. PROCEDURE page_grabber{(filter: Boolean)};
  450. { Rechenzeitintensive Variante der Seitensuche: alle Seiten einlesen, wie }
  451. { sie kommen. Für <filter>=True werden nur Seiten mit rein dezimaler }
  452. { Seitennummer gelesen, Pseudoseiten also herausgefiltert. }
  453. { Prinzip des Algorithmus: }
  454. { Kreis 3  Kreis 2  Kreis 1  Kreis 0   (nach aufsteigender Priorität)  }
  455. {   *        x        x        x     |                                 }
  456. { =====      *                       |  === Kopfzeile     * anfordern  }
  457. { -----                              |  --- Folgezeile    x sperren    }
  458. { -----                              |  ^^^ Seite komplett             }
  459. { ^^^^^    =====      *              |                                 }
  460. {          -----                     | Gesucht wird i. a. nach Seite   }
  461. {          -----                     | "???", bei magazinparalleler    }
  462. {          ^^^^^    =====      *     | Übertragung dagegen nach "X??", }
  463. {                   -----            | wobei X=1..8 für alle 4 Kreise  }
  464. {                   -----            | gleich sein muß. }
  465. {                   ^^^^^    =====   | }
  466. { Jetzt sind die Seiten in 3, 2 und 1 stabil und komplett und können }
  467. { ausgelesen werden. }
  468. { Eine ganz naheliegende Idee wäre es, 3 und 2 bereits auszulesen, noch }
  469. { während man in 1 bzw. 0 auf Kopfzeilen wartet. }
  470. { Andererseits ist es wichtig, bereits die erste Seite, die nach der }
  471. { Anforderung eintrifft, im jeweiligen Kreis einzufrieren. Für alle }
  472. { danach eintreffenden Seiteninhalte wird der Speicher nämlich nicht mehr }
  473. { extra gelöscht, so daß unvollständig definierte Seiten (Schlagzeilen }
  474. { z. B.) mit ihren Vorgängern verschmelzen, was nicht so toll aussieht. }
  475. { Diese zeitoptimale Methode ist darum nur bei magazinparalleler }
  476. { Übertragung bedenkenlos möglich. Dort treffen aufeinanderfolgende }
  477. { Seiten eines Magazins nur ca. alle 0.8 sec ein, und so schnell geht das }
  478. { Einlesen über den I²C-Bus noch allemal (ca. 0.4 sec/Seite). }
  479. VAR i,mag,anz,neu: Integer;
  480.     seite,dummy: p_onepage;
  481.     timeout,parmode: Boolean;
  482. PROCEDURE waitforpg(unit: Integer);
  483. { max. 2 Sekunde auf das Eintreffen einer Seite warten }
  484. VAR t0,t: zeiteintrag;
  485. BEGIN
  486.   uhrzeit(t0);
  487.   REPEAT
  488.     uhrzeit(t); timeout := diff_time(t0,t)>100;
  489.   UNTIL seite_da(unit) OR timeout;
  490. END;
  491. PROCEDURE einlesen(unit: Integer);
  492. { neue Seite einlesen und einreihen }
  493. BEGIN
  494.   getpage(unit,dummy,False);
  495.   IF (make_bcd(get_bcd(dummy^.pg))=dummy^.pg) OR NOT filter THEN BEGIN
  496.     Inc(anz); seite := hunt_in_list(dummy^.pg,dummy^.sp,True);
  497.     IF seite=Nil THEN BEGIN
  498.       New(seite); Inc(neu);
  499.       getpage(unit,seite,True); add_sp_number(seite); ins_to_list(seite);
  500.     END;
  501.   END;
  502. END;
  503. BEGIN
  504.   New(dummy);
  505.   anz := 0; neu := 0;
  506.   hurricane; redraw_queue(-1);  { Seitensuche freimachen }
  507.   REPEAT
  508.     FOR i := 0 TO 2 DO sperren(i);
  509.     anfordern(3,$100,0,%000);
  510.     waitforpg(3); getpage(3,dummy,False);
  511.     parmode := (dummy^.cbits AND SERMAG)=0;
  512.     IF parmode THEN BEGIN  { magazinparallele Sendefolge ;-\ }
  513.       FOR i := 3 DOWNTO -1 DO IF NOT timeout THEN BEGIN
  514.         { indirektes Sperren von (i+1): }
  515.         IF i>-1 THEN anfordern(i,dummy^.pg,0,%100)
  516.         { Die Seite in (i+2) ist bereits komplett und stabil: }
  517.         IF i<2 THEN einlesen(i+2);
  518.         { jetzt auf die zuletzt angeforderte Seite warten: }
  519.         IF i>-1 THEN waitforpg(i);
  520.       END
  521.     END ELSE BEGIN  { normale, magazinserielle Sendefolge }
  522.       FOR i := 2 DOWNTO 0 DO IF NOT timeout THEN BEGIN
  523.         { (i+1) sperren und auf die nächste Seite warten: }
  524.         anfordern(i,$100,0,%000); waitforpg(i);
  525.       END;
  526.       { alle kompletten Seiten einlesen: }
  527.       IF NOT timeout THEN
  528.         FOR i := 3 DOWNTO 1 DO einlesen(i);
  529.     END;
  530.     mainline; Write(anz,' Seiten gefunden, ',neu,' gelesen');
  531.     event_scan;
  532.   UNTIL newevent OR timeout;
  533.   IF timeout THEN BEGIN
  534.     mainline; Write('keine neuen Seiten - Abbruch');
  535.   END;
  536.   Dispose(dummy);
  537. END;
  538.  
  539. PROCEDURE topgrab{(pg0: p_onepage)};
  540. { alle laut TOP-Text verfügbaren Seiten anfordern, allerdings nur bis zu }
  541. { der durch <toplevel> vorgegebenen Priorität }
  542. CONST interleave=10;
  543. VAR i,j,n,level: Integer;
  544.     pri: ARRAY[0..17] OF Char;
  545. BEGIN
  546.   pri := '-KABCDEFHGJI-----';
  547.   FOR level := 1 TO toplevel DO
  548.     FOR i := 0 TO interleave-1 DO
  549.       FOR j := 0 TO 799 DIV interleave DO BEGIN
  550.         n := 100 + j*interleave + i;
  551.         IF (n<900) THEN BEGIN
  552.           IF Ord(pri[topcode[pg0^.chars[n-60]]])-64=level THEN
  553.             add_job(IntStr(n),True);   { nach absteigender Priorität }
  554.         END;
  555.       END;
  556.   redraw_queue(-1);
  557. END;
  558.  
  559. PROCEDURE getconfig{(nr: Integer)};
  560. VAR datei: Text;
  561.     sender, zeile, name: str80;
  562.     is_header, found, anything, save_fifo: Boolean;
  563.     t: Integer;
  564. BEGIN
  565.   IF activejobs[0].pg=0 THEN BEGIN
  566.     anfordern(0,$100,0,%000);
  567.     t := 50;   { max. 1 sec warten! }
  568.     REPEAT Delay(1); Dec(t) UNTIL seite_da(0) or (t=0);
  569.   END;
  570.   gethead(0,sender);
  571.   IF activejobs[0].pg=0 THEN sperren(0);
  572.   IF nr=2 THEN name := configpath+'VT2.config'
  573.           ELSE name := configpath+'VT.config';
  574.   Reset(datei,name);
  575.   IF IOResult<>0 THEN BEGIN
  576.     mainline; Write(#155'2m"',name,'" nicht gefunden!');
  577.     add_job('100',False);
  578.     redraw_queue(-1);
  579.     Exit;
  580.   END;
  581.   Buffer(datei,500);
  582.   found := False; anything := False;
  583.   is_header := True;
  584.   save_fifo := fifo; fifo := True;
  585.   WHILE NOT EoF(datei) DO BEGIN
  586.     ReadLn(datei,zeile);
  587.     t := Length(zeile); WHILE t>0 DO BEGIN
  588.       IF zeile[t]=' ' THEN zeile[t] := #0 ELSE t := 1;
  589.       Dec(t);
  590.     END;
  591.     IF zeile='' THEN
  592.       is_header := True { auf eine Leerzeile folgt ein Titel }
  593.     ELSE BEGIN
  594.       IF is_header THEN BEGIN
  595.         found := (Pos(zeile,sender)>0);
  596.         IF found THEN BEGIN
  597.           mainline; Write('hole '); IF nr>1 THEN Write(nr,'. ');
  598.           Write('Seitenauswahl f}r "',zeile,'"');
  599.           anything := True;
  600.         END;
  601.       END ELSE
  602.         IF found THEN add_job(zeile,True);
  603.       is_header := False;
  604.     END;
  605.   END;
  606.   IF NOT anything THEN BEGIN
  607.     Write('unbekannter Sender: "',Copy(sender,5,10),'"');
  608.     add_job('100',False);
  609.   END;
  610.   Close(datei);
  611.   fifo := save_fifo;
  612.   redraw_queue(-1);
  613. END;
  614.  
  615. FUNCTION edconfig{(nr: Integer): Boolean};
  616. VAR fenster: Text;
  617.     s: Str80;
  618. LIBRARY DosBase:  { Include-Files nein danke }
  619. -222 : FUNCTION  Execute(D1: Str; D2,D3: Long): Boolean;
  620. END;
  621. BEGIN
  622.   showscreen(False);
  623.   Reset(fenster,'CON:100/100/440/80/VT-Ausgabefenster');
  624.   IF nr=2 THEN s := editor + configpath + 'VT2.config'
  625.           ELSE s := editor + configpath + 'VT.config';
  626.   edconfig := Execute(s,0,FileHandle(fenster));
  627.   Close(fenster);
  628.   showscreen(True);
  629. END;
  630.  
  631. PROCEDURE dump_numbers;
  632. { Sendername und Seitennummern ins Clipboard schreiben, Hilfe beim Erstellen }
  633. { der config-Dateien }
  634. VAR anz,nextnr,i: Integer;
  635.     hilf: p_onepage;
  636.     ok: Boolean;
  637.     s: str80;
  638. BEGIN
  639.   IF root=Nil THEN Exit;
  640.   anz := 0; hilf := root;
  641.   WHILE hilf<>Nil DO BEGIN
  642.     IF hilf^.next=Nil THEN nextnr := -1 ELSE nextnr := hilf^.next^.pg;
  643.     IF (hilf^.pg<$900) AND (hilf^.pg<>nextnr) THEN Inc(anz);
  644.     hilf := hilf^.next;
  645.   END;
  646.   start_clip(26+4*anz);
  647.   FOR i := 2 TO 25 DO BEGIN
  648.     s[i] := Chr(root^.chars[i+6]);
  649.     IF s[i]<' ' THEN s[i] := ' ';
  650.   END;
  651.   s[1] := #10; s[26] := #10; s[27] := #0;
  652.   clip_it(s,26);
  653.   hilf := root;
  654.   WHILE hilf<>Nil DO BEGIN
  655.     IF hilf^.next=Nil THEN nextnr := -1 ELSE nextnr := hilf^.next^.pg;
  656.     IF (hilf^.pg<$900) AND (hilf^.pg<>nextnr) THEN BEGIN
  657.       s := hexstr(hilf^.pg,3)+#10; clip_it(s,4);
  658.     END;
  659.     hilf := hilf^.next;
  660.   END;
  661.   end_clip;
  662. END;
  663.  
  664. BEGIN  { Initialisierungen }
  665.   editor := 'c:Ed '; { Editor für configs }
  666.   configpath := '';
  667.   toplevel := 4;  { nur Programm- und Blockseiten }
  668.   maxwait := 80;
  669.   burst := 0;
  670.   shuffle := 20;
  671.   i2c_snooze := False; { kein Busy-Pointer beim Lesen von Seiten! }
  672. END.
  673.