home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* COPYCURS.PAS *)
- (* Speicherresidente Copy-Cursor-Funktion *)
- (* (c) 1988 Karsten Gieselmann & PASCAL International *)
- (* ------------------------------------------------------ *)
-
- {$R-,S-,I-,V-,B-,N-} (* größtmögliche Geschwindigkeit! *)
- {$M 1024,0,0} (* wenig Stack, kein Heap! *)
-
- PROGRAM CopyCursor;
-
- USES
- Crt, Dos; (* benötigte Units *)
-
- CONST
- Version = 'COPYCURS v1.0';
- Hotkey = $7100; (* Aktivierungstaste *)
- CopyKey = $4400; (* Einfügetaste, hier: <F10> *)
- Escape = $011B;
- Return = $1C0D;
- HotkeyName = '<Alt><F10>'; (* Aktivierungstaste *)
- MaxCol = 80; (* Bildschirmausmaße *)
- MaxRow = 25;
-
- TYPE
- ScreenType = ARRAY [1..MaxRow, 1..MaxCol] of WORD;
-
- VAR
- Screen : ^ScreenType; (* Bildschirmspeicher *)
- SaveInt16 : POINTER;
- SaveSS,SaveSP, (* Speicher für Stacktops *)
- ProgSS,ProgSP,
- VideoSegment, (* Basissegment des Bildspeichers *)
- Ch : WORD;
- Active, (* Schaltervariablen *)
- CopyMode : BOOLEAN;
-
- (* --- einen Tastencode von der alten Int16-ISR holen --- *)
-
- FUNCTION GetKey : WORD;
- INLINE ($31/$C0/$9C/$FF/$1E/SaveInt16);
-
- (* ----------- die Copy-Cursor-Routine ------------------ *)
-
- PROCEDURE GetCopyCursorChar (VAR Key : WORD);
-
- TYPE
- Direction = (_Left, _Right, _Up, _Down,
- _Home, _End, _Top, _Bottom);
- VAR
- Quit,Moved : BOOLEAN;
- Col,Row : BYTE;
- Command : WORD;
- PageOffset : WORD ABSOLUTE $0040:$004E;
-
- PROCEDURE ReverseAttribute;
- (* invertiert das Farbattribut bei (Col,Row) *)
-
- VAR VideoWord : RECORD CASE BYTE OF
- 1: (v : WORD);
- 2: (c,a : BYTE);
- END;
- BEGIN
- WITH VideoWord DO BEGIN
- v := Screen^[Row,Col];
- a := (a MOD 16)*16 + a SHR 4;
- Screen^[Row,Col] := v
- END
- END;
-
-
- PROCEDURE MoveCopyCursor (d : Direction);
-
- BEGIN
- Moved := TRUE;
- ReverseAttribute;
- CASE d OF
- _Left: IF Col > 1 THEN
- Dec(Col)
- ELSE IF Row > 1 THEN BEGIN
- Col:=80; Dec(Row);
- END;
- _Right: IF Col < 80 THEN
- Inc (Col)
- ELSE IF Row < 25 THEN BEGIN
- Col:=1; Inc(Row);
- END;
- _Up: IF Row > 1 THEN
- Dec (Row)
- ELSE
- Row:=25;
- _Down: IF Row < 25 THEN
- Inc (Row)
- ELSE
- Row:=1;
- _Home: Col:= 1;
- _End: Col:=80;
- _Top: Row:= 1;
- _Bottom: Row:=25;
- END;
- ReverseAttribute;
- END;
-
-
- PROCEDURE InitCopyCursor;
-
- VAR
- Regs : Registers;
-
- BEGIN
- CopyMode := TRUE;
- Moved := FALSE;
- WITH Regs DO BEGIN
- AH := $0F;
- Intr ($10, Regs); (* Bildschirmmodus holen *)
- IF AL = 7 THEN
- VideoSegment := $B000 (* Monochrome, Hercules *)
- ELSE
- VideoSegment := $B800; (* Farbgrafik *)
- Screen := Ptr (VideoSegment + PageOffset SHR 4, 0);
- AH := $03;
- Intr ($10, Regs); (* Cursorposition holen *)
- Col := Succ (DL);
- Row := Succ (DH);
- END;
- ReverseAttribute;
- END;
-
-
- BEGIN
- IF NOT CopyMode THEN (* Copy-Cursor noch nicht aktiv? *)
- InitCopyCursor; (* dann erst einmal initialisieren *)
- Quit := FALSE;
- REPEAT
- Command := GetKey;
- IF NOT Moved THEN BEGIN
- Moved := Hi(Command) IN [$47,$48,$49,$4B,
- $4D,$4F,$50,$51];
- IF NOT Moved THEN
- Command := Escape
- (* erste Taste muß Copy-Cursor bewegen! *)
- END;
- CASE Command OF
- $4B00: MoveCopyCursor (_Left);
- $4D00: MoveCopyCursor (_Right);
- $4800: MoveCopyCursor (_Up);
- $5000: MoveCopyCursor (_Down);
- $4700: MoveCopyCursor (_Home);
- $4F00: MoveCopyCursor (_End);
- $4900: MoveCopyCursor (_Top);
- $5100: MoveCopyCursor (_Bottom);
- CopyKey: BEGIN (* Bildschirm-Zeichen übergeben *)
- Key := Lo(Screen^[Row,Col]);
- MoveCopyCursor (_Right);
- Quit := TRUE;
- END;
- (* Copy-Cursor vorübergehend deaktivieren *)
- Hotkey: BEGIN
-
- Key := GetKey;
- Active := FALSE;
- Quit := TRUE;
- END;
- (* Copy-Cursor-Funktion verlassen *)
- Return,
- Escape: BEGIN
- ReverseAttribute;
- IF Command = Return THEN
- Key := Return
- (* Ende, das <Return> zurückgeben *)
- ELSE
- Key := GetKey;
- (* Ende, auf weitere Taste warten *)
- IF Key <> Hotkey THEN BEGIN
- Active := FALSE;
- CopyMode := FALSE;
- Quit := TRUE;
- END
- ELSE
- (* Taste war Hotkey, doch weiter machen *)
- InitCopyCursor;
- END;
- (* gedrückte Taste übergeben *)
- ELSE BEGIN
- Key := Command;
- Quit := TRUE
- END;
- END;
- UNTIL Quit;
- END;
-
-
- (* --- die neue ISR für den Tastatur-Interrupt 16h ------ *)
-
- {$F+}
-
- PROCEDURE Int16 (Flags,CS,IP,AX,BX,CX,DX,SI,
- DI,DS,ES,BP : WORD); INTERRUPT;
-
- PROCEDURE ChainInt (Address : POINTER);
- (* Sprung zur ISR bei "Address" *)
- INLINE ($5B/$58/$87/$5E/$0E/$87/$46/$10/$89/
- $EC/$5D/$07/$1F/$5F/$5E/$5A/$59/$CB);
-
- PROCEDURE SwitchStack;
- (* auf den Programm-Stapel umschalten *)
- INLINE ($8C/$16/SaveSS/$89/$26/SaveSP/$FA/
- $8E/$16/ProgSS/$8B/$26/ProgSP/$FB);
-
- PROCEDURE SwitchBack;
- (* vom Programmstapel zurückschalten *)
- INLINE ($FA/$8E/$16/SaveSS/$8B/$26/SaveSP/$FB);
-
- BEGIN
- IF Hi(AX) = 0 THEN BEGIN
- (* soll Tastencode geholt werden? *)
- IF not Active THEN BEGIN
- AX := GetKey;
- Active := (AX = Hotkey);
- (* Copy-Cursor aktivieren? *)
- END;
- IF Active THEN BEGIN
- SwitchStack;
- GetCopyCursorChar (Ch);
- SwitchBack;
- AX := Ch
- (* Übergabe erst nach Stapel-Rückschaltung!! *)
- END
- END ELSE
- ChainInt (SaveInt16)
- (* keinen Tastencode holen, weiter mit alter ISR *)
- END;
-
- {$F-}
-
-
- (* --- der Installationsteil von COPYCURS --------------- *)
-
- BEGIN
- ProgSS := SSeg; (* Werte für Programm-Stapel merken *)
- ProgSP := SPtr;
- WriteLn (^M^J, Version, ' installiert,',
- ^M^J'aktivieren mit ', HotKeyName, '.');
- Active := FALSE; (* Schalter initialisieren *)
- CopyMode := FALSE;
- (* alten Int16-Vektor merken... *)
- GetIntVec ($16, SaveInt16);
- (* ...eigene Routine einsetzen... *)
- SetIntVec ($16, @Int16);
- (* ...Break-Vektor zurücksetzen... *)
- SetIntVec ($1B, SaveInt1B);
- Keep (0); (* ...und resident machen! *)
- END.
- (* ------------------------------------------------------ *)
- (* Ende von COPYCURS.PAS *)