home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / das_buch / dos / showvect.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-05-13  |  20.3 KB  |  412 lines

  1. {$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X-,M 16384,0,0}
  2. (*===================================================================*)
  3. (*                     SHOWVECT.PAS Version 1.0                      *)
  4. (*                 Copyright (C) 1993 te-wi Verlag                   *)
  5. (*-------------------------------------------------------------------*)
  6. (* Das Programm zeigt die Liste der Interruptvektoren mit Kommentar  *)
  7. (* auf dem Bildschirm an. Die Liste kann zusätzlich auch in eine     *)
  8. (* Datei »SHOWVECT.OUT« geschrieben und ausgedruckt werden (LPT1).   *)
  9. (*-------------------------------------------------------------------*)
  10. (* Achtung:                                                          *)
  11. (* Wenn das Programm aus der IDE von Turbo/Borland Pascal aufgerufen *)
  12. (* wird, werden nicht die Originalvektoren, sondern die vom Compiler *)
  13. (* umgebogenen Vektoren angezeigt!                                   *)
  14. (* Das Programm kann sowohl im Protected- als auch im Real-Mode com- *)
  15. (* piliert und gestartet werden, im DMPI werden allerdings nicht die *)
  16. (* Interruptvektoren sondern die Descriptoren angezeigt.             *)
  17. (*===================================================================*)
  18.  
  19. PROGRAM ShowVectors;
  20.  
  21. USES
  22.   Crt, Dos, Hex, Cursor, Printer;
  23.  
  24. VAR
  25.   VecTab : ARRAY[0..$FF] OF STRING[77];
  26.  
  27. CONST
  28.   UpperLine: STRING[77] = #32#32#32#218#196'[Adresse]'#196#194'[I]'   +
  29.              #194#196#196#196#196#196'[Bezeichnung]'#196#196#196#196  +
  30.              #196#194#196#196#196#196#196#196#196#196#196'[Beschreib' +
  31.              'ung]'#196#196#196#196#196#196#196#196#196#191;
  32.   Lowerline: STRING[77] = #32#32#32#192#196#196#196#196#196#196#196   +
  33.              #196#196#196#196#193#196#196#196#193#196#196#196#196#196 +
  34.              #196#196#196#196#196#196#196#196#196#196#196#196#196#196 +
  35.              #196#196#196#196#193#196#196#196#196#196#196#196#196#196 +
  36.              #196#196#196#196#196#196#196#196#196#196#196#196#196#196 +
  37.              #196#196#196#196#196#196#196#196#196#217;
  38.   InfoLine   : STRING[61] = '                 » Show Vectors v1.01 ' +
  39.              '(C) 1993 te-wi Verlag «';
  40.   StatusLine : STRING[78] = '['#24#25'][PgUp][PgDn][End][Home]' +
  41.              ' [$]XX [S]peichern [D]rucken  [F1]=Hilfe [ESC]=Ende';
  42.   HelpLine   : STRING[39] = 'Zurück zur Tabelle mit beliebiger Taste';
  43.  
  44. PROCEDURE Init;
  45. VAR
  46.   Vectors: ARRAY[0..$FF] OF POINTER;  { Zeiger auf alle Intr-Vektoren }
  47.   i      : BYTE;                                     { Zählervariable }
  48. BEGIN
  49.   (* Alle Interruptvektoren in einem Array vom Typ LogRec holen:     *)
  50.   SwapVectors;                          (* nicht die programmeigenen *)
  51.   FOR i := 0 TO $FF DO GetIntVec(i, Vectors[i]);   (* Vektoren holen *)
  52.   SwapVectors;                              (* Vektoren restaurieren *)
  53.   (* Die Tabelle mit den Bezeichnungen und Erklärungen aufbauen:     *)
  54.   VecTab[$00] := 'DIVIDE ERROR           '
  55.                + #179'Division durch Null             ';
  56.   VecTab[$01] := 'SINGLE STEP            '
  57.                + #179'Debugger-Einzelschritt-Mode     ';
  58.   VecTab[$02] := 'NON MASKABLE INTERRUPT '
  59.                + #179'Nicht maskierbarer Interrupt NMI';
  60.   VecTab[$03] := 'ONE-BYTE-INTERR.       '
  61.                + #179'Breakpoint                      ';
  62.   VecTab[$04] := 'OVERFLOW               '
  63.                + #179'Überlauf der internen Hardware  ';
  64.   VecTab[$05] := 'PRINT SCREEN KEY       '
  65.                + #179'Start bei Druck auf [PrtScr]    ';
  66.   VecTab[$06] := 'UNDEFINED OPCODE       '
  67.                + #179'ab 80286                        ';
  68.   VecTab[$07] := 'NO MATH UNIT AVAILABLE '
  69.                + #179'ab 80286 für die NPX-Emulation  ';
  70.   VecTab[$08] := 'IRQ0 TIMER INTERRUPT   '
  71.                + #179'Zeitgenerator-Hardware-Interrupt';
  72.   VecTab[$09] := 'IRQ1 KEYBOARD INTERRUPT'
  73.                + #179'Tastatur-Hardware-Interrupt     ';
  74.   VecTab[$0A] := 'IRQ2 EGA VERT. RETRACE '
  75.                + #179'Vertical-Retrace-Signal bei EGA ';
  76.   VecTab[$0B] := 'IRQ3 COM2              '
  77.                + #179'Serielle Schnittstelle 2        ';
  78.   VecTab[$0C] := 'IRQ4 COM1              '
  79.                + #179'Serielle Schnittstelle 1        ';
  80.   VecTab[$0D] := 'IRQ5 FIXED DISK        '
  81.                + #179'Festplatte bei XT, bei AT LPT2  ';
  82.   VecTab[$0E] := 'IRQ6 DISKETTE          '
  83.                + #179'Disketten-Hardware-Interrupt    ';
  84.   VecTab[$0F] := 'IRQ7 PRINTER           '
  85.                + #179'Drucker-Hardware-Interrupt LPT1 ';
  86.   VecTab[$10] := 'VIDEO                  '
  87.                + #179'BIOS-Bildschirminterrupt        ';
  88.   VecTab[$11] := 'EQUIPMENT DETERMINATION'
  89.                + #179'Ermittlung der PC-Konfiguration ';
  90.   VecTab[$12] := 'MEMORY SIZE            '
  91.                + #179'Größe des Arbeitsspeichers      ';
  92.   VecTab[$13] := 'DISK                   '
  93.                + #179'Disketten-/Festplatten-Interrupt';
  94.   VecTab[$14] := 'SERIAL I/O             '
  95.                + #179'Serielle Ein-/Ausgabe über BIOS ';
  96.   VecTab[$15] := 'CASSETTE/AT-FUNCTIONS  '
  97.                + #179'Kassetten-Interr./AT-Funktionen ';
  98.   VecTab[$16] := 'KEYBOARD               '
  99.                + #179'BIOS-Tastatur-Interrupt         ';
  100.   VecTab[$17] := 'PRINTER                '
  101.                + #179'Drucker-BIOS-Interrupt          ';
  102.   VecTab[$18] := 'TRANSFER TO ROM BASIC  '
  103.                + #179'Sprung ins BASICA (IBM)         ';
  104.   VecTab[$19] := 'DISK BOOT              '
  105.                + #179'System-Start (IBM)              ';
  106.   VecTab[$1A] := 'CLOCK                  '
  107.                + #179'BIOS-Timer-Interrupt            ';
  108.   VecTab[$1B] := 'CTRL BREAK KEY         '
  109.                + #179'BIOS [Ctrl]+[Break]-Routine     ';
  110.   VecTab[$1C] := 'CLOCK TICK             '
  111.                + #179'Timer-Zusatzroutine (IBM)       ';
  112.   VecTab[$1D] := '6845 VIDEO INIT TABLE  '
  113.                + #179'Video-Tabelle                   ';
  114.   VecTab[$1E] := 'DISKETTE PARAMS TABLE  '
  115.                + #179'Disketten-Parameter-Tabelle     ';
  116.   VecTab[$1F] := 'GRAPHICS SET 2         '
  117.                + #179'BIOS-Grafikzeichensatz-Tabelle  ';
  118.   VecTab[$20] := 'PROGAM TERMINATION     '
  119.                + #179'Programmende (bei COM-Programm) ';
  120.   VecTab[$21] := 'DOS INTERRUPT          '
  121.                + #179'DOS-Standard-Interrupt          ';
  122.   VecTab[$22] := 'TERMINATE ADDRESS      '
  123.                + #179'Abbruch, nie direkt verwenden!  ';
  124.   VecTab[$23] := 'CONTROL C EXIT ADDRESS '
  125.                + #179'[CTRL]+[C]-Abbruchadresse       ';
  126.   VecTab[$24] := 'FATAL ERROR HANDLER    '
  127.                + #179'Behandlung kritischer DOS-Fehler';
  128.   VecTab[$25] := 'ABSOLUTE DISK READ     '
  129.                + #179'Direktes Lesen von Datenträger  ';
  130.   VecTab[$26] := 'ABSOLUTE DISK WRITE    '
  131.                + #179'Direktes Schreiben von Datentr. ';
  132.   VecTab[$27] := 'TSR                    '
  133.                + #179'Beenden und im Speicher halten  ';
  134.   VecTab[$28] := 'KEYBOARD BUSY LOOP     '
  135.                + #179'DOS-internes Flag               ';
  136.   VecTab[$29] := 'FAST PUTCHAR           '
  137.                + #179'DOS-interne Routine             ';
  138.   VecTab[$2A] := 'MICROSOFT NETWORKS     '
  139.                + #179'Microsoft-Netzwerk-Routinen     ';
  140.   FOR i := $2B TO $2D DO
  141.     VecTab[i] := 'INTERNAL               '
  142.                + #179'DOS-interne Routine             ';
  143.   VecTab[$2E] := 'EXECUTE - INTERNAL     '
  144.                + #179'DOS-interne Routine             ';
  145.   VecTab[$2F] := 'MULTIPLEX              '
  146.                + #179'DOS-Multiplexer-Interrupt       ';
  147. {$IFDEF DPMI}
  148.   VecTab[$30] := 'BORLAND DPMI-INTERFACE '
  149.                + #179'CP/M-Funkt. / auch Borland DPMI ';
  150. {$ELSE}
  151.   VecTab[$30] := 'FAR JUMP TO CP/M CALL  '
  152.                + #179'CP/M-Funkt. / auch Borland DPMI ';
  153. {$ENDIF}
  154.   VecTab[$31] := 'FAR JUMP TO CP/M CALL  '
  155.                + #179'Zeiger auf CP/M-kompat. Aufruf  ';
  156.   VecTab[$32] := 'RESERVED               '
  157.                + #179'Für DOS reserviert              ';
  158.   VecTab[$33] := 'MS MOUSE               '
  159.                + #179'Microsoft-Mausinterface         ';
  160.   FOR i := $34 TO $3E DO
  161.     VecTab[i] := 'FLOATING POINT EMULATN.'
  162.                + #179'Fließkomma-Emulations-Routine   ';
  163.   VecTab[$3F] := 'MICROSOFT DLL MANAGER  '
  164.                + #179'Microsoft DLL-Manager           ';
  165.   VecTab[$40] := 'HARD DISK              '
  166.                + #179'relozierter BIOS-Floppy-Handler ';
  167.   VecTab[$41] := 'FIXED DISK PARAMETERS  '
  168.                + #179'reloz. BIOS-Festplattenparameter';
  169.   VecTab[$42] := 'RELOCATED VIDEO HANDLER'
  170.                + #179'Umgebogener BIOS-Video-Handler  ';
  171.   VecTab[$43] := 'USER FONT TABLE        '
  172.                + #179'EGA/VGA-Fonttabellen            ';
  173.   VecTab[$44] := 'NOVELL NETWARE         '
  174.                + #179'High-Level-Sprachen API         ';
  175.   FOR i := $45 TO $60 DO
  176.     VecTab[i] := 'RESERVED               '
  177.                + #179'reserviert                      ';
  178.   VecTab[$46] := '2 FIXED DISK PARAMETERS'
  179.                + #179'siehe INT 41h                   ';
  180.   VecTab[$4A] := 'AT USER ALARM          '
  181.                + #179'RTC Alarmschnittstelle zum BIOS ';
  182.   FOR i := $61 TO $66 DO
  183.     VecTab[i] := 'RESERVED FOR USER INTR.'
  184.                + #179'für Applikationen reserviert    ';
  185.   VecTab[$67] := 'EMM                    '
  186.                + #179'EMS-Manager                     ';
  187.   FOR i := $68 TO $6C DO
  188.     VecTab[i] := 'UNUSED                 '
  189.                + #179'normalerweise unbenutzt         ';
  190.   VecTab[$6D] := 'VGA INTERNAL           '
  191.                + #179'von versch. VGA-Karten verwendet';
  192.   VecTab[$6E] := 'UNUSED                 '
  193.                + #179'unbenutzt                       ';
  194.   VecTab[$6F] := 'NOVELL NETBIOS         '
  195.                + #179'Novell-Netzwerk                 ';
  196.   VecTab[$70] := 'IRQ8 REAL TIME CLOCK   '
  197.                + #179'AT Echtzeit-Uhr                 ';
  198.   VecTab[$71] := 'IRQ9 LAN ADAPTER 1     '
  199.                + #179'Netzwerk-Adapter 1              ';
  200.   VecTab[$72] := 'IRQ10 RESERVED         '
  201.                + #179'reserviert                      ';
  202.   VecTab[$73] := 'IRQ11 RESERVED         '
  203.                + #179'reserviert                      ';
  204.   VecTab[$74] := 'IRQ12 MOUSE INTERRUPT  '
  205.                + #179'Maus-Interrupt bei IBM PS/2     ';
  206.   VecTab[$75] := 'IRQ13 80287 ERROR      '
  207.                + #179'80x87-Fehler                    ';
  208.   VecTab[$76] := 'IRQ14 FIXED DISK       '
  209.                + #179'Festplatte                      ';
  210.   VecTab[$77] := 'IRQ15 RESERVED         '
  211.                + #179'reserviert                      ';
  212.   FOR i := $78 TO $7E DO
  213.     VecTab[i] := 'UNUSED                 '
  214.                + #179'normalerweise unbenutzt         ';
  215.   VecTab[$7A] := 'NOVELL NETWARE LL API  '
  216.                + #179'Low-Level API von Novell        ';
  217.   VecTab[$7F] := 'HDILOAD                '
  218.                + #179'IBM 8514/A-Interface            ';
  219.   FOR i := $80 TO $F0 DO
  220.     VecTab[i] := 'RESERVED FOR BASIC IPR '
  221.                + #179'für GW-Basic/Basica reserviert  ';
  222.   FOR i := $F1 TO $FD DO
  223.     VecTab[i] := 'RESERVED FOR USER INTR.'
  224.                + #179'für Applikationen reserviert    ';
  225.   FOR i := $FE TO $FF DO
  226.     VecTab[i] := 'PROTECTED MODE RESERV. '
  227.                + #179'für Protected Mode reserviert   ';
  228.   FOR i := $00 TO $FF DO                { die Zeichenketten aufbauen: }
  229.     VecTab[i] := '   '#179 + Ptr2Hex(Vectors[i], TRUE)
  230.                     + #179'$' + Byte2Hex(i)
  231.                     + #179 + VecTab[i] + #179;
  232. END;
  233.  
  234. PROCEDURE Run;
  235.  
  236.   PROCEDURE SetBackGround;
  237.   BEGIN
  238.     IF BYTE(Ptr(Seg0040, $0049)^) IN [0, 2, 7] THEN    { SW/Monochrom }
  239.       TextAttr := LightGray                                { Standard }  
  240.     ELSE                                                     { Farbe: } 
  241.     BEGIN
  242.       TextColor(Yellow); TextBackground(Blue);                 { Bunt }
  243.     END;
  244.   END;
  245.  
  246.   PROCEDURE WriteALine(l: INTEGER; s: STRING);
  247.   BEGIN
  248.     TextAttr := 112;                              { Farbe: invertiert }
  249.     GotoXY(1, l);                              { Zeilenanfang von »l« }
  250.     ClrEoL;                                    { Bis zum Ende löschen }
  251.     GotoXY(2, l);                              { 2. Zeichen der Zeile }
  252.     Write(s);                                          { »s« ausgeben }
  253.     SetBackGround;                                 { Std-Farbe setzen }
  254.   END;
  255.  
  256.   PROCEDURE WriteDown(s: STRING; i: INTEGER);
  257.   VAR                                  { Zeichen nach unten schreiben }
  258.     y: INTEGER;
  259.   BEGIN
  260.     IF s[0] > ^@ THEN                            { auch das ist #0 !! }
  261.       FOR y := 1 TO BYTE(s[0]) DO            { identisch zu Length(s) }
  262.       BEGIN                                { wüstes schnelles Typcast }
  263.         GotoXY(79, y + i); Write(s[y]);        { ein Zeichen ausgeben }
  264.       END;
  265.   END;
  266.  
  267.   PROCEDURE Help;
  268.   VAR
  269.     i: INTEGER;
  270.     ch: CHAR;
  271.   BEGIN
  272.     WriteALine(25, HelpLine);
  273.     TextAttr := 111;                  { weiße Schrift auf rotem Grund }
  274.     FOR i := 2 TO 24 DO
  275.     BEGIN
  276.       GotoXY(1, i); ClrEoL;           { Bildschirm außer Statuszeilen }
  277.     END;                              { löschen                       }  
  278.     GotoXY(5, 3); Write(#218); FOR i := 6 TO 74 DO Write(#196);
  279.     Write(#191);                      { Rahmen um den Hilfebildschirm }
  280.     FOR i := 4 TO 21 DO               { mit Grafikzeichen (einfache)  }  
  281.     BEGIN                             { Linien) zeichnen              }
  282.       GotoXY(5, i); Write(#179, #179:70);
  283.     END; 
  284.     GotoXY(5, 22); Write(#192); FOR i := 6 TO 74 DO Write(#196);
  285.     Write(#217);
  286.     ch := #0;                         { Hilfetext ausgeben            }
  287.     GotoXY(36,  4); Write('Hilfe');  GotoXY(5, 5); Write(#195);
  288.     FOR i := 6 TO 74 DO Write(#196); Write(#180);
  289.     GotoXY( 6,  7); Write('Mit den Cursortasten wird durch die Liste '
  290.                         + 'gescrollt.');
  291.     GotoXY( 6,  9); Write('Direktes Anspringen erfolgt durch Eingabe '
  292.                         + 'der Hex-Nummer des entspre-');
  293.     GotoXY( 6, 10); Write('chenden Interrupts. Die Eingabe muß immer '
  294.                         + 'mit »$« und zwei Hexzahlen');
  295.     GotoXY( 6, 11); Write('erfolgen, bei Interrupts kleiner als 10h m'
  296.                         + 'it führender Null, also ');
  297.     GotoXY( 6, 12); Write('beispielweise $03 für Int 3h.');
  298.     GotoXY( 6, 14); Write('Mit »[S]peichern« wird die Tabelle auf den'
  299.                         + ' Datenträger in die Datei');
  300.     GotoXY( 6, 15); Write('SHOWVECT.OUT ins aktuelle Verzeichnis gesi'
  301.                         + 'chert.  Eine bereits vor-');
  302.     GotoXY( 6, 16); Write('handene ältere Datei wird dabei überschrie'
  303.                         + 'ben. Mit »[D]rucken« wird');
  304.     GotoXY( 6, 17); Write('die komplette Liste aller Interrupts auf d'
  305.                         + 'em Drucker ausgegeben.');
  306.     GotoXY( 6, 18); Write('Achtung: Das dauert, da es sich um 256 Zei'
  307.                         + 'len handelt, etwas länger.');
  308.     GotoXY( 6, 20); Write('Das Programm wird mit einem Druck auf <ESC'
  309.                         + '> ohne Nachfrage beendet.');
  310.     REPEAT
  311.       ch := ReadKey;             { Tastendruck abfragen, bei F-Tasten }
  312.     UNTIL ch <> #0;                     { das erste Zeichen schlucken }  
  313.     WriteALine(25, StatusLine);              { Infozeile restaurieren }
  314.     FOR i := 2 TO 24 DO                     { roten Bildschirm wieder }
  315.     BEGIN                                   { löschen (blau)          }
  316.       GotoXY(1, i);
  317.       ClrEoL;
  318.     END;
  319.     GotoXY(1,  2); Write(UpperLine);            { alten Rahmen wieder }
  320.     GotoXY(1, 24); Write(Lowerline);                   { restaurieren }
  321.   END;
  322.  
  323. VAR
  324.    First, Second,                               { für direkte Eingabe }
  325.    key           : CHAR;                            { Tastaturabfrage }
  326.    i, j, c       : BYTE;                              { Zählvariablen }
  327.    t             : Text;                              { Dateivariable }
  328.    test          : INTEGER;                               { für Val() }
  329. BEGIN
  330.   HideCursor;                                            { Cursor aus }
  331.   SetBackGround;                            { Hintergrundfarbe setzen }
  332.   ClrScr;                                        { ... und BS löschen }
  333.   WriteALine(1, InfoLine);                   { erste und letzte Zeile }
  334.   WriteALine(25, StatusLine);                          { ... anzeigen }
  335.   GotoXY(1, 2);                                       { Rahmen ziehen }
  336.   WriteLn(UpperLine);
  337.   FOR j := 0 TO 20 DO WriteLn(VecTab[j]);    { Vektoren ab 0 anzeigen }
  338.   WriteLn(Lowerline);                            { untere Rahmenzeile }
  339.   i := 0; j := 0;                            { Variablen auf 0 setzen }
  340.   REPEAT
  341.     key := UpCase(ReadKey);    { Die Tastaturabfrage für die Schleife }
  342.     IF (key = 'S') THEN                           { Taste »Speichern« }
  343.     BEGIN
  344.       WriteDown('SPEICHERN IN DATEI', 2);             { Info ausgeben }
  345.       Assign(t, 'SHOWVECT.OUT');                     { Datei zuordnen }
  346.       ReWrite(t);                                   { ... neu anlegen }
  347.       WriteLn(t, UpperLine);                        { Rahmen oben ... }
  348.       FOR i := 0 TO $FF DO WriteLn(t, VecTab[i]);      { Vektoren ... }
  349.       WriteLn(t, UpperLine);           { und unteren Rahmen schreiben }
  350.       Close(t);                                     { Datei schließen }
  351.       WriteDown('                  ', 2);          { Infotext löschen }
  352.       i := $00;                                      { Vektorenanfang }
  353.     END
  354.     ELSE IF key = 'D' THEN                          { Taste »Drucken« } 
  355.     BEGIN
  356.       WriteDown('VEKTOREN DRUCKEN', 2);               { Info ausgeben }
  357.       WriteLn(Lst, UpperLine);                      { Rahmen oben ... }
  358.       FOR i := 0 TO $FF DO WriteLn(Lst, VecTab[i]);    { Vektoren ... }
  359.       WriteLn(Lst, Lowerline);           { und unteren Rahmen drucken }
  360.       WriteDown('                 ', 2);           { Infotext löschen }
  361.       i := $00;                                      { Vektorenanfang }
  362.     END
  363.     ELSE IF key = '$' THEN BEGIN                  { direkt anspringen }
  364.       REPEAT
  365.         First  := ReadKey;                { Zehnerzahl (hex) abfragen }
  366.       UNTIL First IN ['0'..'9', 'A'..'F', 'a'..'f'];
  367.       REPEAT
  368.        Second := ReadKey;                  { Einerzahl (hex) abfragen }
  369.       UNTIL Second IN ['0'..'9', 'A'..'F', 'a'..'f'];
  370.       Val('$' + First + Second, c, test);  { String in Zahl umwandeln }
  371.       IF test = 0 THEN                 { kein Fehler, also ausführen: }
  372.       BEGIN               
  373.         IF c IN [$00..$FF - 20] THEN i := c        ELSE
  374.         IF c IN [$FF - 20..$FF] THEN i := $FF - 20 ELSE i := 0;
  375.         GotoXY(1, 3);                             { Cursor zum Anfang }
  376.         FOR j := i TO i + 20 DO WriteLn(VecTab[j]);        { ausgeben }
  377.       END;
  378.     END
  379.     ELSE IF key = #0 THEN               { Cursor- oder Funktionstaste }
  380.     BEGIN
  381.       key := ReadKey;                            { zweiten Code lesen }
  382.       IF (key = 'H') AND (i > 0) THEN Dec(i);             { Cursor Up }
  383.       IF (key = 'P') AND (i < $FF - 20) THEN Inc(i);    { Cursor Down }
  384.       IF (key = 'G') AND (i <> 0) THEN i := 0;                 { Home }
  385.       IF (key = 'O') AND (i < $FF - 21) THEN i := $FF - 20;     { End }
  386.       IF (key = 'Q') THEN                                      { PgUp }
  387.         IF (i <= $FF - 20 * 2) THEN Inc(i, 21) ELSE i := $FF - 20;
  388.       IF (key = 'I') THEN                                      { PgDn }
  389.         IF (i >= 21 * 2) THEN Dec(i, 21) ELSE i := 0;
  390.       IF key = ';' THEN Help;                                    { F1 }
  391.       GotoXY(1, 3);
  392.       FOR j := i TO i + 20 DO WriteLn(VecTab[j]);    { Werte anzeigen }
  393.     END;
  394.   UNTIL key = #27;                               { Bis <ESC> gedrückt }
  395. END;
  396.  
  397. PROCEDURE Done;
  398. BEGIN
  399.   SetCursor(StartCursor);                         { Cursor anschalten }
  400.   TextAttr := LightGray;                      { Standard-Textattribut }
  401.   WriteLn(' ');        { nur so wird das Text-Attribut zurückgesetzt! }
  402.   ClrScr;                                    { und Bildschirm löschen }
  403. END;
  404.  
  405. BEGIN
  406.   Init;                                  { Initialisieren der Tabelle }
  407.   Run;                                         { Anzeigen der Tabelle }
  408.   Done;                                      { Restaurieren der Werte }
  409. END.                  
  410.  
  411. (*===================================================================*)
  412.