home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
1991
/
07_08
/
tricks
/
scroll.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-04-19
|
12KB
|
318 lines
(* ------------------------------------------------------ *)
(* SCROLL.PAS *)
(* Anzeigen und Durchblättern einer beliebigen Liste *)
(* (c) 1988, 1991 Karsten Gieselmann & TOOLBOX *)
(* ------------------------------------------------------ *)
{$R-,S-,I-,V-,B-,N-}
(* keine Fehlerprüfung, maximale Geschwindigkeit! *)
UNIT Scroll;
INTERFACE
USES Crt, Dos;
(* ------------ Initialisierungsroutine ----------------- *)
PROCEDURE SetupScrollArea(DataSize : LONGINT;
Normal, Selected : POINTER);
(* definiert das aktuelle Fenster (Window-Befehl) als *)
(* Scroll-Bereich; die zu durchblätternde Liste umfaßt *)
(* "DataSize" Elemente(Zeilen), diese werden durch die *)
(* Routinen bei "Normal"(normale Ausgabe) und "Selected"*)
(* (ungleich NIL für Leuchtbalken) ausgegeben. Syntax *)
(* der Ausgaberoutinen: *)
(* {$F+}
Procedure WriteLine(Col,Row : BYTE; Index : LONGINT);
{$F-} *)
(* (Col,Row) ist dabei die Ausgabeposition des ersten *)
(* Zeichens der durch "Index" gekennzeichneten Textzeile*)
(* in Fensterkoordinaten! *)
(* --- Ansteuerung und Abfrage des Scroll-Fensters ------ *)
VAR TopIndex : LONGINT;
(* Index des Listenelements in der obersten
Textzeile im Scroll-Fenster *)
VAR SelectIndex : LONGINT;
(* Index der durch Leuchtbalken hervorgehobenen
Zeile im Scroll-Fenster *)
VAR LinesToScroll : LONGINT;
(* Elementumfang der anzuzeigenden Liste
(entspricht der Zeilenzahl) *)
PROCEDURE ScrollResponse(ScanCode : WORD);
(* wertet den Tastencode "ScanCode" aus und leitet ent- *)
(* sprechende Maßnahmen ein; über die Variablen *)
(* "TopIndex" und "SelectIndex" kann der Zustand des *)
(* Scroll-Fensters jederzeit abgefragt werden. *)
PROCEDURE RedrawScrollArea;
(* gibt den momentanen Inhalt des Scroll-Fensters (also *)
(* die ersten Einträge ab "TopIndex" neu aus; die *)
(* Position eines eventuell vorhandenen Selektbalkens *)
(* wird dabei nicht verändert. *)
(* - Sichern und Wiederherstellen eines Scroll-Zustands - *)
TYPE
ScrollPB = RECORD (* Scroll Parameter Block *)
Left, Top, Right, Bottom : BYTE; (* Fenstergrenzen *)
LineSave : LONGINT; (* Listenumfang *)
TopSave, SelectSave : LONGINT; (* Zustands-Ind. *)
Normal, Selected : POINTER; (* Ausgabe *)
END;
PROCEDURE SaveScrollArea(VAR Buffer : ScrollPB);
(* sichert den aktuellen Zustand des Scroll-Systems *)
(* in "Buffer" *)
PROCEDURE RestoreScrollArea(VAR Buffer : ScrollPB);
(* reinitialisiert das Scroll-System mit dem Inhalt *)
(* von "Buffer" *)
IMPLEMENTATION
CONST
Overlap = 1;
(* Zahl der Überschneidungszeilen bei PgUp/PgDn *)
VAR
ColSize, RowSize : BYTE;
WriteNormalProc, (* Zeiger auf Ausgaberoutinen *)
WriteSelectedProc : POINTER;
SelectBar : BOOLEAN;
(* Anzeige mit Leuchtbalken? *)
FUNCTION Min(a, b : LONGINT) : LONGINT;
(* Minimum zweier LONG-INTEGER *)
INLINE(
$58/ (* POP AX ;Parameter a nach DX:AX *)
$5A/ (* POP DX ; *)
$5B/ (* POP BX ;Parameter b nach CX:BX *)
$59/ (* POP CX ; *)
$39/$CA/ (* CMP CX,DX ;Hi(a) mit Hi(b) vergl. *)
$7C/$0A/ (* JL *+10 ;fertig, Hi(a) < Hi(b) *)
$75/$04/ (* JNE *+04 ;vertauschen, wenn a <> b *)
$39/$D8/ (* CMP AX,BX ;Lo(a) mit Lo(b) vergl. *)
$76/$04/ (* JBE *+4 ;fertig, Lo(a) < Lo(b) *)
$87/$C3/ (* XCHG AX,BX ;a mit b vertauschen *)
$87/$CA); (* XCHG DX,CX ;Ergebnis steht in DX:AX *)
FUNCTION Max(a, b : LONGINT) : LONGINT;
(* Maximum zweier LONG-INTEGER *)
INLINE(
$58/ (* POP AX ;Parameter a nach DX:AX *)
$5A/ (* POP DX ; *)
$5B/ (* POP BX ;Parameter b nach CX:BX *)
$59/ (* POP CX ; *)
$39/$CA/ (* CMP CX,DX ;Hi(a) mit Hi(b) vergl. *)
$7F/$0A/ (* JG *+10 ;fertig, Hi(a) > Hi(b) *)
$75/$04/ (* JNE *+04 ;vertauschen, wenn a <> b *)
$39/$D8/ (* CMP AX,BX ;Lo(a) mit Lo(b) vergl. *)
$73/$04/ (* JAE *+4 ;fertig, Lo(a) > Lo(b) *)
$87/$C3/ (* XCHG AX,BX ;a mit b vertauschen *)
$87/$CA); (* XCHG DX,CX ;Ergebnis steht in DX:AX *)
PROCEDURE SetupScrollArea(DataSize : LONGINT;
Normal, Selected : POINTER);
(* Definition eines Bereichs und Initialisierung des *)
(* Scroll-Systems *)
BEGIN
LinesToScroll := DataSize;
WriteNormalProc := Normal;
WriteSelectedProc := Selected;
SelectBar := (Selected <> NIL);
ColSize := Succ(Lo(WindMax)-Lo(WindMin));
RowSize := Succ(Hi(WindMax)-Hi(WindMin));
TopIndex := 1;
SelectIndex := Ord(SelectBar);
(* Null, falls kein Leuchtbalken *)
END;
PROCEDURE WriteNormal(Col, Row : BYTE; Index : LONGINT);
(* springt zur Ausgaberoutine f. normale Listenelemente *)
INLINE ($FF/$1E/WriteNormalProc);
PROCEDURE WriteSelected(Col, Row : BYTE; Index : LONGINT);
(* springt zur Ausgaberoutine für Leuchbalken-Element *)
INLINE ($FF/$1E/WriteSelectedProc);
PROCEDURE WriteList(Index : LONGINT);
(* listet die ersten ab "Index" beginnenden Einträge *)
VAR
Row : BYTE;
BEGIN
TopIndex := Index; (* Zeilenzeiger aktualisieren *)
FOR Row := 1 TO Min(LinesToScroll, RowSize) DO
IF Pred(Index+Row) <> SelectIndex THEN
WriteNormal(1, Row, Pred(Index+Row))
ELSE
WriteSelected(1, Row, Pred(Index+Row));
END;
PROCEDURE ScrollResponse(ScanCode : WORD);
(* Auswertung der Taste "ScanCode" *)
CONST
Home = $4700; End_ = $4F00;
PgUp = $4900; PgDn = $5100;
Up = $4800; Down = $5000;
PROCEDURE ScrollList(Increment : SHORTINT);
(* rollt Fenster um "Increment" Zeilen *)
PROCEDURE ScrollWindow(Left,Top,Right,Bottom : BYTE;
Lines : SHORTINT);
(* Aufruf der BIOS-Scrollroutine *)
VAR
Regs : Registers;
BEGIN
WITH Regs do BEGIN
IF Lines > 0 THEN
AH := 6 (* Scrolle Bildschirm aufwärts *)
ELSE
AH := 7; (* Scrolle Bildschirm abwärts *)
AL := Abs(Increment);
(* Zahl der zu scrollenden Zeilen *)
BH := TextAttr;
CL := Pred(Left) + Lo(WindMin);
(* Fenster-Koordinaten *)
CH := Pred(Top) + Hi(WindMin);
DL := Pred(Right) + Lo(WindMin);
DH := Pred(Bottom) + Hi(WindMin);;
Intr($10, Regs);
END;
END;
BEGIN
ScrollWindow(1, 1, ColSize, RowSize, Increment);
TopIndex := TopIndex+Increment;
IF Increment < 0 THEN
IF SelectBar THEN
WriteSelected(1, 1, TopIndex)
ELSE
WriteNormal(1, 1, TopIndex)
ELSE
IF SelectBar THEN
WriteSelected(1, RowSize, Pred(TopIndex+RowSize))
ELSE
WriteNormal(1, RowSize, Pred(TopIndex+RowSize))
END;
BEGIN
CASE ScanCode OF
Home : (* Liste von Anfang an zeigen *)
BEGIN
IF SelectBar THEN SelectIndex := 1;
WriteList(1);
END;
End_ : (* Liste bis zum Ende zeigen *)
BEGIN
IF SelectBar THEN SelectIndex := LinesToScroll;
WriteList(Max(1, LinesToScroll-Pred(RowSize)));
END;
PgUp : (* eine Seite aufwärts blättern *)
BEGIN
IF SelectBar THEN
SelectIndex :=
Max(1, LONGINT(SelectIndex)-RowSize+Overlap);
WriteList(Max(1,
LONGINT(TopIndex)-RowSize+Overlap));
END;
PgDn : (* eine Seite abwärts blättern *)
BEGIN
IF SelectBar THEN
SelectIndex :=
Min(LinesToScroll, SelectIndex+RowSize-Overlap);
WriteList(Min(Max(1,
LinesToScroll-Pred(RowSize)),
TopIndex+RowSize-Overlap));
END;
Up : (* eine Zeile aufwärts blättern *)
IF SelectBar THEN
IF SelectIndex > 1 THEN
IF SelectIndex = TopIndex THEN BEGIN
Dec(SelectIndex);
WriteNormal(1, SelectIndex-TopIndex+2,
Succ(SelectIndex));
ScrollList(-1);
END ELSE BEGIN
Dec(SelectIndex);
WriteNormal(1, SelectIndex-TopIndex+2,
Succ(SelectIndex));
WriteSelected(1, SelectIndex-Pred(TopIndex),
SelectIndex);
END
ELSE
ELSE
IF TopIndex > 1 THEN ScrollList(-1);
Down : (* eine Zeile abwärts blättern *)
IF SelectBar THEN
IF SelectIndex < LinesToScroll THEN
IF SelectIndex = Pred(TopIndex+RowSize)
THEN BEGIN
Inc(SelectIndex);
WriteNormal(1, SelectIndex-TopIndex,
Pred(SelectIndex));
ScrollList(+1);
END ELSE BEGIN
Inc(SelectIndex);
WriteNormal(1, SelectIndex-TopIndex,
Pred(SelectIndex));
WriteSelected(1, SelectIndex-Pred(TopIndex),
SelectIndex);
END
ELSE
ELSE
IF Pred(TopIndex+RowSize) < LinesToScroll THEN
ScrollList(+1);
END;
END;
PROCEDURE RedrawScrollArea;
(* Neuausgabe der Scroll-Liste ab "TopIndex" *)
BEGIN
WriteList(TopIndex);
END;
PROCEDURE SaveScrollArea(VAR Buffer : ScrollPB);
(* sichert den aktuellen Zustand des Scroll-Systems *)
(* in "Buffer" *)
BEGIN
WITH Buffer DO BEGIN
Left := Succ(Lo(WindMin));
Top := Succ(Hi(WindMin));
Right := Succ(Lo(WindMax));
Bottom := Succ(Hi(WindMax));
LineSave := LinesToScroll;
TopSave := TopIndex;
SelectSave := SelectIndex;
Normal := WriteNormalProc;
Selected := WriteSelectedProc;
END;
END;
PROCEDURE RestoreScrollArea(VAR Buffer : ScrollPB);
(* reinitialisiert das Scroll-System mit dem Inhalt *)
(* von "Buffer" *)
BEGIN
WITH Buffer DO BEGIN
Window(Left, Top, Right, Bottom);
SetupScrollArea(LineSave, Normal, Selected);
TopIndex := TopSave;
SelectIndex := SelectSave;
END;
END;
END.
(* ------------------------------------------------------ *)
(* Ende von SCROLL.PAS *)