home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 1 / Mecomp-CD.iso / amiga / tools / misc / videotext5.41 / src / videotext.p < prev    next >
Encoding:
Text File  |  1997-06-15  |  32.3 KB  |  938 lines

  1. PROGRAM VideoText;
  2. FROM vt USES startup,info; {$opt q,s+,i+ }
  3. { Hauptprogramm/Ereignisverwaltung zum Projekt VideoText }
  4.  
  5. CONST version = '$VER: VideoText 5.41  (15.06.97)';
  6.  
  7. {          global       sys }
  8. {         /  |   \      /   }
  9. { pagelist decode cct  /    }
  10. {       \    |    /   /     }
  11. {        bildschirm _/      }
  12. {            |              }
  13. {          datei            }
  14. {            |              }
  15. {           jobs            }
  16. {          /   \            }
  17. {      info    startup      }
  18. {                           }
  19. {  HAUPTPROGRAMM VIDEOTEXT  }
  20.  
  21. CONST stacksize=10;
  22.  
  23. VAR l: Long;
  24.     stop,searching,auto: Boolean;
  25.     roundrobin: Byte;
  26.     inputname,searchstr: Str80;
  27.     j,toprequest,adip_count: Integer;
  28.     pgstack: ARRAY[1..stacksize] OF RECORD pg,sp: Integer; END;
  29.     stackptr,stackbot: Integer;
  30.     lastslide: zeiteintrag;
  31.  
  32. PROCEDURE push(seite: p_onepage);
  33. { "vergeßlicher" Stack: Überlauf führt nicht zum Abweisen der neuen }
  34. { Seitennummer, sondern zum Vergessen der ältesten. }
  35. BEGIN
  36.   IF seite<>Nil THEN BEGIN
  37.     pgstack[stackptr].pg := seite^.pg;
  38.     pgstack[stackptr].sp := seite^.sp;
  39.     Inc(stackptr); IF stackptr>stacksize THEN stackptr := 1;
  40.     IF stackptr=stackbot THEN BEGIN
  41.       Inc(stackbot); IF stackbot>stacksize THEN stackbot := 1;
  42.     END;
  43.   END;
  44. END;
  45.  
  46. FUNCTION pop: p_onepage;
  47. VAR seite: p_onepage;
  48. BEGIN
  49.   seite := Nil;
  50.   WHILE (stackptr<>stackbot) AND (seite=Nil) DO BEGIN
  51.     Dec(stackptr); IF stackptr=0 THEN stackptr := stacksize;
  52.     seite := hunt_in_list(pgstack[stackptr].pg,pgstack[stackptr].sp,True);
  53.   END;
  54.   IF seite=Nil THEN short_msg('Weiter zurück geht''s nicht.',0);
  55.   pop := seite;
  56. END;
  57.  
  58. PROCEDURE topcleaner;
  59. { entfernt unnötige TOP-Seiten aus der Seitenliste, je nachdem welche noch }
  60. { gebraucht werden. }
  61. VAR seite,hilf: p_onepage;
  62.     i: Integer;
  63.     refresh,kill: Boolean;
  64. BEGIN
  65.   refresh := False;
  66.   FOR i := $1F0 TO $1F4 DO BEGIN
  67.     seite := hunt_in_list(i,0,True);
  68.     CASE i OF
  69.       $1F0: kill := toprequest=0;
  70.       $1F1: kill := (toprequest AND 2)=0;
  71.       OTHERWISE kill := (toprequest AND 4)=0;
  72.     END;
  73.     IF kill AND (seite<>Nil) THEN BEGIN
  74.       IF seite=visblpage THEN refresh := True;
  75.       hilf := seite^.next; del_from_list(seite); update_list(hilf,-1);
  76.     END;
  77.   END;
  78.   IF refresh THEN writepage(thispage,True);
  79. END;
  80.  
  81. PROCEDURE topscan;
  82. { Schaut, was für TOP-Seiten schon eingetroffen sind, und führt ggf. die }
  83. { angeforderten Aktionen aus. }
  84. VAR pg: ARRAY[0..4] OF p_onepage;
  85.     i,n: Integer;
  86.     schluss: Boolean;
  87. BEGIN
  88.   FOR i := 0 TO 4 DO
  89.     pg[i] := hunt_in_list($1F0+i,0,True);
  90.   { Anzahl ADIP-Seiten (ADditional Info Page) aus 1F0 ermitteln: }
  91.   IF (pg[0]<>Nil) AND (toprequest AND 4<>0) AND (adip_count=0) THEN BEGIN
  92.     i := 840; schluss := False;
  93.     REPEAT
  94.       CASE topcode[pg[0]^.chars[i]] OF { Magazinnummer }
  95.         14: { Don't Care } ;
  96.         15: schluss := True;
  97.         16: { ungültige Ziffer } ;
  98.         OTHERWISE IF topcode[pg[0]^.chars[i+7]]=2 THEN Inc(adip_count);
  99.       END;
  100.       i := i + 8;
  101.     UNTIL (i=960) OR schluss;
  102.     IF adip_count>3 THEN adip_count := 3; { Nee, so geht's ja auch nicht! }
  103.     IF adip_count<3 THEN BEGIN  { zuviele Seiten angefordert }
  104.       cancel_job($1f4);
  105.       IF adip_count<2 THEN cancel_job($1f3);
  106.       redraw_queue(-1);
  107.     END;
  108.   END;
  109.   { Blockseiten (d. h. Themenbereichs-Leitseiten) anfordern: }
  110.   IF (pg[0]<>Nil) AND (toprequest AND 1<>0) THEN BEGIN
  111.     busy_pointer; topgrab(pg[0]); normal_pointer;
  112.     short_msg('Blockseiten angefordert',0);
  113.     toprequest := toprequest AND NOT 1; topcleaner;
  114.   END;
  115.   { TOP-Statistik: }
  116.   IF (pg[0]<>Nil) AND (pg[1]<>Nil) AND (toprequest AND 2<>0) THEN BEGIN
  117.     busy_pointer; short_msg('erstelle TOP-Statistik ...',0);
  118.     topinfo(pg[0],pg[1]); short_msg('',0); normal_pointer;
  119.     mark_list(False); thispage := hunt_in_list($999,1,False);
  120.     mark_list(True); writepage(thispage,True);
  121.     toprequest := toprequest AND NOT 2; topcleaner;
  122.   END;
  123.   { TOP-Text-Menue: }
  124.   n := 0; FOR i := 1 TO adip_count DO IF pg[i+1]<>Nil THEN Inc(n);
  125.   IF (pg[0]<>Nil) AND (n=adip_count) AND (toprequest AND 4<>0) THEN BEGIN
  126.     busy_pointer; short_msg('erstelle TOP-Menüs ...',0);
  127.     create_topmenu(pg[0],pg[2],pg[3],pg[4]); short_msg('',0); normal_pointer;
  128.     thispage := hunt_in_list($900,0,False);
  129.     redraw_list; writepage(thispage,True);
  130.     toprequest := toprequest AND NOT 4; topcleaner;
  131.   END;
  132. END;
  133.  
  134. PROCEDURE write_checks;
  135. { Menuehäkchen an den Zustand der Programmvariablen anpassen }
  136. VAR i: Integer;
  137. BEGIN
  138.   checkme($020301,asciifile);
  139.   checkme($020302,NOT asciifile);
  140.   checkme($020400,withicon);
  141.   checkme($041200,fifo);
  142.   checkme($050100,(testing AND 1)<>0);
  143.   checkme($050300,(testing AND 2)<>0);
  144.   FOR i := 1 TO 3 DO
  145.     checkme($050600+i, tv_status=3-i);
  146.   FOR i := 1 TO 2 DO
  147.     checkme($050900+i, fontno=i);
  148.   checkme($060200,silentrexx);
  149. END;      
  150.  
  151. PROCEDURE handle_menu(code: Long);
  152. { *die* zentrale Ereignisverarbeitung, viele Mausklick- und Tastatur- }
  153. { Ereignisse lassen sich hierauf abbilden! }
  154. VAR item,subitem: Word;
  155.     i,j: Integer;
  156.     l: Long;
  157.     s: str80;
  158.     pg1,pg2: p_onepage;
  159.     save_fifo,ok,refresh: Boolean;
  160.     f: Text;
  161. BEGIN
  162.   menupicked := False;
  163.   item := code SHR 8;
  164.   subitem := code AND $FF;
  165.   CASE item OF
  166.     { *** Projekt *** }
  167.     $0101: say_hello(version);
  168.     $0102: helpme;
  169.     $0103: IF write_to_icon THEN short_msg('aktuelle Parameter gesichert',0)
  170.       ELSE short_msg('Fehler beim Schreiben der Parameter',2);
  171.     $0105: CASE privateer OF 
  172.         2: short_msg('Ein ARexx-Skript läuft noch!',0);
  173.         1: short_msg('PubScreen ist noch in Gebrauch!',0);
  174.         OTHERWISE stop := True;
  175.       END;
  176.     { *** Datei *** }
  177.     $0201: BEGIN { VT-Format laden }
  178.         sleep; IF fileselect('VT-Seiten laden',False,inputname) THEN
  179.           IF filetype(inputname)=1 THEN BEGIN
  180.             busy_pointer; s := IntStr(getpages(inputname,True));
  181.             short_msg(s+' Seiten gelesen',0); redraw_list; normal_pointer;
  182.             writepage(thispage,True);
  183.           END ELSE
  184.             short_msg('keine VT-Seitendatei, sorry',0);
  185.         wakeup;
  186.       END;
  187.     $0203: BEGIN { Ausgabeformat }
  188.         asciifile := subitem=$01;
  189.         fileinfo;
  190.       END;
  191.     $0204: BEGIN { Icons erzeugen }
  192.         withicon := has_check($020400);
  193.         fileinfo;
  194.       END;
  195.     $0206: BEGIN
  196.         CASE subitem OF
  197.           $01: BEGIN { Dateinamen ändern }
  198.               sleep;
  199.               IF fileselect('Ausgabedatei festlegen',True,outputname) THEN;
  200.               wakeup;
  201.             END;
  202.           $02: namefrompage(outputname,visblpage); { Namen aus Titelzeile }
  203.           $03: append_datestr(outputname,True);
  204.         END;
  205.         fileinfo;
  206.       END;
  207.     $0207: BEGIN
  208.         sleep;
  209.         IF ask_and_kill(outputname, True) THEN
  210.           short_msg('Ausgabedatei überschrieben',0);
  211.         wakeup;
  212.       END;
  213.     { *** Seiten *** }
  214.     $0301: writepage(visblpage,False); { Rätseltaste }
  215.     $0302: writepage(thispage,True); { Seite neu aufbauen }
  216.     $0303: BEGIN auto := True; uhrzeit(lastslide); END;  { Automatik }
  217.     $0304: BEGIN  { alle Seiten als "gesehen" markieren }
  218.         pg1 := root;
  219.         WHILE pg1<>Nil DO BEGIN
  220.           pg1^.dejavu := True; pg1 := pg1^.next;
  221.         END;
  222.         redraw_list;
  223.       END;
  224.     $0306: BEGIN { Text suchen }
  225.         sleep;
  226.         IF stringrequest('Suchbegriff eingeben:', searchstr) THEN BEGIN
  227.           busy_pointer;
  228.           IF NOT hunt(searchstr, root, True) THEN
  229.             short_msg('"'+searchstr+'" nicht gefunden', 0);
  230.           normal_pointer;
  231.         END;
  232.         wakeup;
  233.       END;
  234.     $0307: IF thispage<>Nil THEN BEGIN  { Weitersuchen }
  235.         sleep; busy_pointer;
  236.         IF NOT hunt(searchstr, thispage^.next, True) THEN
  237.           short_msg('"'+searchstr+'" nicht gefunden', 0);
  238.         normal_pointer; wakeup;
  239.       end;
  240.     $0309: BEGIN { Textausdruck }
  241.         IF incomplete THEN pg1 := thispage
  242.           ELSE pg1 := visblpage;
  243.         IF pg1<>Nil THEN BEGIN
  244.           sleep; busy_pointer;
  245.           short_msg('Seite wird gedruckt ... ',0);
  246.           IF printpage(pg1) THEN add_msg('OK.',0)
  247.           ELSE add_msg('Fehler!',2);
  248.           normal_pointer; wakeup;
  249.         END;
  250.       END;
  251.     $030A: BEGIN   { IFF-Bild }
  252.         sleep;
  253.         IF fileselect('IFF-Bild speichern',True,iffpicname) THEN BEGIN
  254.           IF filetype(iffpicname)<>-1 THEN BEGIN
  255.             s := iffpicname+' überschreiben?'
  256.             ok := ja_nein(s);
  257.           END ELSE
  258.             ok := True;
  259.           IF ok THEN BEGIN
  260.             { IFF-Bild mit Standard-Farbreihenfolge: }
  261.             make_colperms($01234567);
  262.             REPEAT writepage(visblpage, concealed); newevent := False;
  263.             UNTIL NOT incomplete;
  264.             short_msg('IFF-Bild ... ',0); busy_pointer;
  265.             IF iffdump(iffpicname, withicon) THEN add_msg('gespeichert',0)
  266.               ELSE add_msg('Dateifehler!',2);
  267.             normal_pointer;
  268.             make_colperms(colperm); writepage(visblpage, concealed);
  269.           END;
  270.         END;
  271.         wakeup;
  272.       END;
  273.     $030B: BEGIN  { Seite speichern }
  274.         sleep; { save_action enthält meist Rückfragen }
  275.         IF subitem=4 THEN
  276.           j := save_action(root, 3)
  277.         ELSE IF incomplete THEN
  278.           j := save_action(thispage, subitem)
  279.         ELSE
  280.           j := save_action(visblpage, subitem);
  281.         wakeup;
  282.       END;
  283.     $030C: BEGIN { Seite ins Clipboard }
  284.         IF incomplete THEN pg1 := thispage
  285.           ELSE pg1 := visblpage;
  286.         IF pg1<>Nil THEN BEGIN
  287.           page_to_clip(pg1);
  288.           short_msg('Seitentext als Clip gespeichert',0);
  289.         END;
  290.       END;
  291.     $030E: BEGIN { Seite löschen }
  292.         CASE subitem OF
  293.           $01: IF thispage<>Nil THEN BEGIN
  294.               del_from_list(thispage); update_list(thispage,-1);
  295.             END;
  296.           $02: IF thispage<>Nil THEN BEGIN
  297.               i := 0; j := thispage^.pg; pg1 := root;
  298.               WHILE pg1<>Nil DO BEGIN
  299.                 pg2 := pg1; pg1 := pg1^.Next;
  300.                 IF pg2^.pg=j THEN BEGIN
  301.                   del_from_list(pg2); Inc(i);
  302.                 END;
  303.               END;
  304.               update_list(thispage,-i);
  305.             END;
  306.           $03: BEGIN kill_list(thispage); redraw_list; END;
  307.           $04: BEGIN kill_list(root); redraw_list; END;
  308.           OTHERWISE;
  309.         END;
  310.         writepage(thispage,True);
  311.       END;
  312.     { *** Anfordern *** }
  313.     $0401: BEGIN { Seite 100 }
  314.         add_job('100',True); redraw_queue(-1);
  315.       END;
  316.     $0402: IF thispage<>Nil THEN BEGIN { diese Seite nochmal }
  317.         s := hexstr(thispage^.pg,3)+'/'+hexstr(thispage^.sp,1);
  318.         add_job(s,False); redraw_queue(-1);
  319.       END;
  320.     $0403: IF do_retry=0 THEN { die nicht gefundenen nochmal }
  321.         { bzw. wenn keine "nicht gefundenen" Seiten da sind, und wenn die } 
  322.         { aktuelle eine Mehrfachseite ist, annehmen, daß der Benutzer in }
  323.         { Wirklichkeit "diese mit allen Unterseiten nochmal" meint: }
  324.         IF (thispage<>Nil) AND (thispage^.sp>0) THEN BEGIN
  325.           cancel_job(thispage^.pg);
  326.           { falls man auch schon "f8" gedrückt hatte ... }
  327.           s := hexstr(thispage^.pg,3); add_job(s,False); redraw_queue(-1);
  328.         END;
  329.     $0404: BEGIN { Vorauswahl }
  330.         busy_pointer; getconfig(subitem); normal_pointer;
  331.       END;
  332.     $0405,$0406,$0407: BEGIN  { Stichprobe (gefiltert/erweitert) }
  333.         test(0);
  334.         i := (item - $0404) MOD 3;
  335.         CASE i OF
  336.           1: short_msg('Stichprobe läuft ...',0);
  337.           2: short_msg('gefilterte Stichprobe läuft ...',0);
  338.           0: short_msg('erweiterte Stichprobe läuft ...',0);
  339.         END;
  340.         busy_pointer; page_grabber(i); normal_pointer;
  341.       END;
  342.     $0408: IF subitem=2 THEN BEGIN { Sendernamen kopieren }
  343.         dump_title(visblpage); short_msg('Sendername als Clip gespeichert',0);
  344.       END ELSE IF root<>Nil THEN BEGIN { Seitennummern kopieren }
  345.         busy_pointer; dump_numbers; normal_pointer;
  346.         short_msg('Seitennummern als Clip gespeichert',0);
  347.       END;
  348.     $0409,$040A: BEGIN { Vorauswahl/Senderliste editieren }
  349.         short_msg('Editor-Aufruf ... ',0); sleep; busy_pointer;
  350.         IF item=$0409 THEN ok := ed_config(thispage)
  351.           ELSE ok := ed_stations;
  352.         IF ok THEN add_msg('abgeschlossen',0)
  353.           ELSE add_msg('DOS-Fehler',2);
  354.         normal_pointer; wakeup;
  355.       END;
  356.     $040C: IF subitem=$01 THEN BEGIN { TOP-Verzeichnis erstellen }
  357.         short_msg('TOP-Text-Seiten angefordert',0);
  358.         toprequest := toprequest OR 4; adip_count := 0;
  359.         hurricane;
  360.         save_fifo := fifo; fifo := False;
  361.         add_job('1f4',False); add_job('1f3',False); add_job('1f2',False);
  362.         add_job('1f0-1',False);
  363.         fifo := save_fifo;
  364.         redraw_queue(-1);
  365.       END ELSE BEGIN  { ... und löschen }
  366.         pg1 := visblpage; kill_topmenu; redraw_list;
  367.         IF thispage<>pg1 THEN writepage(thispage,True);
  368.       END;
  369.     $040D: BEGIN { TOP-Statistik }
  370.         short_msg('TOP-Seiten angefordert',0);
  371.         toprequest := toprequest OR 2;
  372.         save_fifo := fifo; fifo := False;
  373.         add_job('1f1',False); add_job('1f0-1',False);
  374.         fifo := save_fifo;
  375.         redraw_queue(-1);
  376.       END;
  377.     $040E: BEGIN { Blockseiten holen }
  378.         short_msg('TOP-Leitseite angefordert',0);
  379.         toprequest := toprequest OR 1;
  380.         save_fifo := fifo; fifo := False;
  381.         add_job('1f0-1',False);
  382.         fifo := save_fifo;
  383.         redraw_queue(-1);
  384.       END;
  385.     $0410: BEGIN  { Jobs löschen }
  386.         kill_queue; redraw_queue(-1);
  387.         toprequest := 0; topcleaner;
  388.       END;
  389.     $0411: BEGIN  { einen Job löschen }
  390.         j := thisjob; kill_job(thisjob);
  391.         IF j>=0 THEN  redraw_queue(j)  ELSE  redraw_queue(-1);
  392.       END;
  393.     $0412: BEGIN { FIFO }
  394.         fifo := has_check($041200); redraw_queue(-1);
  395.       END;
  396.     { *** Extras *** }
  397.     $0501: IF has_check($050100) THEN BEGIN  { Test/Uhr }
  398.         testing := testing OR 1;
  399.         test(testing OR $10);
  400.         IF i2c_status<>0 THEN guru(i2c_status);
  401.       END ELSE BEGIN
  402.         testing := testing AND NOT 1;
  403.         test(testing);
  404.       END;
  405.     $0502: IF (testing AND 1)<>0 THEN BEGIN  { VT-Zeit übernehmen }
  406.         sleep; { Uhrzeit umstellen kann 'Zeit kosten' }
  407.         gettime(s); force_time(s);
  408.         wakeup; short_msg('Systemzeit von VT übernommen',0);
  409.       END;
  410.     $0503: IF has_check($050300) THEN BEGIN  { Sendernamen zeigen }
  411.         testing := testing OR 2;
  412.       END ELSE BEGIN
  413.         testing := testing AND NOT 2;
  414.         test(testing);
  415.       END;
  416.     $0505: BEGIN { Decoder-Reset }
  417.         hurricane; init_CCT;
  418.         short_msg('Decoder-Reset ausgeführt',0); redraw_queue(-1);
  419.       END;
  420.     $0506: TV_display(3-subitem); { Fernsehdarstellung }
  421.     $0507: busmaster(NOT has_check($050700));
  422.     $0509: BEGIN { Fontgröße }
  423.         fontno := subitem; IF NOT newfontno THEN;
  424.         redraw_all; write_checks;
  425.       END;
  426.     { *** ARexx *** }
  427.     $0601: rexxhelp;
  428.     $0602: silentrexx := has_check($060200);
  429.     $0604..$060D: IF NOT rexxecute(item - $0603) THEN
  430.         short_msg('Skriptaufruf fehlgeschlagen!',0);
  431.     OTHERWISE;
  432.   END;
  433. END;
  434.  
  435. PROCEDURE handle_raw(code: Long);
  436. { für Sondertasten }
  437. VAR i: integer;
  438.     key: Byte;
  439.     pg1,pg2: p_onepage;
  440.     s: str80;
  441. VAR shift,ctrl,alt,comm: Boolean;
  442. BEGIN
  443.   key := (code SHR 16) AND $7F;
  444.   shift := (code AND $03)<>0; alt := (code AND $30)<>0;
  445.   ctrl := (code AND $08)<>0; comm := (code AND $80)<>0;
  446.   IF key=$5F THEN helpme;  { Help }
  447.   IF key IN [$50..$59] THEN  { *** F-Tasten ... }
  448.     IF NOT shift THEN CASE key OF  { ... normal }
  449.       $50: handle_menu($040100); { F1 }
  450.       $51: testpage;             { F2 }
  451.       $53: handle_menu($040D00); { F4 }
  452.       $54: handle_menu($040C01); { F5 }
  453.       $55: IF alt THEN handle_menu($040700)
  454.          ELSE
  455.            handle_menu($040500); { F6 }
  456.       $56: handle_menu($041000); { F7 }
  457.       $57: handle_menu($040200); { F8 }
  458.       $58: handle_menu($040900); { F9 }
  459.       $59: IF alt THEN
  460.            handle_menu($040403)
  461.          ELSE
  462.            handle_menu($040401); { F10 }
  463.       OTHERWISE short_msg('F'+IntStr(key-$4F)+': ???',0);
  464.     END ELSE CASE key OF  { ... geshiftet }
  465.       $53: handle_menu($040E00); { Shift-F4 }
  466.       $54: handle_menu($040C02); { Shift-F5 }
  467.       $55: handle_menu($040600); { Shift-F6 }
  468.       $56: handle_menu($041100); { Shift-F7 }
  469.       $57: handle_menu($040300); { Shift-F8 }
  470.       $58: handle_menu($040A00); { Shift-F9 }
  471.       $59: IF alt THEN
  472.            handle_menu($040404)
  473.          ELSE
  474.            handle_menu($040402); { Shift-F10 }
  475.       OTHERWISE short_msg('Shift-F'+IntStr(key-$4F)+': ???',0);
  476.     END;
  477.   IF (key IN [$4C..$4F]) AND (thispage<>Nil) THEN BEGIN { *** Cursor-Tasten }
  478.     mark_list(False);
  479.     CASE key OF
  480.       $4C: IF alt THEN
  481.           thispage := prev_magazine(thispage)
  482.         ELSE BEGIN
  483.           IF thispage^.prev<>Nil THEN thispage := thispage^.prev;
  484.           IF shift THEN
  485.             WHILE (thispage^.prev<>Nil) AND (thispage^.dejavu)
  486.             AND (thispage^.cbits AND PF_LOCAL=0) DO
  487.                thispage := thispage^.prev;
  488.           IF ctrl THEN
  489.             WHILE (thispage^.prev<>Nil) AND (thispage^.cbits AND PF_LOCAL=0) DO
  490.                thispage := thispage^.prev;
  491.         END;
  492.       $4D: IF alt THEN
  493.           thispage := next_magazine(thispage)
  494.         ELSE BEGIN
  495.           IF thispage^.next<>Nil THEN thispage := thispage^.next;
  496.           IF shift THEN
  497.             WHILE (thispage^.next<>Nil) AND (thispage^.dejavu)
  498.             AND (thispage^.cbits AND PF_LOCAL=0) DO
  499.                thispage := thispage^.next;
  500.           IF ctrl THEN
  501.             WHILE (thispage^.next<>Nil) AND (thispage^.cbits AND PF_LOCAL=0) DO
  502.                thispage := thispage^.next;
  503.         END;
  504.       $4E: IF shift OR alt THEN
  505.           WHILE thispage^.next<>Nil DO thispage := thispage^.next
  506.         ELSE
  507.           FOR i := 1 TO colht DO
  508.             IF thispage^.next<>Nil THEN thispage := thispage^.next;
  509.       $4F: IF shift OR alt THEN
  510.           thispage := root
  511.         ELSE
  512.           FOR i := 1 TO colht DO
  513.             IF thispage^.prev<>Nil THEN thispage := thispage^.prev;
  514.       OTHERWISE;
  515.     END;
  516.     mark_list(True); writepage(thispage,True);
  517.   END;
  518. END;
  519.  
  520. PROCEDURE handle_key(key: Char);
  521. { einzelne Eingabetaste untersuchen }
  522. VAR pg: p_onepage;
  523.     nr: Integer;
  524. BEGIN
  525.   taste := #0;
  526.   CASE key OF
  527.     '0'..'9','a'..'f','A'..'F','/','*','.','!':
  528.       IF Length(queue_input) < 8 THEN BEGIN
  529.         queue_input := queue_input + Upcase(key); queue_me;
  530.       END;
  531.     #8: IF Length(queue_input) > 0 THEN BEGIN
  532.         queue_input[Length(queue_input)] := #0; queue_me;
  533.       END;
  534.     #13: BEGIN
  535.         pg := Nil;
  536.         IF (Length(queue_input)=3) THEN BEGIN { Sprungbefehl? }
  537.           nr := hexval(queue_input); pg := hunt_in_list(nr,0,False);
  538.           IF pg<>Nil THEN IF pg^.pg<>nr THEN pg := Nil;
  539.           IF thispage<>Nil THEN IF thispage^.pg=nr THEN pg := Nil;
  540.         END;
  541.         IF pg<>Nil THEN BEGIN  { Seite nur anspringen }
  542.           queue_input := ''; queue_me;
  543.           push(thispage);
  544.           mark_list(False); thispage := pg; mark_list(True);
  545.           writepage(thispage,True);
  546.         END ELSE BEGIN    { Seite (neu) anfordern }
  547.           add_job(queue_input,True);
  548.           queue_input := ''; redraw_queue(-1);
  549.         END;
  550.       END;
  551.     '+','-': BEGIN    { Warteschlange blättern }
  552.         mark_queue(False);
  553.         IF key='-' THEN Inc(thisjob) ELSE Dec(thisjob);
  554.         IF thisjob<-queued THEN thisjob := -queued;
  555.         IF thisjob>=maxactive-1 THEN thisjob := maxactive-1;
  556.         mark_queue(True);
  557.         IF thisjob>=0 THEN
  558.           display_select(thisjob);
  559.       END;
  560.     'h','H': handle_menu($030700);
  561.     'i','I': BEGIN withicon := NOT withicon; write_checks; fileinfo; END;
  562.     'n','N': BEGIN checkme($050300, (testing AND 2)=0); handle_menu($050300); END;
  563.     #14: handle_menu($020602); { Ctrl-N }
  564.     'r','R': handle_menu($050500);
  565.     's': handle_menu($030B01);
  566.     'S': handle_menu($030B02);
  567.     #19: handle_menu($030B03); { Ctrl-S }
  568.     't','T': BEGIN checkme($050100, (testing AND 1)=0); handle_menu($050100); END;
  569.     ' ': writepage(thispage,True);
  570.     '?': writepage(visblpage,False);
  571.     #27: BEGIN { Esc: Rücksprung }
  572.         pg := pop; IF pg<>Nil THEN BEGIN
  573.           mark_list(False); thispage := pg;
  574.           mark_list(True); writepage(thispage,True);
  575.         END;
  576.       END;
  577.     #127: BEGIN { Del: erst noch die Qualifier abfragen }
  578.         IF (rawcode AND $30)<>0 THEN handle_menu($030E04) { Alt }
  579.         ELSE IF (rawcode AND $08)<>0 THEN handle_menu($030E03) { Ctrl }
  580.         ELSE IF (rawcode AND $03)<>0 THEN handle_menu($030E02) { Shift }
  581.         ELSE handle_menu($030E01);
  582.       END;
  583.     {'z': testpage;}
  584.     #155: handle_raw(rawcode);
  585.     OTHERWISE BEGIN
  586.         IF key>' ' THEN short_msg(key+'?',0)
  587.         ELSE short_msg('Ctrl-'+Chr(Ord(key)+64)+'?',0);
  588.         Delay(20); short_msg('',0);
  589.       END;
  590.   END;
  591. END;
  592.  
  593. PROCEDURE handle_click;
  594. { angeklickte Seitennummern aufsuchen/anfordern }
  595. VAR nr,max,j: Integer;
  596.     pg: p_onepage;
  597.     code: Char;
  598. BEGIN
  599.   mouseclicked := False;
  600.   nr := number_from_page(clickedx,clickedy);
  601.   IF nr>=0 THEN BEGIN   { Nummer in einer Seite angeklickt }
  602.     pg := hunt_in_list(nr,0,False);
  603.     IF pg<>Nil THEN IF pg^.pg<>nr THEN pg := Nil;
  604.     IF thispage<>Nil THEN IF thispage^.pg=nr THEN pg := Nil;
  605.     IF pg<>Nil THEN BEGIN  { Seite nur anspringen }
  606.       push(thispage);
  607.       mark_list(False); thispage := pg; mark_list(True);
  608.       writepage(thispage,True);
  609.     END ELSE IF nr IN [$100..$899] THEN BEGIN    { Seite (neu) anfordern }
  610.       nr := get_bcd(nr); max := nr;
  611.       IF dblclicked THEN BEGIN
  612.         max := number_from_page(clickedx+4,clickedy);
  613.         IF max<0 THEN max := nr + 3 ELSE max := get_bcd(max);
  614.         IF max<nr THEN max := nr;
  615.         IF (max DIV 100)>(nr DIV 100) THEN max := 100*(nr DIV 100 + 1)-1;
  616.       END;
  617.       FOR j := nr TO max DO
  618.         add_job(IntStr(j),False);
  619.       redraw_queue(-1);
  620.     END;
  621.     Exit;
  622.   END;
  623.   pg := page_from_list(clickedx,clickedy);
  624.   IF pg<>Nil THEN BEGIN
  625.     IF thispage<>pg THEN BEGIN
  626.       mark_list(False); thispage := pg; mark_list(True);
  627.     END ELSE IF dblclicked THEN BEGIN
  628.       del_from_list(thispage); update_list(thispage,-1);
  629.     END;
  630.     writepage(thispage,True);
  631.     Exit;
  632.   END;
  633.   nr := pos_from_queue(clickedx,clickedy);
  634.   IF nr<maxactive THEN BEGIN
  635.     IF thisjob<>nr THEN BEGIN
  636.       mark_queue(False); thisjob := nr; mark_queue(True);
  637.     END ELSE IF dblclicked THEN
  638.       handle_menu($041100);
  639.     Exit;
  640.   END;
  641.   code := click_action(clickedx,clickedy);
  642.   CASE code OF
  643.     'N': handle_menu($020601);
  644.     '+': handle_raw($4D0000);
  645.     '0': handle_key(#27);
  646.     '-': handle_raw($4C0000);
  647.     'F': BEGIN asciifile := NOT asciifile; write_checks; fileinfo; END;
  648.     'I': BEGIN withicon  := NOT withicon;  write_checks; fileinfo; END;
  649.     'J': BEGIN fifo := NOT fifo; write_checks; redraw_queue(-1); END;
  650.     'K': IF dblclicked THEN BEGIN
  651.         kill_list(root); redraw_list;
  652.       END ELSE
  653.         short_msg('He, sachte da!',0);
  654.     'T': BEGIN
  655.         checkme($050100, (testing AND 1)=0); handle_menu($050100);
  656.         IF dblclicked THEN BEGIN
  657.           checkme($050300, (testing AND 2)=0); handle_menu($050300);
  658.         END;
  659.       END;
  660.     'S': BEGIN
  661.         kill_queue;
  662.         IF dblclicked THEN getconfig(1);
  663.         redraw_queue(-1);
  664.       END;
  665.     'L': IF thispage=root THEN handle_raw($4E0001)
  666.         ELSE handle_raw($4F0001);
  667.     OTHERWISE;
  668.   END;
  669. END;
  670.  
  671. PROCEDURE handle_rexx;
  672. { ARexx-Kommandostring auswerten und beantworten }
  673. VAR k: rxkeyid;
  674.     i,j,pg,sp,result: Integer;
  675.     l: Long;
  676.     s,s2: str80;
  677.     pg1,pg2: p_onepage;
  678.     redraw: Boolean;
  679.     c: Char;
  680. BEGIN
  681.   i := 1; WHILE rexxzeile[i]>' ' DO BEGIN
  682.     s[i] := UpCase(rexxzeile[i]); Inc(i);
  683.   END; s[i] := #0;
  684.   WHILE rexxzeile[i] IN [#1..' '] DO Inc(i);
  685.   j := i; WHILE rexxzeile[j]<>#0 DO Inc(j);
  686.   k := scn; WHILE (k<nul) AND (s<>rxkeys[k]) DO Inc(k);
  687.   CASE k OF
  688.     scn: BEGIN rexxreply(0,'');
  689.         CASE UpCase(rexxzeile[i]) OF
  690.           'A': handle_menu($040700);    { 'all' }
  691.           'S': handle_menu($040600);    { 'selected' }
  692.           OTHERWISE handle_menu($040500);
  693.         END;
  694.       END;
  695.     top: BEGIN handle_menu($040C01); rexxreply(0,''); END;
  696.     tos: BEGIN handle_menu($040D00); rexxreply(0,''); END;
  697.     aut: BEGIN handle_menu($040E00); rexxreply(0,''); END;
  698.     tok: BEGIN handle_menu($040C02); rexxreply(0,''); END;
  699.     fif: BEGIN fifo := True; write_checks; redraw_queue(-1); rexxreply(0,''); END;
  700.     lif: BEGIN fifo := False; write_checks; redraw_queue(-1); rexxreply(0,''); END;
  701.     can: BEGIN handle_menu($041000); rexxreply(0,''); END;
  702.     rty: IF do_retry>0 THEN rexxreply(0,'') ELSE rexxreply(5,'');
  703.     clf: IF ask_and_kill(outputname, False) THEN rexxreply(0,'')
  704.            ELSE rexxreply(10,'');
  705.     l2c: BEGIN handle_menu($040801); rexxreply(0,''); END;
  706.     p2c: BEGIN handle_menu($030C00); rexxreply(0,''); END;
  707.     s2f: BEGIN showscreen(1); rexxreply(0,''); END;
  708.     s2b: BEGIN showscreen(-1); rexxreply(0,''); END;
  709.     scl: BEGIN sleep; gettime(s); force_time(s); wakeup; rexxreply(0,''); END;
  710.     snp: BEGIN if write_to_icon THEN rexxreply(0,'') ELSE rexxreply(10,''); END;
  711.     qit: IF privateer=0 THEN BEGIN stop := True; rexxreply(0,''); END
  712.       ELSE rexxreply(10,'');
  713.     pre: BEGIN
  714.         busy_pointer;
  715.         IF rexxzeile[i] IN ['1'..'9'] THEN
  716.           getconfig(Ord(rexxzeile[i])-Ord('0')) ELSE getconfig(1);
  717.         normal_pointer; rexxreply(0,'');
  718.       END;
  719.     enq: BEGIN
  720.         add_job(Copy(rexxzeile,i,j-i),True); redraw_queue(-1); rexxreply(0,'');
  721.       END;
  722.     dsp: BEGIN
  723.         pg1 := root;
  724.         IF (UpCase(rexxzeile[i])='N') AND (thispage<>Nil) THEN
  725.           pg1 := thispage^.next;
  726.         IF rexxzeile[i] IN ['0'..'9'] THEN BEGIN
  727.           pgstr2numbers(Copy(rexxzeile,i,j-i), pg, sp);
  728.           IF sp<=0 THEN BEGIN
  729.             pg1 := hunt_in_list(pg,0,False);
  730.             IF pg1<>Nil THEN IF pg1^.pg<>pg THEN pg1 := Nil;
  731.           END ELSE
  732.             pg1 := hunt_in_list(pg,sp,True);
  733.         END;
  734.         IF pg1<>Nil THEN BEGIN
  735.           mark_list(False); thispage := pg1; mark_list(True);
  736.           writepage(thispage,True); rexxreply(0,'');
  737.         END ELSE
  738.           rexxreply(5,'');
  739.       END;    
  740.     hnt: BEGIN
  741.         result := 5;
  742.         IF j>i THEN BEGIN                                  
  743.           searchstr := Copy(rexxzeile,i,j-i);
  744.           busy_pointer;
  745.           IF hunt(searchstr, root, False) THEN result := 0;
  746.           normal_pointer;
  747.         END ELSE IF thispage<>Nil THEN BEGIN
  748.           busy_pointer;
  749.           IF hunt(searchstr, thispage^.next, False) THEN result := 0;
  750.           normal_pointer;
  751.         END;
  752.         rexxreply(result,'');
  753.       END;
  754.     kil: IF UpCase(rexxzeile[i]) IN ['0'..'9','T'] THEN BEGIN
  755.         redraw := False;
  756.         IF (UpCase(rexxzeile[i])='T') AND (thispage<>Nil) THEN BEGIN
  757.           pg := thispage^.pg; sp := thispage^.sp;
  758.         END ELSE
  759.           pgstr2numbers(Copy(rexxzeile,i,j-i), pg, sp);
  760.         pg1 := root;
  761.         WHILE pg1<>Nil DO BEGIN
  762.           pg2 := pg1; pg1 := pg1^.next;
  763.           IF (pg2^.pg=pg) AND ((pg2^.sp=sp) OR (sp<=0)) THEN BEGIN
  764.             IF pg1=Nil THEN pg1 := pg2^.prev;
  765.             IF pg2=thispage THEN redraw := True;
  766.             del_from_list(pg2); pg2 := Nil;
  767.             IF pg1<>Nil THEN update_list(pg1,-1);
  768.           END;
  769.         END;
  770.         IF pg2<>Nil THEN update_list(pg2,0);  { Listenende neu zeichnen }
  771.         IF redraw THEN BEGIN mark_list(True); writepage(thispage,True); END;
  772.         rexxreply(0,'');
  773.       END ELSE BEGIN
  774.         kill_list(root); redraw_list; rexxreply(0,'');
  775.       END;
  776.     sav: BEGIN
  777.         IF rexxzeile[i] IN ['0'..'9'] THEN BEGIN
  778.           pgstr2numbers(Copy(rexxzeile,i,j-i), pg, sp);
  779.           IF sp>0 THEN BEGIN
  780.             j := 1; pg1 := hunt_in_list(pg,sp,True);
  781.           END ELSE BEGIN
  782.             j := 2; pg1 := hunt_in_list(pg,0,False);
  783.             IF pg1<>Nil THEN IF pg1^.pg<>pg THEN pg1 := Nil;
  784.           END;
  785.         END ELSE IF UpCase(rexxzeile[i])='T' THEN BEGIN
  786.           j := 1; pg1 := visblpage
  787.         END ELSE BEGIN
  788.           j := 4; pg1 := root;
  789.         END;
  790.         sleep;
  791.         IF pg1=Nil THEN rexxreply(5,'')
  792.         ELSE IF save_action(pg1,j)=0 THEN rexxreply(0,'')
  793.         ELSE rexxreply(10,'');
  794.         wakeup;
  795.       END;
  796.     fnm: BEGIN
  797.         s := outputname;
  798.         outputname := Copy(rexxzeile,i,j-i); fileinfo; rexxreply(0, s);
  799.       END;
  800.     fmd: BEGIN
  801.         IF asciifile THEN s := 'ASCII' ELSE s := 'VT';
  802.         CASE UpCase(rexxzeile[i]) OF
  803.           'A': BEGIN asciifile := True; fileinfo; rexxreply(0, s); END;
  804.           'V': BEGIN asciifile := False; fileinfo; rexxreply(0, s); END;
  805.           OTHERWISE rexxreply(20,'');
  806.         END;
  807.       END;
  808.     ics: BEGIN
  809.         withicon := UpCase(rexxzeile[i+1])<>'F'; fileinfo; rexxreply(0,'');
  810.       END;
  811.     ifd: BEGIN
  812.         iffpicname := Copy(rexxzeile,i,j-i);
  813.         { schwarzen Hintergrund erzwingen: }
  814.         make_colperms($01234567);
  815.         REPEAT writepage(visblpage,concealed); newevent := False;
  816.         UNTIL NOT incomplete;
  817.         busy_pointer;
  818.         IF iffdump(iffpicname, withicon) THEN rexxreply(0,'') 
  819.           ELSE rexxreply(10,'');
  820.         normal_pointer;
  821.         make_colperms(colperm); writepage(visblpage,concealed);
  822.       END;
  823.     loa: BEGIN
  824.         inputname := Copy(rexxzeile,i,j-i);
  825.         IF filetype(inputname)=1 THEN BEGIN
  826.           sleep; busy_pointer; IF getpages(inputname,True)=0 THEN;
  827.           normal_pointer; wakeup;
  828.           redraw_list; writepage(thispage,True);
  829.           rexxreply(0,'');
  830.         END ELSE
  831.           rexxreply(10,'');
  832.       END;
  833.     laq: BEGIN
  834.         i := queued+active; s := IntStr(i); IF i>0 THEN i := 5; rexxreply(i,s);
  835.       END;
  836.     gst: BEGIN
  837.         c := UpCase(rexxzeile[i]);
  838.         IF c IN ['L','R'] THEN BEGIN
  839.           l := VTstat;
  840.           IF (l AND 3)=3 THEN BEGIN     { Normalfall: Empfang OK }
  841.             gethead(s);
  842.             IF c='L' THEN BEGIN  { 'live' }
  843.               name2dosname(s,s2); s := s2;
  844.             END;  { sonst: 'raw' }
  845.             rexxreply(0,s);
  846.           END ELSE IF (l AND 1)=0 THEN 
  847.             rexxreply(6,'')    { überhaupt kein Empfang --> RC=6 }
  848.           ELSE
  849.             rexxreply(5,'');   { Sender ohne VT --> RC=5 }
  850.         END ELSE BEGIN
  851.           IF thispage=Nil THEN
  852.             rexxreply(5,'')
  853.           ELSE BEGIN
  854.             namefrompage(s, thispage); rexxreply(0,s);
  855.           END;
  856.         END;
  857.       END;
  858.     gpn,gpi: IF thispage=Nil THEN
  859.         rexxreply(5,'')
  860.       ELSE BEGIN
  861.         s := hexstr(thispage^.pg,3);
  862.         IF k=gpi THEN s := s + hexstr(thispage^.sp,4);
  863.         rexxreply(0,s);
  864.       END;
  865.     OTHERWISE rexxreply(20,'');
  866.   END;
  867. END;
  868.  
  869. PROCEDURE slideshow;
  870. VAR jetzt: zeiteintrag;
  871. BEGIN
  872.   IF thispage=Nil THEN
  873.     auto := False
  874.   ELSE IF thispage^.next=Nil THEN
  875.     auto := False
  876.   ELSE BEGIN
  877.     uhrzeit(jetzt);
  878.     IF diff_time(lastslide,jetzt)>50*autotimer THEN BEGIN
  879.       mark_list(False); thispage := thispage^.next; mark_list(True);
  880.       lastslide := jetzt; writepage(thispage, True);
  881.     END;
  882.   END;
  883. END;
  884.  
  885. VAR speak: Text;
  886.  
  887. BEGIN  { Hauptprogramm }
  888.   { Eine Menge Variablen werden bereits in den Units, wo sie auch deklariert }
  889.   { sind, initialisiert. }
  890.   get_args; inputname := outputname; iffpicname := outputname;
  891.   searchstr := '';
  892.   stop := False; auto := listsize>0; thispage := root;
  893.   AddExitServer(sysclean); sysinit(version);
  894.   write_checks;
  895.   roundrobin := 0; toprequest := 0; adip_count := 0;
  896.   stackbot := 1; stackptr := stackbot;
  897.   init_CCT; { SAA 5246 initialisieren }
  898.   redraw_all; IF thispage=Nil THEN say_hello(version);
  899.   REPEAT
  900.     IF NOT newevent THEN event_scan(True);
  901.     IF newevent THEN BEGIN
  902.       newevent := False; short_msg('',0); auto := False;
  903.       IF taste<>#0 THEN handle_key(taste);
  904.       IF mouseclicked THEN handle_click;
  905.       IF menupicked THEN handle_menu(menucode);
  906.       IF rexxzeile<>'' THEN handle_rexx;
  907.     END ELSE IF (testing<>0) OR incomplete OR (visblpage=Nil) OR auto OR
  908.       (toprequest+queued+active>0) THEN BEGIN
  909.       Delay(5);  { Multitasking-freundlich, wir haben Zeit ... }
  910.       IF testing<>0 THEN test(testing OR $10);
  911.       IF visblpage=Nil THEN say_hello(version)
  912.         ELSE IF incomplete THEN writepage(visblpage,True);
  913.       IF auto THEN slideshow;
  914.       IF toprequest>0 THEN topscan;
  915.       searching := queued+active>0;
  916.       IF queued>0 THEN handle_queue;
  917.       IF active>0 THEN BEGIN
  918.         handle_jobs;
  919.         attempt_input(roundrobin);
  920.         roundrobin := (roundrobin+1) MOD maxactive;
  921.       END;
  922.       IF searching AND (queued+active=0) AND (speech<>'') THEN BEGIN { "Fertig!" }
  923.         Rewrite(speak,'SPEAK:'); IF IOResult=0 THEN BEGIN
  924.           Write(speak,speech+' '); Close(speak);
  925.         END;
  926.       END;
  927.     END ELSE   { nichts mehr zu tun :-) }
  928.       l := Wait(-1);
  929.     IF (i2c_status<>0) AND (testing AND 1=0) THEN BEGIN
  930.       testing := testing OR 1; test(testing OR $10);
  931.       guru(i2c_status);
  932.     END;
  933.   UNTIL stop;
  934.   SetStdIO(Nil); CloseConsole(Con);
  935.   kill_list(root); sysclean;
  936. END.
  937.  
  938.