home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1991 / 07_08 / tricks / scroll.pas < prev    next >
Pascal/Delphi Source File  |  1991-04-19  |  12KB  |  318 lines

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