home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 01 / praxis / scroll.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-10-20  |  11.8 KB  |  301 lines

  1. (* ------------------------------------------------------------------------- *)
  2. (*                            SCROLL.PAS                                     *)
  3. (*           Anzeigen und Durchblättern einer beliebigen Liste               *)
  4. (*                                                                           *)
  5. (*              (c) 1988   TOOLBOX  &  Karsten Gieselmann                    *)
  6. (* ------------------------------------------------------------------------- *)
  7.  
  8. {$R-,S-,I-,V-,B-,N-}       (* keine Fehlerprüfung, maximale Geschwindigkeit! *)
  9.  
  10. UNIT Scroll;
  11.  
  12. INTERFACE
  13.  
  14. USES
  15.   Crt, Dos;                                               (* benötigte Units *)
  16.  
  17. (* ------------------------ Initialisierungsroutine ------------------------ *)
  18.  
  19. PROCEDURE SetupScrollArea(DataSize : LONGINT; Normal, Selected : POINTER);
  20.  
  21.   (* definiert das aktuelle Fenster (Window-Befehl) als Scroll-Bereich;  die *)
  22.   (* zu  durchblätternde Liste  umfaßt "DataSize"  Elemente (Zeilen),  diese *)
  23.   (* werden durch die Routinen bei "Normal" (normale Ausgabe) und "Selected" *)
  24.   (* (ungleich NIL für Leuchtbalken) ausgegeben. Syntax der Ausgaberoutinen: *)
  25.  
  26.   (*  {$F+}  Procedure WriteLine(Col,Row : BYTE; Index : LONGINT);  {$F-}    *)
  27.  
  28.   (* (Col,Row) ist dabei die Ausgabeposition des ersten Zeichens der durch   *)
  29.   (* "Index" gekennzeichneten Textzeile in Fensterkoordinaten!               *)
  30.  
  31. (* -------------- Ansteuerung und Abfrage des Scroll-Fensters -------------- *)
  32.  
  33. VAR TopIndex : LONGINT;
  34.      (* Index des Listenelements in der obersten Textzeile im Scroll-Fenster *)
  35.  
  36. VAR SelectIndex : LONGINT;
  37.      (* Index der durch Leuchtbalken hervorgehobenen Zeile im Scroll-Fenster *)
  38.  
  39. VAR LinesToScroll : LONGINT;
  40.         (* Elementumfang der anzuzeigenden Liste (entspricht der Zeilenzahl) *)
  41.  
  42. PROCEDURE ScrollResponse(ScanCode : WORD);
  43.   (* wertet den Tastencode "ScanCode" aus und leitet entsprechende Maßnahmen *)
  44.   (* ein;  über die Variablen "TopIndex" und "SelectIndex"  kann der Zustand *)
  45.   (* des Scroll-Fensters jederzeit abgefragt werden.                         *)
  46.  
  47. PROCEDURE RedrawScrollArea;
  48.   (* gibt den momentanen Inhalt des Scroll-Fensters (also die ersten Einträ- *)
  49.   (* ge ab "TopIndex" neu aus; die Position eines  eventuell vorhandenen Se- *)
  50.   (* lektbalken wird dabei nicht verändert.                                  *)
  51.  
  52. (* ----------- Sichern und Wiederherstellen eines Scroll-Zustands ---------- *)
  53.  
  54. TYPE
  55.   ScrollPB = RECORD                                (* Scroll Parameter Block *)
  56.                Left, Top, Right, Bottom : BYTE;            (* Fenstergrenzen *)
  57.                LineSave                 : LONGINT;           (* Listenumfang *)
  58.                TopSave, SelectSave      : LONGINT;       (* Zustands-Indizes *)
  59.                Normal, Selected         : POINTER;        (* Ausgaberoutinen *)
  60.              END;
  61.  
  62. PROCEDURE SaveScrollArea(VAR Buffer : ScrollPB);
  63.              (* sichert den aktuellen Zustand des Scroll-Systems in "Buffer" *)
  64.  
  65. PROCEDURE RestoreScrollArea(VAR Buffer : ScrollPB);
  66.             (* reinitialisiert das Scroll-System mit dem Inhalt von "Buffer" *)
  67.  
  68. (* ------------------------------------------------------------------------- *)
  69.  
  70. IMPLEMENTATION
  71.  
  72. CONST
  73.   Overlap = 1;               (* Zahl der Überschneidungszeilen bei PgUp/PgDn *)
  74.  
  75. VAR
  76.   ColSize, RowSize  : BYTE;       (* Spalten/Zeilengröße des Ausgabefensters *)
  77.   WriteNormalProc,                             (* Zeiger auf Ausgaberoutinen *)
  78.   WriteSelectedProc : POINTER;
  79.   SelectBar         : BOOLEAN;                  (* Anzeige mit Leuchtbalken? *)
  80.  
  81.  
  82. FUNCTION Min(a,b : LONGINT) : LONGINT;        (* Minimum zweier LONG-INTEGER *)
  83. INLINE(
  84.   $58/                      (*  POP   AX     ;Parameter a nach DX:AX holen   *)
  85.   $5A/                      (*  POP   DX     ;                               *)
  86.   $5B/                      (*  POP   BX     ;Parameter b nach CX:BX holen   *)
  87.   $59/                      (*  POP   CX     ;                               *)
  88.   $39/$CA/                  (*  CMP   CX,DX  ;Hi(a) mit Hi(b) vergleichen    *)
  89.   $7C/$0A/                  (*  JL    *+10   ;fertig, wenn Hi(a) < Hi(b)     *)
  90.   $75/$04/                  (*  JNE   *+04   ;vertauschen, wenn a <> b       *)
  91.   $39/$D8/                  (*  CMP   AX,BX  ;Lo(a) mit Lo(b) vergleichen    *)
  92.   $76/$04/                  (*  JBE   *+4    ;fertig, wenn Lo(a) < Lo(b)     *)
  93.   $87/$C3/                  (*  XCHG  AX,BX  ;a mit b vertauschen            *)
  94.   $87/$CA);                 (*  XCHG  DX,CX  ;Ergebnis steht in DX:AX        *)
  95.  
  96.  
  97. FUNCTION Max(a,b : LONGINT) : LONGINT;        (* Maximum zweier LONG-INTEGER *)
  98. INLINE(
  99.   $58/                      (*  POP   AX     ;Parameter a nach DX:AX holen   *)
  100.   $5A/                      (*  POP   DX     ;                               *)
  101.   $5B/                      (*  POP   BX     ;Parameter b nach CX:BX holen   *)
  102.   $59/                      (*  POP   CX     ;                               *)
  103.   $39/$CA/                  (*  CMP   CX,DX  ;Hi(a) mit Hi(b) vergleichen    *)
  104.   $7F/$0A/                  (*  JG    *+10   ;fertig, wenn Hi(a) > Hi(b)     *)
  105.   $75/$04/                  (*  JNE   *+04   ;vertauschen, wenn a <> b       *)
  106.   $39/$D8/                  (*  CMP   AX,BX  ;Lo(a) mit Lo(b) vergleichen    *)
  107.   $73/$04/                  (*  JAE   *+4    ;fertig, wenn Lo(a) > Lo(b)     *)
  108.   $87/$C3/                  (*  XCHG  AX,BX  ;a mit b vertauschen            *)
  109.   $87/$CA);                 (*  XCHG  DX,CX  ;Ergebnis steht in DX:AX        *)
  110.  
  111.  
  112. PROCEDURE SetupScrollArea(DataSize : LONGINT; Normal, Selected : POINTER);
  113.          (* Definition eines Bereichs und Initialisierung des Scroll-Systems *)
  114. BEGIN
  115.   LinesToScroll := DataSize;
  116.   WriteNormalProc := Normal;
  117.   WriteSelectedProc := Selected;
  118.   SelectBar := (Selected <> NIL);              (* Blättern mit Leuchtbalken? *)
  119.   ColSize := Succ(Lo(WindMax)-Lo(WindMin));
  120.   RowSize := Succ(Hi(WindMax)-Hi(WindMin));
  121.   TopIndex := 1;
  122.   SelectIndex := Ord(SelectBar);            (* Null, falls kein Leuchtbalken *)
  123. END;
  124.  
  125.  
  126. PROCEDURE WriteNormal(Col, Row : BYTE; Index : LONGINT);
  127.                     (* springt zur Ausgaberoutine für normale Listenelemente *)
  128. INLINE ($FF/$1E/WriteNormalProc);
  129.  
  130.  
  131. PROCEDURE WriteSelected(Col, Row : BYTE; Index : LONGINT);
  132.                    (* springt zur Ausgaberoutine für das Leuchbalken-Element *)
  133. INLINE ($FF/$1E/WriteSelectedProc);
  134.  
  135.  
  136. PROCEDURE WriteList(Index : LONGINT);
  137.                         (* listet die ersten ab "Index" beginnenden Einträge *)
  138. VAR
  139.   Row : BYTE;
  140. BEGIN
  141.   TopIndex := Index;                           (* Zeilenzeiger aktualisieren *)
  142.   FOR Row:=1 TO Min(LinesToScroll, RowSize) DO
  143.     IF Pred(Index+Row) <> SelectIndex THEN
  144.       WriteNormal(1, Row, Pred(Index+Row))
  145.     ELSE
  146.       WriteSelected(1, Row, Pred(Index+Row));
  147. END;
  148.  
  149.  
  150. PROCEDURE ScrollResponse(ScanCode : WORD);
  151.                                           (* Auswertung der Taste "ScanCode" *)
  152. CONST
  153.   Home = $4700;    End_ = $4F00;    (* Codes der Tasten zur Scroll-Steuerung *)
  154.   PgUp = $4900;    PgDn = $5100;
  155.   Up   = $4800;    Down = $5000;
  156.  
  157.   PROCEDURE ScrollList(Increment : SHORTINT);
  158.                   (* rollt Fenster um "Increment" Zeilen auf (+) bzw. ab (-) *)
  159.  
  160.      PROCEDURE ScrollWindow(Left,Top,Right,Bottom : BYTE; Lines : SHORTINT);
  161.                                             (* Aufruf der BIOS-Scrollroutine *)
  162.      VAR
  163.        Regs : Registers;
  164.      BEGIN
  165.        WITH Regs do BEGIN
  166.          IF Lines > 0 THEN
  167.            AH := 6                            (* Scrolle Bildschirm aufwärts *)
  168.          ELSE
  169.            AH := 7;                            (* Scrolle Bildschirm abwärts *)
  170.          AL := Abs(Increment);             (* Zahl der zu scrollenden Zeilen *)
  171.          BH := TextAttr;
  172.          CL := Pred(Left) + Lo(WindMin);              (* Fenster-Koordinaten *)
  173.          CH := Pred(Top) + Hi(WindMin);
  174.          DL := Pred(Right) + Lo(WindMin);
  175.          DH := Pred(Bottom) + Hi(WindMin);;
  176.          Intr($10, Regs);
  177.        END;
  178.      END;
  179.  
  180.   BEGIN
  181.     ScrollWindow(1, 1, ColSize, RowSize, Increment);
  182.     TopIndex := TopIndex+Increment;
  183.     IF Increment < 0 THEN
  184.       IF SelectBar THEN
  185.         WriteSelected(1, 1, TopIndex)
  186.       ELSE
  187.         WriteNormal(1, 1, TopIndex)
  188.     ELSE
  189.       IF SelectBar THEN
  190.         WriteSelected(1, RowSize, Pred(TopIndex+RowSize))
  191.       ELSE
  192.         WriteNormal(1, RowSize, Pred(TopIndex+RowSize))
  193.   END;
  194.  
  195.  
  196. BEGIN
  197.   CASE ScanCode OF
  198.  
  199.     Home :                                     (* Liste von Anfang an zeigen *)
  200.       BEGIN
  201.         IF SelectBar THEN
  202.           SelectIndex := 1;
  203.         WriteList(1);
  204.       END;
  205.  
  206.     End_ :                                      (* Liste bis zum Ende zeigen *)
  207.       BEGIN
  208.         IF SelectBar THEN
  209.           SelectIndex := LinesToScroll;
  210.         WriteList(Max(1, LinesToScroll-Pred(RowSize)));
  211.       END;
  212.  
  213.     PgUp :                                   (* eine Seite aufwärts blättern *)
  214.       BEGIN
  215.         IF SelectBar THEN
  216.           SelectIndex := Max(1, LONGINT(SelectIndex)-RowSize+Overlap);
  217.         WriteList(Max(1, LONGINT(TopIndex)-RowSize+Overlap));
  218.       END;
  219.  
  220.     PgDn :                                    (* eine Seite abwärts blättern *)
  221.       BEGIN
  222.         IF SelectBar THEN
  223.           SelectIndex := Min(LinesToScroll, SelectIndex+RowSize-Overlap);
  224.         WriteList(Min(Max(1, LinesToScroll-Pred(RowSize)),
  225.                                TopIndex+RowSize-Overlap));
  226.       END;
  227.  
  228.     Up :                                     (* eine Zeile aufwärts blättern *)
  229.       IF SelectBar THEN
  230.         IF SelectIndex > 1 THEN
  231.           IF SelectIndex = TopIndex THEN BEGIN
  232.             Dec(SelectIndex);
  233.             WriteNormal(1, SelectIndex-TopIndex+2, Succ(SelectIndex));
  234.             ScrollList(-1);
  235.           END ELSE BEGIN
  236.             Dec(SelectIndex);
  237.             WriteNormal(1, SelectIndex-TopIndex+2, Succ(SelectIndex));
  238.             WriteSelected(1, SelectIndex-Pred(TopIndex), SelectIndex);
  239.           END
  240.         ELSE
  241.       ELSE
  242.         IF TopIndex > 1 THEN
  243.           ScrollList(-1);
  244.  
  245.     Down :                                    (* eine Zeile abwärts blättern *)
  246.       IF SelectBar THEN
  247.         IF SelectIndex < LinesToScroll THEN
  248.           IF SelectIndex = Pred(TopIndex+RowSize) THEN BEGIN
  249.             Inc(SelectIndex);
  250.             WriteNormal(1, SelectIndex-TopIndex, Pred(SelectIndex));
  251.             ScrollList(+1);
  252.           END ELSE BEGIN
  253.             Inc(SelectIndex);
  254.             WriteNormal(1, SelectIndex-TopIndex, Pred(SelectIndex));
  255.             WriteSelected(1, SelectIndex-Pred(TopIndex), SelectIndex);
  256.           END
  257.         ELSE
  258.       ELSE
  259.         IF Pred(TopIndex+RowSize) < LinesToScroll THEN
  260.           ScrollList(+1);
  261.   END;
  262. END;
  263.  
  264.  
  265. PROCEDURE RedrawScrollArea;     (* Neuausgabe der Scroll-Liste ab "TopIndex" *)
  266. BEGIN
  267.   WriteList(TopIndex);
  268. END;
  269.  
  270.  
  271. PROCEDURE SaveScrollArea(VAR Buffer : ScrollPB);
  272.              (* sichert den aktuellen Zustand des Scroll-Systems in "Buffer" *)
  273. BEGIN
  274.   WITH Buffer DO BEGIN
  275.     Left := Succ(Lo(WindMin));
  276.     Top := Succ(Hi(WindMin));
  277.     Right := Succ(Lo(WindMax));
  278.     Bottom := Succ(Hi(WindMax));
  279.     LineSave := LinesToScroll;
  280.     TopSave := TopIndex;
  281.     SelectSave := SelectIndex;
  282.     Normal := WriteNormalProc;
  283.     Selected := WriteSelectedProc;
  284.   END;
  285. END;
  286.  
  287.  
  288. PROCEDURE RestoreScrollArea(VAR Buffer : ScrollPB);
  289.             (* reinitialisiert das Scroll-System mit dem Inhalt von "Buffer" *)
  290. BEGIN
  291.   WITH Buffer DO BEGIN
  292.     Window(Left, Top, Right, Bottom);
  293.     SetupScrollArea(LineSave, Normal, Selected);
  294.     TopIndex := TopSave;
  295.     SelectIndex := SelectSave;
  296.   END;
  297. END;
  298.  
  299. END.
  300. (* ------------------------------------------------------------------------- *)
  301. (*                         Ende von SCROLL.PAS                               *)