home *** CD-ROM | disk | FTP | other *** search
- {$N-}
- Unit Mousunit;
- {
- ***********************************************************
- * *
- * Microsoft Mouse Interface Routines *
- * Unit version 1.0 *
- * *
- * Copyright (C) 1988 by *
- * Dr. Bernhard Stütz *
- * *
- ***********************************************************
- }
-
- interface
- uses crt,dos,graph;
- type
- MouseMenuFlags = Array [1..20] of boolean;
- MaskType = Array [0..1,0..15] of word;
- MaskPointer = ^MaskRecord;
- MaskRecord = Record
- mask : masktype;
- x : word;
- y : word;
- end;
- var
- RightarrowCursor,DownarrowCursor,InvertedCursor:MaskRecord;
- const
- LeftB:byte=0;
- RightB:byte=1;
-
- StandardCursor : MaskRecord
- = (mask:(($3fff,$1fff,$fff, $7ff, $3ff, $1ff, $ff, $7f,
- $3f, $1f, $1ff, $10ff,$30ff,$f87f,$f87f,$fc3f),
- ($0, $4000,$6000,$7000,$7800,$7c00,$7e00,$7f00,
- $7f80,$7fc0,$7c00,$4600,$600, $300, $300, $180));
- x:0;y:0);
-
- UpArrowCursor : MaskRecord
- = (mask:(($f9ff,$f0ff,$e07f,$e07f,$c03f,$c03f,$801f,$801f,
- $f, $f, $f0ff,$f0ff,$f0ff,$f0ff,$f0ff,$f0ff),
- ($0, $600, $f00, $f00, $1f80,$1f80,$3fc0,$3fc0,
- $7fe0,$600, $600, $600, $600, $600, $600, $600));
- x:5;y:0);
-
- LeftArrowCursor : MaskRecord
- = (mask:(($fe1f,$f01f,$0, $0, $0, $f01f,$fe1f,$ffff,
- $ffff,$ffff,$ffff,$ffff,$ffff,$ffff,$ffff,$ffff),
- ($0, $c0, $7c0, $7ffe,$7c0, $c0, $0, $0,
- $0, $0, $0, $0, $0, $0, $0, $0));
- x:0;y:3);
-
- CheckMarkCursor : MaskRecord
- = (mask:(($fff0,$ffe0,$ffc0,$ff81,$ff03,$607, $f, $1f,
- $c03f,$f07f,$ffff,$ffff,$ffff,$ffff,$ffff,$ffff),
- ($0, $6, $c, $18, $30, $60, $70c0,$1d80,
- $700, $0, $0, $0, $0, $0, $0, $0));
- x:6;y:7);
-
- PointingHandCursor : MaskRecord
- = (mask:(($e1ff,$e1ff,$e1ff,$e1ff,$e1ff,$e000,$e000,$e000,
- $0, $0, $0, $0, $0, $0, $0, $0),
- ($1e00,$1200,$1200,$1200,$1200,$13ff,$1249,$1249,
- $f249,$9001,$9001,$9001,$8001,$8001,$8001,$ffff));
- x:5;y:0);
-
- DiagonalcrossCursor : MaskRecord
- = (mask:(($7e0, $180, $0, $c003,$f00f,$c003,$0, $180,
- $7e0, $ffff,$ffff,$ffff,$ffff,$ffff,$ffff,$ffff),
- ($0, $700e,$1c38,$660, $3c0, $660, $1c38,$700e,
- $0, $0, $0, $0, $0, $0, $0, $0));
- x:7;y:4);
-
- RectangularCrossCursor : MaskRecord
- = (mask:(($fc3f,$fc3f,$fc3f,$0,$0, $0, $fc3f,$fc3f,
- $fc3f,$ffff,$ffff,$ffff,$ffff,$ffff,$ffff,$ffff),
- ($0, $180, $180, $180, $7ffe,$180, $180, $180,
- $0, $0, $0, $0, $0, $0, $0, $0));
- x:7;y:4);
-
- HourglassCursor : MaskRecord
- = (mask:(($0, $0, $0, $0, $8001,$c003,$e007,$f00f,
- $e007,$c003,$8001,$0, $0, $0, $0, $ffff),
- ($0, $7ffe,$6006,$300c,$1818,$c30, $660, $3c0,
- $660, $c30, $1998,$33cc,$67e6,$7ffe,$0, $0));
- x:7;y:7);
-
- procedure ResetMouse;
- procedure ShowMouse;
- procedure HideMouse;
- procedure MousePos(var X,Y : word);
- function LeftButton : Boolean;
- function RightButton : Boolean;
- procedure PutMouse(X,Y : word);
- function ButtonPressInfo(Button : byte;
- var PressCount,X,Y : word):boolean;
- function ButtonReleaseInfo(Button : word;
- var PressCount,X,Y : word):boolean;
- procedure SetHorizontalRange(Min,Max : word);
- procedure SetVerticalRange(Min,Max : word);
- function MouseInBox(x1,y1,x2,y2:word) : Boolean;
- procedure SetGraphicsCursor(var maskp : MaskRecord);
- procedure SetTextCursor(sel,start,stop : word);
- procedure MouseRatio(X,Y : Word);
- procedure MotionCounters(var X,Y : Integer);
- procedure LightPenEmulation(f : Boolean);
- procedure ConditionalOff(ux,uy,lx,ly : word);
- procedure DoubleSpeedThreshold(mickey : word);
- procedure SetMouseProcedure(m:word;p:pointer);
- Procedure CursorMirror(var S,D:MaskRecord;F:byte);
- Function MouseMenu(s:string;c:byte;var f:MouseMenuFlags):byte;
-
- (**************************************************************)
-
- Implementation
-
- var
- CrtMode : byte absolute $40:$49;
- MouseHandler : Pointer;
- ExitSave : Pointer;
- Int1BSave : Pointer;
- OldCursor : Pointer;
-
- const
- M1 : word = 0;
- M2 : word = 0;
- M3 : word = 0;
- M4 : word = 0;
- M5 : word = 0;
- M6 : word = 0;
- MaxX : Integer = 639; { EGA F-Mode }
- MaxY : Integer = 349; { " }
- SegPointer : word = $ffff;
- GDriver : integer = Detect;
- GMode : integer = 0;
- AboFlag : Boolean = false;
- Hercules : Boolean = false;
-
- function BitSet(TestByte : Byte; BitNumber : Byte) : Boolean;
- { Testet Bit BitNumber in Byte TestByte }
- begin
- TestByte := TestByte and (1 shl BitNumber);
- BitSet := (TestByte > 0);
- end;
-
- procedure CheckPos(var X, Y : word);
- { Limitiert die Variablen X,Y auf die maximale Bildschirmgröße }
- begin
- if Y > MaxY then Y := MaxY;
- if X > MaxX then X := MaxX;
- end;
-
- procedure Mouse;
- { Ruft den Maustreiber über Interrupt 51d }
- var
- regs: registers;
- begin
- Regs.ax := M1; { CPU-Register für Mauscall setzen }
- Regs.bx := M2;
- Regs.cx := M3;
- Regs.dx := M4;
- Regs.si := M5;
- Regs.di := M6;
- Regs.es :=SegPointer;
- Intr(51,Regs); { Maustreiber aufrufen }
- M1 := Regs.ax; { Ergebnisse in Variablen kopieren }
- M2 := Regs.bx;
- M3 := Regs.cx;
- M4 := Regs.dx;
- end;
-
-
- procedure ShowMouse;
- { Schaltet Mauszeiger ein }
- begin
- M1 := 1;
- Mouse;
- end;
-
- procedure HideMouse;
- { Schaltet Mauszeiger aus }
- begin
- M1 := 2;
- Mouse;
- end;
-
- procedure MousePos(var X,Y : word);
- { Ermittelt Position des Mauszeigers }
- begin
- M1 := 3;
- Mouse;
- X := M3;
- Y := M4;
- if AboFlag then begin
- CloseGraph;
- NoSound;
- writeln('Break');
- halt(1);
- end;
- end;
-
- function LeftButton : Boolean;
- { Testet Status des linken Mausknopfs }
- begin
- M1 := 3;
- Mouse;
- if BitSet(M2,LeftB) then LeftButton := true
- else LeftButton := false;
- end;
-
- function RightButton : Boolean;
- { Testet Status des rechten Mausknopfs }
- begin
- M1 := 3;
- Mouse;
- if BitSet(M2,RightB) then RightButton := true
- else RightButton := false;
- end;
-
- procedure PutMouse(X,Y : word);
- { Setzt Mauszeiger auf bestimmte Position }
- begin
- CheckPos(X,Y);
- M1 := 4;
- M3 := X;
- M4 := Y;
- Mouse;
- end;
-
- Function ButtonPressInfo(Button : byte;
- var PressCount,X,Y : word):boolean;
- { Testet Anzahl der Mausknopfbetätigungen seit letztem Aufruf }
- { Button: 0=leftb, 1=rightb }
- begin
- M1 := 5;
- M2 := Button;
- Mouse;
- ButtonPressInfo:=BitSet(M1,Button);
- PressCount := M2; { Knopfbetätigungen seit letztem Aufruf}
- X := M3; { Cursor-Position bei letzter Betätigung}
- Y := M4; { " }
- end;
-
- Function ButtonReleaseInfo(Button : word;
- var PressCount,X,Y : word):boolean;
- { Testet Anzahl der Mausknopfloslassungen seit letztem Aufruf }
- { Button: 0=leftb, 1=rightb }
- begin
- M1 := 6;
- M2 := Button;
- Mouse;
- ButtonReleaseInfo := not BitSet(M1,Button);
- PressCount := M2; { Loslassungen seit letztem Aufruf}
- X := M3; { Cursor-Position bei letztem Loslassen}
- Y := M4; { " }
- end;
-
- procedure SetHorizontalRange(Min,Max : word);
- { setzt horizontalen Mauszeigerbereich }
- var Dummy:word;
- begin
- CheckPos(Min,Dummy);
- CheckPos(Max,Dummy);
- M1 := 7;
- M3 := Min;
- M4 := Max;
- Mouse;
- end;
-
- procedure SetVerticalRange(Min,Max : word);
- { setzt vertikalen Mauszeigerbereich }
- var Dummy:word;
- begin
- CheckPos(Dummy,Min);
- CheckPos(Dummy,Max);
- M1 := 8;
- M3 := Min;
- M4 := Max;
- Mouse;
- end;
-
- function MouseInBox(x1,y1,x2,y2:word) : Boolean;
- { Testet, ob sich Mauszeiger in bestimmten Bildschirmbereich befindet }
- var x,y:word;
- begin
- if x2<x1 then begin x:=x1; x1:=x2; x2:=x; end;
- if y2<y1 then begin y:=y1; y1:=y2; y2:=y; end;
- MousePos(x,y);
- MouseInBox:=( ((x>=x1) and (x<=x2-1)) and
- ((y>=y1) and (y<=y2-1)) );
- end;
-
- procedure SetGraphicsCursor(var maskp : MaskRecord);
- { Setzt neue Form des Grafik-Mauszeigers }
- begin
- if OldCursor <> @maskp then begin
- OldCursor := @maskp;
- with Maskp do begin
- M1 := 9;
- M2 := X;
- M3 := Y;
- M4 := ofs(Mask);
- SegPointer := seg(Mask);
- end;
- end;
- Mouse;
- end;
-
- procedure SetTextCursor(sel,start,stop : word);
- { setzt Größe und Art des Mauszeigers im Textmodus }
- begin
- M1 := 10;
- M2 := sel; { Hardware- oder Software-Cursor }
- M3 := start; { Scanline oder Bildschirmmaske }
- M4 := stop; { Scanline oder Zeigermaske }
- Mouse;
- end;
-
- procedure MouseRatio(X,Y : Word);
- { Setzt Empfindlichkeit des Mauszeigers }
- begin
- M1 := 15;
- M3 := X;
- M4 := Y;
- Mouse;
- end;
-
- procedure MotionCounters(var X,Y : Integer);
- { Gibt Distanz in Maus-Einheiten seit letztem Aufruf zurück }
- { 1 Mickey = 1/200 inch }
- var
- x1,y1:longint;
- begin
- M1:=11;
- Mouse;
- if M3 > $fff then x1:=m3-65536 else x1:=m3;
- if M4 > $fff then y1:=m4-65536 else y1:=m4;
- X:=x1;
- Y:=y1;
- end;
-
- procedure LightPenEmulation(f : Boolean);
- { Schaltet Light Pen Emulation an/aus }
- { Nur zur Vollständigkeit implementiert }
- begin
- if f then M1:=13 else M1:=14;
- Mouse;
- end;
-
- procedure ConditionalOff(ux,uy,lx,ly : word);
- { Schaltet Mauszeiger aus, wenn er sich im angegeben Bereich befindet }
- begin
- M1:=16;
- if ux < lx then begin
- M3:=ux;
- M5:=lx;
- end else begin
- M3:=lx;
- M5:=ux;
- end;
- if uy < ly then begin
- M4:=uy;
- M6:=ly;
- end else begin
- M4:=ly;
- M6:=uy;
- end;
- Mouse;
- end;
-
- procedure DoubleSpeedThreshold(mickey : word);
- { Legt Mausgeschwindigkeit fest, bei der sich
- Mausempfindlichkeit verdoppelt }
- begin
- M1:=19;
- M4:=mickey; { Schwelle in Mickeys/Sekunde }
- Mouse;
- end;
-
- procedure MouseCallExit;
- { Exit-Prozedur des Maustreiber-Aufrufs }
- { Nötig, weil Interrupt Procedure mit RETI statt mit RET FAR
- beendet wird. Maustreiber erwartet RET FAR. }
- begin
- Inline ($5D/$58/$58/$89/$EC/$5D/$07/$1F/
- $5F/$5E/$5A/$59/$5B/$58/$CB);
- { pop bp ; pop ax ; pop ax ; mov sp,bp ; pop es ; pop ds ;
- pop di ; pop si ; pop dx ; pop cx ; pop bx ; pop ax ;
- ret far}
- end;
-
- Procedure UserHandlerCall(Mask,Button,X,Y:word);
- { Ruft User Maus Interrupt Prozedur }
- { Nötig, weil Turbo Pascal V4 keine prozeduralen Parameter erlaubt. }
- Inline($FF/$1E/MouseHandler); { call far [MouseHandler] }
-
- Procedure MouseInterrupt(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:word);
- { Diese Prozedur wird vom Maustreiber bei in Mask festgelegten
- Bedingungen gerufen. Von ihr wird der User Handler gerufen. }
- Interrupt;
- Begin
- UserHandlerCall(AX,BX,CX,DX);
- MouseCallExit;
- End;
-
- procedure SetMouseProcedure(m:word;p:pointer);
- { Teilt Maustreiber Addresse von MouseInterrupt und Event-Maske mit }
- begin
- M1:=12;
- M3:=m;
- M4:=Ofs(MouseInterrupt);
- SegPointer:=Seg(MouseInterrupt);
- MouseHandler:=p; { Adresse des User Handlers }
- Mouse;
- end;
-
- Function MouseMenu(s:string;c:byte;var f:MouseMenuFlags):byte;
- { Menüzeile am unteren Bildrand einschalten, angeklickte
- Auswahl als Funktionswert zurückgeben, Flags ändern }
- var
- test,d:boolean;
- color,ncolor,i,k,p1,p2,p3:byte;
- boxl,count,x,y,y1:word;
- code:integer;
- text:string;
- wbar:string;
- begin
- SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
- if Length(s) > 0 then d:=true else d:=false;
- p1:=1;
- boxl:=trunc(GetMaxX/c);
- MouseMenu:=0;
- MousePos(x,y);
- if y > GetMAxY-25 then begin
- test:=buttonpressinfo(LeftB,count,x,y1);
- setgraphicscursor(PointinghandCursor);
- end;
- while (y > GetMaxY-25) or d do begin
- test:=buttonpressinfo(LeftB,count,x,y1);
- ShowMouse;
- if (count > 0) or d then begin
- HideMouse;
- if d then begin
- SetViewPort(0,GetMaxY-25,GetMaxX,GetMaxY,ClipOn);
- ClearViewPort;
- SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
- end;
- for i:=1 to c do begin
- if MouseInBox(boxl*(i-1),GetMaxY-20,boxl*i-5,GetMaxY)
- and (count > 0) then begin
- MouseMenu:=i; { Funktionswert zurückgeben }
- f[i]:=not f[i]; { zugehöriges Flag komplementieren }
- Sound(440); { akustische Rückmeldung }
- delay(2);
- NoSound;
- MousePos(x,y);
- SetViewPort(0,0,GetMaxX,GetMaxY-25,ClipOn);
- exit;
- end;
- if d then begin
- color:=GetColor; { Menüleiste zeichnen }
- SetColor(GetMaxColor);
- Rectangle(boxl*(i-1),GetMaxY-20,boxl*i-5,GetMaxY);
- if f[i] then begin
- p1:=pos(':',copy(s,p1,length(s)))+p1;
- p2:=pos(';',copy(s,p1,length(s)));
- p3:=p2;
- end else begin
- p2:=pos(':',copy(s,p1,length(s)));
- p3:=pos(';',copy(s,p1,length(s)));
- end;
- if p2 = 0 then p2:=length(s);
- text:=copy(s,p1,p2-1);
- val(copy(text,1,2),ncolor,code);
- if copy(text,1,2) = '00' then begin
- SetColor(GetMaxColor);
- text:=copy(text,3,length(text));
- wbar:='';
- for k:=1 to length(text)+1 do wbar:=wbar+'█';
- OutTextXY(boxl*(i-1)+3,GetMaxY-10,wbar);
- SetColor(0);
- end;
- if ncolor > 0 then begin
- if ncolor > GetMaxColor then ncolor := GetMaxColor;
- SetColor(ncolor);
- text:=copy(text,3,length(text));
- end;
- p1:=p3+p1;
- OutTextXY(boxl*(i-1)+5,GetMaxY-10,text);
- SetColor(color);
- end;
- end;
- ShowMouse;
- end;
- MousePos(x,y);
- d:=false;
- end;
- SetViewPort(0,0,GetMaxX,GetMaxY-25,ClipOn);
- end;
-
- function BitInvert(b:word):word;
- { Inveriert Bitfolge in wort b : fedcba9876543210 -> 0123456789abcdef }
-
- inline ($58/$B9/$10/$00/$33/$DB/$D1/$D0/$D1/$DB/$E2/$FA/$8B/$C3);
- { pop ax; mov cx,16; xor bx,bx; rcl ax,1; rcr bx,1;loop; mov ax,bx }
-
- Procedure CursorMirror(var S,D:MaskRecord;F:byte);
- { Kopiert und spiegelt Mauszeiger-Masken }
- Var
- i,k:byte;
- Begin
- for i:= 0 to 1 do begin
- for k:= 0 to 15 do begin
- if (F and 1) > 0 then D.mask[i,k]:=S.mask[i,15-k]
- else D.mask[i,k]:=S.mask[i,k];
- if (F and 2) > 0 then D.mask[i,k]:=BitInvert(D.mask[i,k]);
- end;
- end;
- if (F and 1) > 0 then D.y:=15-S.y else D.y:=S.y;
- if (F and 2) > 0 then D.x:=15-S.x else D.x:=S.x;
- end;
-
- procedure ResetMouse;
- { Initialisiert Maustreiber, testet Bildschirmmodus, setzt bei
- Herkuleskarte richtigen Bildschirmmodus und ermittelt maximalen
- Mauszeigerbereich }
- var
- size:word;
- save:boolean;
- begin
- DetectGraph(GDriver,Gmode);
-
- { Mit diesem Trick versteht der Maustreiber die Herkuleskarte }
-
- if GDriver = HercMono then begin
- CrtMode := 6;
- Hercules := true;
- end;
-
- M1 := 0;
- Mouse;
- MaxX:=GetMaxX;
- MaxY:=GetMaxY;
- SetHorizontalRange(0,MaxX);
- SetVerticalRange(0,Maxy);
- end;
-
- Procedure CallOld1B;
- Inline ($9C/$FF/$1E/Int1BSave);
- { pushf ; call far Int1BSave }
- { rufe alten Interrupt 1B Handler }
-
- {$F+} Procedure Int1B; Interrupt; {$F-}
- { Setzt Abbruch-Flag, wenn Break gedrückt wird.
- Der Abbruch erfolgt, sobald MousePos aufgerufen wird }
- Begin
- SetIntVec($1B,Int1BSave);
- CallOld1B;
- AboFlag:=true;
- End;
-
- {$F+} Procedure MouseExit; {$F-}
- { Mouse Unit Exit Handler }
- { Setzt Bildschirmmodus auf Text Modus }
- Begin
- M1 := 0;
- Mouse;
- nosound;
- If Hercules then CrtMode := 7;
- ExitProc:=ExitSave;
- end;
-
- { Unit-Initialisierung }
- begin
- M1 := 0;
- Mouse;
- if not (M1=65535) then begin {Testen, ob Maustreiber vorhanden}
- CloseGraph;
- ClrScr;
- GotoXY(20,12);
- Write('MS Maustreiber nicht installiert !');
- Halt(1);
- end;
- MaxX:=79;
- MaxY:=24;
- ClrScr;
-
- CursorMirror(LeftArrowCursor,RightArrowCursor,2);
- CursorMirror(UpArrowCursor,DownArrowCursor,1);
- CursorMirror(StandardCursor,InvertedCursor,3);
- ExitSave:=ExitProc;
- ExitProc:=@MouseExit;
- GetIntVec($1B,Int1BSave);
- SetIntVec($1B,@Int1B);
- end.