676 lines
13 KiB
C++
676 lines
13 KiB
C++
;/* GDIMACRO.INC - GDI macros
|
||
|
||
LMHLockCnt equ byte ptr 3
|
||
wptr equ word ptr
|
||
bptr equ byte ptr
|
||
|
||
PtoLMH macro r1,r2
|
||
ifnb <r2>
|
||
mov r1,[r2 - 2]
|
||
else
|
||
mov r1,[r1 - 2]
|
||
endif
|
||
endm
|
||
|
||
LMHtoP macro r1,r2 ;; Local Movable Handle to pointer
|
||
ifnb <r2>
|
||
mov r1,[r2]
|
||
else
|
||
mov r1,[r1]
|
||
endif
|
||
endm
|
||
|
||
LMHtoPES macro r1,r2 ;; Local Movable Handle to ptr, deref vi ES
|
||
ifnb <r2>
|
||
mov r1,es:[r2]
|
||
else
|
||
mov r1,es:[r1]
|
||
endif
|
||
endm
|
||
|
||
LMPsize macro r1,r2 ;; Local Movable pointer size
|
||
mov r1,-4[r2]
|
||
endm
|
||
|
||
|
||
LockDataSegment macro
|
||
endm
|
||
|
||
|
||
UnlockDataSegment macro
|
||
endm
|
||
|
||
farLockDataSegment macro
|
||
endm
|
||
|
||
|
||
farUnlockDataSegment macro
|
||
endm
|
||
|
||
|
||
; NOTE: The lock/unlock macros are not going to check
|
||
; for under/overflow. Its highly unlikely that
|
||
; it will occur, and if it does, we'll be hosed
|
||
; anyway....
|
||
|
||
|
||
LLock macro r
|
||
inc LMHLockCnt[r] ;;Increment ref count
|
||
endm
|
||
|
||
LUnlock macro r
|
||
dec LMHLockCnt[r] ;;Decrement reference count
|
||
endm
|
||
|
||
LLocked? macro r
|
||
cmp LMHLockCnt[r],0 ;; is the handle locked?
|
||
endm
|
||
|
||
LLockES macro r
|
||
inc es:LMHLockCnt[r] ;;Increment ref count
|
||
endm
|
||
|
||
LUnlockES macro r
|
||
dec es:LMHLockCnt[r] ;;Decrement reference count
|
||
endm
|
||
|
||
LLockedES? macro r
|
||
cmp es:LMHLockCnt[r],0 ;; is the handle locked?
|
||
endm
|
||
|
||
; The jmpnext macro and associated symbols are used to generate
|
||
; the fall-through chain and generate the labels required for
|
||
; error checking.
|
||
|
||
??ji = 0 ;;Initial index value
|
||
|
||
jmpnext macro e
|
||
jn %??ji,%(??ji+1),e ;;Set next label
|
||
endm
|
||
|
||
jn macro i,j,e
|
||
.sall
|
||
??ji&i:
|
||
.xall
|
||
ifb <e> ;;If not the end of the chain
|
||
db 03dh ;;mov bx, next two bytes
|
||
errn$ ??ji&j,+2 ;;mext lable must be two bytes away
|
||
endif
|
||
??ji=j ;;increment counter
|
||
endm
|
||
|
||
ifdef DEBUG
|
||
ifndef ?HELPER
|
||
ExternFP ValidateHandle
|
||
endif
|
||
endif
|
||
|
||
;*
|
||
;* Valid? macro Handle,Error_exit,LowLimit,UpLimit
|
||
;*
|
||
;* Validate an object handle. A valid handle must 1)not be NULL 2)be for
|
||
;* an object of the specified type.
|
||
;*
|
||
;*
|
||
;* Macro Arguments:
|
||
;*
|
||
;* Handle - object handle
|
||
;* Error_exit - the next instruction to execute if an invalid obj
|
||
;* LowLimit, UpLimit - Range of the possible object type
|
||
;*
|
||
;* Return:
|
||
;* DS:BX - pointer to the object
|
||
;*
|
||
;* Trashes:
|
||
;* AX,BX,CX,DX
|
||
;*
|
||
|
||
Valid? macro Handle,Error_exit,LowLimit,UpLimit
|
||
local ValidHandle,Invalidexit
|
||
|
||
ifdef DISABLE
|
||
ifdef DEBUG
|
||
|
||
;******************************************************************************
|
||
;
|
||
; Object handle validation in a debug version
|
||
;
|
||
;******************************************************************************
|
||
|
||
push dx
|
||
mov bx, LowLimit
|
||
ifnb <UpLimit>
|
||
mov dx, UpLimit
|
||
else
|
||
mov dx, LowLimit
|
||
endif
|
||
|
||
cCall <far ptr ValidateHandle>,<Handle,bx,dx>
|
||
pop dx
|
||
or ax,ax
|
||
jnz ValidHandle
|
||
jmp Error_exit
|
||
else
|
||
|
||
;******************************************************************************
|
||
;
|
||
; Object handle validation in a retail version
|
||
;
|
||
;******************************************************************************
|
||
|
||
mov bx,Handle ; NULL handle validation
|
||
or bx,bx
|
||
jz Invalidexit
|
||
|
||
LMHtoP bx ; dereference for object pointer
|
||
|
||
mov ax,ilObjType[bx] ; Validate the object type
|
||
|
||
irp stock_type,<OBJ_PEN,OBJ_BRUSH,OBJ_FONT,OBJ_BITMAP,OBJ_PALETTE>
|
||
ife stock_type-LowLimit
|
||
and ax,NOT OBJ_FLAGS ; mask only for possible stock obj
|
||
endif
|
||
endm
|
||
|
||
ifnb <UpLimit>
|
||
cmp ax,LowLimit ; Check object type range
|
||
jl Invalidexit
|
||
cmp ax,UpLimit
|
||
jle ValidHandle
|
||
else
|
||
cmp ax,LowLimit ; Check a particular object type
|
||
je ValidHandle
|
||
endif
|
||
|
||
Invalidexit:
|
||
xor ax,ax
|
||
jmp Error_exit ; it is not a valid handle
|
||
|
||
endif
|
||
|
||
ValidHandle:
|
||
|
||
else ; !DISABLE
|
||
|
||
mov bx,Handle
|
||
LMHtoP bx
|
||
|
||
endif ; !DISABLE
|
||
endm
|
||
|
||
ValidDebug? macro Handle,LowLimit,UpLimit
|
||
|
||
ifdef DEBUG
|
||
|
||
push bx
|
||
push dx
|
||
mov bx, LowLimit
|
||
ifnb <UpLimit>
|
||
mov dx, UpLimit
|
||
else
|
||
mov dx, LowLimit
|
||
endif
|
||
|
||
cCall <far ptr ValidateHandle>,<Handle,bx,dx>
|
||
pop dx
|
||
pop bx
|
||
|
||
endif
|
||
endm
|
||
|
||
;*
|
||
;* Notify? macro
|
||
;*
|
||
;* Tests if the given dc is hooked, and if it is, calls off to
|
||
;* send a notification to whomever is hooked into the dc notification
|
||
;* hook.
|
||
;*
|
||
;* Macro Arguments:
|
||
;*
|
||
;* hDC - the actual DC handle
|
||
;* lParam - the notification code to send via the hook
|
||
;* errLbl - optional parameter, which gives label to
|
||
;* jump to if notification returns 0
|
||
;*
|
||
;* Trashes:
|
||
;* AX,BX,flags
|
||
;*
|
||
ifdef LATER
|
||
ifndef ?LVB
|
||
ExternFP SendDCNotify
|
||
ExternFP SendInvalidVisRgn
|
||
endif
|
||
Notify? macro hDC,code,param1,param2,errLbl
|
||
mov bx,hDC
|
||
mov bx,[bx]
|
||
mov ax,word ptr lpNotifyProc[bx]
|
||
or ax,word ptr lpNotifyProc+2[bx]
|
||
jz @F
|
||
push hDC
|
||
mov ax,code
|
||
push ax
|
||
mov ax,param1
|
||
push ax
|
||
mov ax,param2
|
||
push ax
|
||
cCall <far ptr SendDCNotify>
|
||
ifnb <errLbl>
|
||
or ax,ax
|
||
endif
|
||
ifnb <errLbl>
|
||
jnz @F
|
||
jmp errLbl
|
||
endif
|
||
@@:
|
||
endm
|
||
|
||
|
||
;* VNotify?
|
||
;*
|
||
;* Tests if the given dc is hooked and has an invalid visrgn. If
|
||
;* it does, then a notification is sent to the dc hook.
|
||
;*
|
||
;* Warning:
|
||
;* if we call the call-back, the gdi heap can be compacted,
|
||
;* so no dereferenced handles can be relied on after making
|
||
;* this call.
|
||
;*
|
||
;* Entry:
|
||
;* hDC - handle to dc to check and send notifications
|
||
;* reg - scratch register to use
|
||
;*
|
||
;* Exit:
|
||
;* reg - trashed
|
||
;* flags - trashed
|
||
;*
|
||
VNotify? macro hDC,reg
|
||
mov reg,hDC
|
||
LMHtoP reg
|
||
test byte ptr DCFlags[reg],BadVisRgn
|
||
jz @F
|
||
cCall <far ptr SendInvalidVisRgn>,<hDC>
|
||
@@:
|
||
endm
|
||
|
||
VNotifyPtr? macro reg,hDC
|
||
test byte ptr DCFlags[reg],BadVisRgn
|
||
jz @F
|
||
cCall <far ptr SendInvalidVisRgn>,<hDC>
|
||
@@:
|
||
endm
|
||
endif
|
||
|
||
;-----------------------------------------------------------------------
|
||
; cProcVDO - cProc "Validate Debug Only"
|
||
;
|
||
; Same as cProc, except used for "Validate in Debug Only" entry points.
|
||
; Declares Iname if debug, name if retail.
|
||
;
|
||
cProcVDO macro name,opts,savelist
|
||
ifdef DEBUG
|
||
cProc <I&name>,<opts>,<savelist>
|
||
else
|
||
LabelFP <PUBLIC, I&name>
|
||
cProc <name>,<opts>,<savelist>
|
||
endif
|
||
endm
|
||
|
||
GDIGLOBALLOCK macro Handle,segRegister,offsetRegister
|
||
.lall
|
||
ifndef GlobalLock
|
||
ExternFP GlobalLock
|
||
endif
|
||
cCall <far ptr GlobalLock>,<Handle>
|
||
ifnb <segRegister>
|
||
mov segRegister,dx
|
||
endif
|
||
ifnb <offsetRegister>
|
||
mov offsetRegister,ax
|
||
endif
|
||
.sall
|
||
endm
|
||
|
||
|
||
GDIGLOBALUNLOCK macro Handle
|
||
ifndef GlobalUnlock
|
||
ExternFP GlobalUnlock
|
||
endif
|
||
cCall <far ptr GlobalUnlock>,<Handle>
|
||
endm
|
||
|
||
GDIRequestSem macro
|
||
endm
|
||
|
||
GDIClearSem macro
|
||
endm
|
||
|
||
|
||
; setlbl generates a macro which will declare labels public
|
||
; if "debug" has been defined. The symbol generated will
|
||
; be of the form:
|
||
;
|
||
; filename_label
|
||
;
|
||
; where
|
||
;
|
||
; filename is the parameter given to the setlbl macro,
|
||
; and label is the first parameter given to the lbl macro
|
||
; which is generated by setlbl.
|
||
;
|
||
;
|
||
; lbl is the macro which will define the given label and
|
||
; if "debug" is defined, declare it public.
|
||
;
|
||
;
|
||
; lbl foo,<opt1>,opt2
|
||
;
|
||
; where
|
||
;
|
||
; foo is the name of the label
|
||
; opt1 is an optional second parameter. If present,
|
||
; it must be some combination of
|
||
; proc, label, near, far, byte, word, dword
|
||
; opt2 is an optional third parameter which if present
|
||
; must be "public". It forces the declaration of
|
||
; "foo" to be public.
|
||
|
||
|
||
|
||
setlbl macro filename
|
||
lbl ¯o n,opt1,opt2
|
||
.sall
|
||
ifnb <opt1>
|
||
n opt1
|
||
ifdef debug
|
||
filename&&_&&n equ n
|
||
public filename&&_&&n
|
||
endif
|
||
else
|
||
n:
|
||
ifdef debug
|
||
filename&&_&&n:
|
||
public filename&&_&&n
|
||
endif
|
||
endif
|
||
ifnb <opt2>
|
||
public n
|
||
endif
|
||
.xall
|
||
&endm
|
||
endm
|
||
|
||
|
||
smov macro segreg1,segreg2
|
||
push segreg2
|
||
pop segreg1
|
||
endm
|
||
|
||
jmps macro there
|
||
jmp short there
|
||
endm
|
||
|
||
; structure to allow easy access to components of DWORD.
|
||
|
||
HILO struc
|
||
lo dw ?
|
||
hi dw ?
|
||
HILO ends
|
||
|
||
; structure to allow easy access to components of LP.
|
||
|
||
OFFSEL struc
|
||
off dw ?
|
||
sel dw ?
|
||
OFFSEL ends
|
||
|
||
|
||
;--------------------------------------------------------------------------;
|
||
; ABS
|
||
; Maps the signed integer in AX to a positive signed integer to be
|
||
; returned in AX. If FOO is blank then 8000h is mapped to 7fffh.
|
||
; Since GDI defines MININT as 8000h, we should deal with this case.
|
||
; If FOO is non-blank, 8000h is mapped to 8000h. (Usually bad!)
|
||
; All other integers behave as one would expect with Absolute Value.
|
||
; Entry:
|
||
; AX = signed integer (8000h to 7fffh)
|
||
; Returns:
|
||
; AX = ABS(AX)
|
||
; Trashes:
|
||
; DX, FLAGS
|
||
;
|
||
; History:
|
||
; Tue 29 October 1991 -by- Raymond E. Endres [rayen]
|
||
; Wrote it.
|
||
;--------------------------------------------------------------------------;
|
||
|
||
|
||
ABS macro FOO ;NOTE: default FOO is blank!
|
||
cwd
|
||
xor ax,dx
|
||
sub ax,dx
|
||
ifb <FOO> ;if FOO is blank
|
||
cwd ;remove the 8000h case
|
||
xor ax,dx
|
||
endif
|
||
endm
|
||
|
||
|
||
;--------------------------------------------------------------------------;
|
||
; min_ax
|
||
; returns min of AX and REG
|
||
; Entry:
|
||
; AX = integer
|
||
; REG = general purpose register containing an integer
|
||
; Returns:
|
||
; AX = min(AX,REG)
|
||
; Error Returns:
|
||
; none
|
||
; Registers Destroyed:
|
||
; DX,FLAGS
|
||
; Registers Preserved:
|
||
; BX,CX,SI,DI,DS,ES,BP
|
||
; Calls:
|
||
; none
|
||
; History:
|
||
; Sat Mar 07, 1987 08:39:04p -by- Tony Pisculli [tonyp]
|
||
; wrote it
|
||
;--------------------------------------------------------------------------;
|
||
|
||
|
||
min_ax macro REG
|
||
sub ax,REG
|
||
cwd
|
||
and ax,dx
|
||
add ax,REG
|
||
endm
|
||
|
||
|
||
|
||
;--------------------------------------------------------------------------;
|
||
; max_ax
|
||
; returns max of AX and REG
|
||
; Entry:
|
||
; AX = integer
|
||
; REG = general purpose register containing an integer
|
||
; Returns:
|
||
; AX = max(AX, REG)
|
||
; Error Returns:
|
||
; none
|
||
; Registers Destroyed:
|
||
; DX,FLAGS
|
||
; Registers Preserved:
|
||
; BX,CX,SI,DI,DS,ES,BP
|
||
; Calls:
|
||
; none
|
||
; History:
|
||
; Sat Mar 07, 1987 08:41:38p -by- Tony Pisculli [tonyp]
|
||
; wrote it
|
||
;--------------------------------------------------------------------------;
|
||
|
||
maxintoax macro mem1,mem2
|
||
mov ax,mem1
|
||
max_ax mem2
|
||
endm
|
||
|
||
|
||
max_ax macro REG
|
||
sub ax,REG
|
||
cwd
|
||
not dx
|
||
and ax,dx
|
||
add ax,REG
|
||
endm
|
||
|
||
|
||
|
||
; The following equates are used for defining the target
|
||
; processor to the shift macros.
|
||
|
||
|
||
GENERIC equ 0
|
||
|
||
;CPU equ GENERIC
|
||
;CPU equ 88
|
||
;CPU equ 86
|
||
;CPU equ 186
|
||
CPU equ 286
|
||
;CPU equ 386
|
||
|
||
|
||
|
||
;--------------------------------------------------------------------------;
|
||
; shiftl
|
||
;
|
||
; shiftl is used to implement the advanced shift left immediate
|
||
; (SHL dest,count) functionality of the 286 and 386.
|
||
;
|
||
; Entry:
|
||
; DEST = var to shift
|
||
; COUNT = number to shift by
|
||
; Returns:
|
||
; DEST = DEST shl COUNT
|
||
; Error Returns:
|
||
; none
|
||
; Registers Destroyed:
|
||
; none
|
||
; Registers Preserved:
|
||
; all
|
||
; Calls:
|
||
; none
|
||
; History:
|
||
; Sat Mar 07, 1987 08:44:30p -by- Tony Pisculli [tonyp]
|
||
; wrote it
|
||
;--------------------------------------------------------------------------;
|
||
|
||
|
||
shiftl macro DEST,COUNT
|
||
if (CPU eq 286) or (CPU eq 386)
|
||
shl DEST,COUNT
|
||
else
|
||
REPT COUNT
|
||
shl DEST,1
|
||
ENDM
|
||
endif
|
||
endm
|
||
|
||
|
||
|
||
;--------------------------------------------------------------------------;
|
||
; shiftr
|
||
;
|
||
; shiftr is used to implement the advanced shift right immediate
|
||
; (SHR dest,count) functionality of the 286 and 386.
|
||
;
|
||
; Entry:
|
||
; DEST = var to shift
|
||
; COUNT = number to shift by
|
||
; Returns:
|
||
; DEST = DEST shr COUNT
|
||
; Error Returns:
|
||
; none
|
||
; Registers Destroyed:
|
||
; none
|
||
; Registers Preserved:
|
||
; all
|
||
; Calls:
|
||
; none
|
||
; History:
|
||
; Sat Mar 07, 1987 08:44:52p -by- Tony Pisculli [tonyp]
|
||
; wrote it
|
||
;--------------------------------------------------------------------------;
|
||
|
||
|
||
shiftr macro DEST,COUNT
|
||
if (CPU eq 286) or (CPU eq 386)
|
||
shr DEST,COUNT
|
||
else
|
||
REPT COUNT
|
||
shr DEST,1
|
||
ENDM
|
||
endif
|
||
endm
|
||
|
||
|
||
;--------------------------------------------------------------------------;
|
||
; nop32
|
||
;
|
||
; compensate for bug in the 386 chip and 32-bit string operations.
|
||
;
|
||
;--------------------------------------------------------------------------;
|
||
nop32 macro
|
||
db 067h
|
||
nop
|
||
endm
|
||
|
||
if 0
|
||
*/
|
||
|
||
#ifndef DEBUG
|
||
#include "igdi.inc"
|
||
#endif
|
||
|
||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||
#define MIN(a,b) ((a)<=(b)?(a):(b))
|
||
#define ABS(x) (((x) >= 0) ? (x) : (-(x)))
|
||
#define LBYTE(x) ((BYTE)((x)&0xFF))
|
||
#define HBYTE(y) ((BYTE)(((y)>>8)&0xFF))
|
||
#define LWORD(x) ((short)((x)&0xFFFF))
|
||
#define HWORD(y) ((short)(((y)>>16)&0xFFFF))
|
||
#define MAKELONG(h,l) ((long)(((WORD)l)|(((long)h)<<16)))
|
||
|
||
extern far PASCAL ValidateHandle(HANDLE, short, short);
|
||
#ifdef DISABLE
|
||
#define Valid(Handle, Low, High) ValidateHandle(Handle, Low, High)
|
||
#else
|
||
#define Valid(Handle, Low, High) TRUE
|
||
#endif
|
||
|
||
#ifdef DEBUG
|
||
#define ValidDebug(Handle, Low, High) {if(!ValidateHandle(Handle, Low, High)) return(NULL);}
|
||
#else
|
||
#define ValidDebug(Handle, Low, High) TRUE
|
||
#endif
|
||
|
||
#define GDIGLOBALLOCK(x) GlobalLock(x)
|
||
#define GDIGLOBALUNLOCK(x) GlobalUnlock(x)
|
||
#define GDILOCKRESOURCE(x) LockResource(x)
|
||
#define GDIENTERCRITSEC()
|
||
#define GDIEXITCRITSEC()
|
||
#define LockDataSegment()
|
||
#define UnlockDataSegment()
|
||
#define farLockDataSegment()
|
||
#define farUnlockDataSegment()
|
||
#define GDIRequestSem()
|
||
#define GDIClearSem()
|
||
|
||
#define LOWORD(l) ((WORD)(l))
|
||
#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
|
||
#define SELECTOROF(lp) HIWORD(lp)
|
||
#define OFFSETOF(lp) LOWORD(lp)
|
||
|
||
/*
|
||
endif
|
||
|
||
;*/
|
||
|
||
|