home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PROG_PAS
/
XLIB_TP5.ZIP
/
UNITS
/
X_MOUSE.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-11-21
|
17KB
|
669 lines
unit X_Mouse;
(*
Basic Mouse Routines for Mode X
****** XLIB - Mode X graphics library ****************
****** ****************
****** Written By Themie Gouthas ( C-Version ) ****************
****** Converted By Christian Harms in TP ****************
Gouthas : egg@dstos3.dsto.gov.au or teg@bart.dsto.gov.au
Harms : harms@minnie.informatik.uni-stuttgart.de
documentation in german and english
*)
(* Es werden die letzten 42 Bytes des Bildschirmspeicher zum schnellen *)
(* Zwischenschpeichern des Maushintergrunds genutzt ! *)
(* The last 42 Bytes of Video-RAM are used to same the Mouse - Pointer *)
(* BackGround . *)
interface
var ButtonStatus,
MouseX,
MouseY : Word;
OldMouseTyp, (* True, wenn Mausz. sonst nur zur Haelfe geht *)
(* if your MousePointer only go to the hald of *)
(* screen, set it to true. *)
MouseAction :Boolean; (* Auf true gesetzt, wenn Maus bewegt wird *)
(* Rücksetzen ist dem Programmierer überlassen.*)
(* It will be true, if MousePointer moved. You *)
(* can it use it, by set to false and wait. *)
const MyMouseForm : Array[1..14] of Byte =
($01,$03,$07,$0f,$1f,$3f,$7f,$ff,$ff,$1c,$3c,$7c,0,0);
(* Setzt den Mauszeiger auf Unsichtbar *)
(* Hide the mousepointer *)
procedure HideMouse;
(* Setzt den Mauszeiger auf sichtbar *)
(* Show the mousepointer *)
procedure ShowMouse;
(* Beim Zeichnen auf activ_page muss der Mauszeiger unsichtbar sein. *)
(* While drawing on activ_page mousepointer have to be hiding. *)
(* Installiert einen Maus-event für Mode X. *)
(* Install mouseevent for mode X. *)
procedure MyMouseInit;
(* Deinstalliert den Maus-event. *)
(* Deinstall the mousevent. *)
procedure MyMouseDestroy;
(* Setzt einen MausCursor - eine Bitmaske. *)
(* set a mousecursor - bitmask. *)
procedure DefineMouseCursor(var MouseDef : Array of Byte;Color : Byte);
(* Setzt das Mausfenster, indem sich der Mauszeiger aufhalten kann. *)
(* Set the mousewindow. Mousepointer can't leave this window. *)
procedure SetMouseWindow(x1,y1,x2,y2:Word);
(* Setzt den MausZeiger auf die Position (x,y). *)
(* set the mousepointer to (x,y). *)
procedure SetPosMouse(x,y:Integer);
(* Ist true, wenn die Maus unsichtbar ist. Wenn nach ShowMouse true -> *)
(* ist keine Maus installiert. *)
(* Return true, if mOuse hide. *)
function IsMouseHidden:Boolean;
(* Gibt true, wenn der Mauszeiger in diesem Rechteck ist. *)
(* Return true, if mousepointer in this rectangle. *)
function InBox(x1,y1,x2,y2:Integer):Boolean;
implementation
uses crt,dos,X_Const;
var MouseInstalled, (* True, wenn eigenen Treiber installiert *)
MouseHidden, (* True, wenn Maus unsichtbar *)
InHandler (* True, wenn grad im Maus_Handler *)
: Boolean;
ButtonCount, (* Anzahl der Maustasten *)
MouseColor
: Byte;
OldX,OldY,OldScreenOfs
: Word;
MouseMask : Array[0..168] of Byte;
(* interne Funktion : Restauriert den CursorHintergrund *)
(* SI: ScreenOffset, AX = Y, BX = X *)
procedure restoreBG; assembler;
asm;
push ds
cld
mov cx,X_Const.ScrnLogicalByteWidth
mul cx (* Y*ScreenBreite+ScreenOfs+x/4 *)
add di,ax
sub cx,3
shr bx,1
shr bx,1
add di,bx
mov si,BGSaveOffs
mov ax,$a000
mov es,ax (* ES: zeigt auf ScreenSeg *)
mov ds,ax
mov dx,3ceh (* Graphics controller Index *)
mov ax,008h (* index in GC of Bit Mask Register *)
out dx,ax (* Set bitmask: all of VGA Latches and *)
(* none of CPU *)
mov dx,3c4h (* Sequence Controller Register *)
mov al,002h (* index in SC of Map Mask register *)
out dx,al (* SC register zeigt schon auf Masking Data *)
inc dx
mov al,0fh
out dx,al
mov bx,cx
mov cx,14
@Loop:
movsb
movsb
movsb
add di,bx
loop @Loop
mov dx,3cfh (* restore bitmask to its default, which *)
mov al,$ff (* selects all bits from the CPU and none *)
out dx,al (* of VGA Latches *)
pop ds
end;
(* interne Funktion : Speichert den CursorHintergrund *)
(* SI: ScreenOffset, AX = Y, BX = X *)
procedure getBG; assembler;
asm;
push ds
cld
mov cx,ScrnLogicalByteWidth
mul cx
add si,ax
sub cx,3
shr bx,1
shr bx,1
add si,bx
mov di,BGSaveOffs
mov ax,$a000
mov es,ax
mov ds,ax
mov dx,3ceh (* set bitmask from VGA Latches and none of CPU *)
mov ax,008h
out dx,ax
mov dx,3c4h
mov al,02h
out dx,al
inc dx
mov al,0fh
out dx,al
mov bx,cx
mov cx,14
@Loop:
movsb
movsb
movsb
add si,bx
loop @Loop
mov dx,3cfh (* restore Bitmask from Latches to CPU *)
mov al,$ff
out dx,al
pop ds
end; (* getBG *)
procedure x_Put_Cursor(x,y,TopClip,BottonClip : Integer;
ScrnOfs : Word ); assembler;
var Height,TopRow,NextLine:Word;
asm;
push ds
mov ax,SEG ScrnLogicalByteWidth
mov ds,ax
mov ax,14 (* Zeichenhöhe *)
mov bx,y
(* Clipping für obere Bildschirmgrenze berechnen *)
mov dx,TopClip
sub dx,bx
jle @NotTopClip (* kein Clipping *)
cmp dx,ax
jnl @NoAction (* Unsichtbar, also raus *)
mov cx,dx
sub ax,dx
add bx,dx
jmp @VertClipDone
(* Clipping für untere Bildschirmgrenze berechnen *)
@NotTopClip:
mov dx,BottonClip
sub dx,bx
js @NoAction
mov cx,0
cmp dx,ax
jg @VertClipDone
inc dx
mov ax,dx
(* eigentliche Zeichenroutine / Vorbereitungen *)
@VertClipDone:
mov Height,ax
mov TopRow,cx
mov ax,$A000 (* es point to ScreenSeg *)
mov es,ax
mov ax,bx
mov cx,ScrnLogicalByteWidth
mul cx
mov di,ax
sub cx,3
mov NextLine,cx
mov cx,x
mov bx,cx
shr cx,1
shr cx,1
add di,cx
and bx,3
add di,ScrnOfs
(* eigentliche Zeichenroutine / Zeichnen *)
mov ax,42
mul bx
mov si,OFFSET MouseMask
add si,ax
mov ax,3 (* INC DS:BX und DS:SI to top border *)
mul TopRow
add si,ax
mov dx,3c4h (* Sequence Controller Index *)
mov al,02 (* index in SC of Map Mask Register *)
out dx,al
inc dx
mov ah,byte ptr [Height] (* AH = ScanLine Loop-Counter *)
mov bl,MouseColor
@RowLoop:
mov cx,3 (* Breite in Bytes *)
@ColLoop:
lodsb
out dx,al
mov es:[di],bl
inc di
loop @ColLoop
add di,NextLine
dec ah
jnz @RowLoop
@NoAction:
pop ds
nop
end;
{$F+}
procedure Maus_Handler{(Flags,ax,bx,cx,dx,si,di,es:Word); interrupt}; assembler;
asm;
push ds
push si
push di
push ax
push bx
push cx
push dx
mov ax,SEG ScrnLogicalByteWidth (* Falls DS geaendert *)
mov ds,ax
mov InHandler,True
mov ButtonStatus,bx (* ButtonStatus eintragen *)
test cx,1 (* Wenn Bewegungs-event : *)
jnz @NoAction
cmp OldMouseTyp,true
jne @Weiter
shr cx,1
@Weiter:
mov MouseX,cx
mov MouseY,dx
mov MouseAction,true
cmp MouseHidden,true
je @NoAction
(* WaitVSyncStart *)
mov dx,3dah
@1: in al,dx
test al,8
jnz @1
@2: in al,dx
test al,8
jz @2
mov di,OldScreenOfs
mov ax,OldY
mov bx,OldX
call restoreBG
mov si,X_Const.ScreenOfs
mov ax,MouseY
mov bx,MouseX
mov OldScreenOfs,si
mov OldY,ax
mov OldX,bx
call getBG
push MouseX
push MouseY
xor ax,ax
push ax
mov ax,GetMaxY
push ax
push X_Const.ScreenOfs
call x_Put_Cursor
@NoAction:
mov InHandler,false
pop dx
pop cx
pop bx
pop ax
pop di
pop si
pop ds
end;
{$F-}
procedure MyMouseInit; assembler;
asm;
cmp MouseInstalled,True (* Wenn schon installiert, raus *)
je @EndNo
xor ax,ax (* Wenn kein Maus-Device, raus *)
int 33h
or ax,ax
jz @EndNo
mov ButtonCount,bl
mov ax,02 (* Hide Cursor *)
int 33h
mov ax,07h (* Set Min/Max horiz. Position *)
mov cx,0
mov dx,GetMaxX
sub dx,8
shl dx,1 (* Cursorbewegung aller 2 Pixel ? *)
int 33h
mov ax,08h (* Set Min/Max vertical Position *)
mov cx,0
mov dx,GetMaxY
int 33h
mov ax,0fh (* Set hor/ver. Speed *)
mov cx,4
mov dx,4
int 33h
mov ax,12 (* Define event-Handler *)
mov bx,SEG Maus_Handler
mov es,bx
mov dx,OFFSET Maus_Handler
mov cx,1fh
int 33h
@EndYes : mov MouseInstalled,true (* Default - Werte *)
mov MouseHidden,true
mov MouseX,1
mov MouseY,1
@EndNo : (* Ende ohne etwas zu installieren *)
end; (* MyMouseInit *)
procedure SetMouseWindow(x1,y1,x2,y2:Word); assembler;
asm
mov ax,07h (* Set Min/Max horiz. Position *)
mov cx,x1
mov dx,x2
sub dx,7
shl dx,1 (* Cursorbewegung aller 2 Pixel ? *)
int 33h
mov ax,08h (* Set Min/Max vertical Position *)
mov cx,y1
mov dx,y2
int 33h
end;
procedure MyMouseDestroy; assembler;
asm;
cmp MouseInstalled,False (* Wenn nicht installiert, raus *)
je @EndNo
call HideMouse
mov ax,12 (* Install event-Handler *)
xor cx,cx (* Disable all events *)
int 33h
mov MouseInstalled,false;
@EndNo:
end;
(*---------------------------------------------------------------------- *)
(* Local function that updates the cursor position *)
(* *)
(* Destroys SI,DI,AX,BX *)
(* *)
(*---------------------------------------------------------------------- *)
procedure update_cursor; assembler;
asm
call WaitVsyncStart
mov di,[OldScreenOfs] (* Delete cursor (restore old background) *)
mov ax,[OldY]
mov bx,[OldX]
call restorebg
mov si,[ScreenOfs] (* Save cursor background *)
mov ax,[MouseY]
mov bx,[MouseX]
mov [OldScreenOfs],si
mov [OldY],ax
mov [OldX],bx
call getbg
push [ScreenOfs] (* Draw the cursor *)
mov ax,[ScrnPhysicalHeight]
push ax
mov ax,0
push ax
push [OldY]
push [OldX]
call x_put_cursor
add sp,10
ret
end;
(*---------------------------------------------------------------------- *)
(* x_update_mouse - Forces the mouse position to be updated and cursor *)
(* to be redrawn. *)
(* *)
(* *)
(* Note this function is useful when you have set "MouseFrozen" to true. *)
(* Allows the cursor position to be updated manually rather than *)
(* automatically by the installed handler. *)
(* *)
(* *)
(* Written by Themie Gouthas *)
(*---------------------------------------------------------------------- *)
procedure x_update_mouse; assembler;
asm
cmp [MouseInstalled],FALSE (* Make sure our handler is installed *)
je @@Done
cmp [MouseHidden],FALSE (* If cursor is already hidden exit *)
jne @@Done
push si
push di
mov ax,03h (* FUNC 3: get cursor pos / button status *)
int 33h (* Update position variables first *)
shr cx,1
mov [MouseX],cx
mov [MouseY],dx
mov [ButtonStatus],bx (* Update button status *)
call update_cursor
pop di
pop si
@@Done:
pop bp
ret
end;
(*---------------------------------------------------------------------- *)
(* x_position_mouse - Positions the mouse cursor at the specified location *)
(* *)
procedure x_position_mouse(x,y:Word); assembler;
asm
@@WaitEndOfHandler: (* Make sure handler not currently active *)
mov bl,[inhandler]
or bl,bl
jnz @@WaitEndOfHandler
mov ax,4
mov cx,X
mov dx,Y
mov [MouseX],cx
mov [MouseY],dx
shl cx,1
mov [inhandler],1
int 33h
(* The handler doesnt get called so need *)
(* to update manually; *)
cmp [MouseHidden],FALSE
jne @@NotVisible
push di
push si
call update_cursor
pop si
pop di
@@NotVisible:
mov [inhandler],0
pop bp
ret
end;
procedure SetPosMouse(x,y:Integer); assembler;
asm;
mov ax,4
mov cx,x
shl cx,1
mov dx,y
int 33h
end;
procedure HideMouse; assembler;
asm;
cmp MouseInstalled,false (* Kein Handler -> raus *)
je @NoAction
cmp MouseHidden,false (* wenn unsichtbar -> raus *)
jne @NoAction
@WaitEndOfHandler:
mov cl,InHandler
or cl,cl
jnz @WaitEndOfHandler
mov MouseHidden,True
mov di,OldScreenOfs
mov ax,OldY
mov bx,OldX
call restoreBG
@NoAction:
end;
procedure ShowMouse; assembler;
asm;
cmp MouseInstalled,false
je @NoAction
cmp MouseHidden,false
je @NoAction
@WaitEndOfHandler:
mov cl,InHandler
or cl,cl
jnz @WaitEndOfHandler
mov si,X_Const.ScreenOfs
mov ax,MouseY
mov bx,MouseX
mov OldScreenOfs,si
mov OldY,ax
mov OldX,bx
call getBG
push OldX
push OldY
xor ax,ax
push ax
mov ax,X_Const.GetMaxY
push ax
push X_Const.ScreenOfs
call x_Put_Cursor
mov MouseHidden,False
@NoAction:
end;
procedure DefineMouseCursor(var MouseDef : Array of Byte;
Color : Byte); assembler;
asm;
cmp MouseInstalled,false
je @NoAction
push ds
mov al,Color
mov MouseColor,al
mov ax,ds (* ES:DI Feld für alle Pixelsachen vom *)
mov es,ax (* Mauszeiger *)
mov di,OFFSET MouseMask
lds si,DWord Ptr [MouseDef]
xor cl,cl
@Loop:
push si
mov dh,14
@RowLoop:
lodsb
xor ah,ah
shl ax,cl
mov bl,al
and bl,0fh
mov es:[di],bl
inc di
shr al,1
shr al,1
shr al,1
shr al,1
stosw
dec dh
jnz @RowLoop
pop si
inc cl
cmp cl,4
jne @Loop
pop ds
@NoAction:
end;
function InBox(x1,y1,x2,y2:Integer):Boolean;
begin;
InBox:= (MouseX>=X1)and(MouseX<=X2)and(MouseY>=y1)and(MouseY<=y2);
end;
function IsMouseHidden:Boolean;
begin;
IsMouseHidden:=MouseHidden;
end;
(* UNIT - CODE *)
begin;
MouseInstalled := false;
MouseHidden := True;
InHandler := false;
BGSaveOffs := BGSaveOffs-14*3-1;
OldMouseTyp := true;
end.