; MyFonts Bitmap Fonts, Copr. 1993, 1994 Matthias K”ppe

		INCLUDE	myfodef.asm
		INCLUDE	ccachdef.asm

	; Publics

		PUBLIC	WriteBmpText, CpiCreateList, WinCreateList, \
			WinHugeCreateList

	;
	; Macro definitions
	;

MetaHeader	MACRO
		CALL	NEAR PTR CopyString
		JZ	@@NR
		PUSH	LocalSize
		PUSH	ArgSize
		ADD	DX, 3			; s len + 3
		PUSH	DX			; Locals to be stored
		MOV	AX, 3			; pushed
		CALL	[ExtSave]
		TEST	MetaState, ms_Record
		JNZ	@@NR
		MOV	AX, MetaOrigin.x
		ADD	atx, AX
		MOV	AX, MetaOrigin.y
		ADD	aty, AX
@@NR:		TEST	MetaState, ms_Draw
		JZ	@@ND
		ENDM

BmpLocals	MACRO
%		LOCAL	sofs: WORD, scopy: BYTE: 256, \		recorded
			ColSel: WORD, yDelta: WORD, MaxLen: WORD, \
			FontLen: WORD, sEntry: BYTE: 2, \
			CCach: DWORD, Bitmap: DWORD, XPos: WORD, \
			MinPos: WORD, MaxPos: WORD, WinDelta: WORD, \
			CurAttrib: WORD, NextAttrib: WORD = LocalSize
		ENDM

CODE		SEGMENT BYTE PUBLIC

	;
	; Generic Bitmap Font Handling
	;

WriteBmpText	PROC FAR
		ARG	Marker: BYTE, s: DWORD, Color: WORD, Attr: BYTE, \
			CharSpace: WORD, aty: WORD, atx: WORD, \
			Item: DWORD, CreateProc: WORD = ArgSize
		BmpLocals
		enter	LocalSize, 0
		MetaHeader

		call	SaveRegs

		les	si, Item
		mov	al, es:[si].TFontRec.EntrySize
		mov	sEntry, al
		mov	ax, es:[si].TFontRec.BitmapDelta
		mov	WinDelta, ax
		mov	al, Attr
		xor	ah, ah
		mov	CurAttrib, ax

		mov	ax, es:[si].TFontRec.FontLength
		mov	FontLen, ax
		mov     MaxLen, ax
		call	NEAR PTR ClipY
		jnc	@@10				; something shown

		test	Attr, ftVerticalMoves
		jz	@@15				; nothing shown
@@10:
		push	ax				; store y start
		call	NEAR PTR GetBitPtr		; ES:SI bitmap
		mov	WORD PTR Bitmap[0], si
		mov	WORD PTR Bitmap[2], es
		les	di, TempMem			; ES:DI storage area
		call    CreateProc
		and	CurAttrib, NOT (ftCharStart + ftForeColor + ftBkColor)
		mov	bx, di				; ES:BX room for CCach
		mov	WORD PTR CCach[0], bx
		mov	WORD PTR CCach[2], es
		pop	dx				; get y start
		mov	ax, minPos
		sub	atx, ax
		add	ax, atx

	; Vertical Loop

@@VertLoop:

	; Attribute Loop

@@AttrLoop:
		push	ax dx				; coords
		mov	cx, MaxLen			; length
		mov	si, 3				; 3 coloumns
		push	WORD PTR es:[bx]		; store first word

		mov	di, Color
		call	SetupCache
		mov	NextAttrib, -1			; assume no new loop

		push	ds
		lds	si, Bitmap

	; Source-Coloumn Loop

@@1:
		add	WORD PTR es:[bx], 8		; next list entry
		mov	bx, es:[bx]			; CCach -> List

		mov	ax, es:[bx+2]			; high offset word
		inc	ax
		jz	@@9				; vertical movement

		inc	ax
		jz	SHORT @@8			; item is empty

	; Attribute (WORD @ 4) Handling

		mov	ax, es:[bx+4]			; check Attr
		and	ax, NOT ftCharStart
		cmp	ax, CurAttrib
		je	@@3				; Attr is OK

		cmp	NextAttrib, -1
		jnz	SHORT @@8			; already set

		mov	NextAttrib, ax			; new loop is needed
@@8:
		mov	bx, WORD PTR CCach[0]		; -> CCach
		jmp	@@1				; next item
@@3:
	; Segment (WORD @ 2) Handling

		mov	ax, -2			; mark as empty
		xchg	ax, es:[bx+2]		; bitmap segment
		or	ax, ax
		jz	SHORT @@S

		mov	ds, ax
		push	si
		mov	si, es:[bx]
		add	si, yDelta
		push	si
		jmp	SHORT @@T
@@S:
		mov	ax, es:[bx]		; bitmap offset
		push	si
		ADD	ax, si			; DS:AX Zeiger auf Bitmap
		add	ax, yDelta
		push	ax
@@T:
		mov	ax, es:[bx+6]		; BX horiz pos
		add	ax, AtX
		mov	bx, WORD PTR CCach[0]
		call	GotoPos			; ES:DI Cache addr to write in
						; CL shift value
		pop	si			; DS:SI Zeiger auf Bitmap

		push	bx di
		NextCol	di			; DI 2nd coloumn
		pop	bx			; BX 1st coloumn
		mov	dx, MaxLen

		test	Attr, ftBold
		jz	@@C

	; Inner loop: Bolden bitmap

		push	bp
		mov	bp, di
		NextCol	bp

@@B:		lodsb
		mov	ah, al
		xor	al, al
		shr	ax, cl
		push	dx
		mov	dx, ax
		shr	dx, 1
		jnc	SHORT @@B1
		or	BYTE PTR es:[bp], 80h
@@B1:		or	ax, dx
		pop	dx
		or	es:[di], al
		or	es:[bx], ah
		inc	di
		inc	bx
		dec	dx
		jnz	@@B
		pop	bp
		jmp	SHORT @@5

	; Inner loop: Copy bitmap

@@C:		lodsb
		mov	ah, al
		xor	al, al
		shr	ax, cl
		or	es:[di], al
		or	es:[bx], ah
		inc	di
		inc	bx
		dec	dx
		jnz	@@C

@@5:		pop	bx si
		jmp	@@1

@@9:		POP	DS
		push	bx			; store entry offset
		push	es:[bx+4]		; store vertical movement
		push	es:[bx+14]		; store next horiz start
						; (x of next entry!)
		mov	ax, es:[bx]		; get end pos
		add	ax, AtX
		mov	bx, WORD PTR CCach[0]
		call	SetRightPos

	; Prepare for next attribute

		mov	ax, NextAttrib
		cmp	ax, -1
		jz	SHORT @@A2

		mov	dx, CurAttrib
		xor	dx, ax
		test	dx, ftForeColor
		jz	SHORT @@A1

		rol	Color, 8
@@A1:
		mov	CurAttrib, ax
		les	bx, CCach

		add	sp, 6
		pop	WORD PTR es:[bx]
		pop	dx ax
		jmp	@@AttrLoop
@@A2:
	; Prepare for next Y

		pop	ax			; get new horizontal start
		pop	cx			; get vertical movement
		or	cx, cx			; movement is zero?
		jz	SHORT @@15		; that's a Shutdown sentinel

		pop	di
		les	bx, CCach
		add	sp, 2			; skip old first word
		mov	WORD PTR es:[bx], di
		pop	dx
		pop	di			; skip old horiz start

		push	ax			; new horiz start
		add	aty, cx
		mov	ax, FontLen
		mov     MaxLen, ax
		call	NEAR PTR ClipY
		mov	dx, ax			; new vert start
		pop	ax			; new horiz start
		jc	SHORT @@15		; & statt dessen: bis zum
						; & n„chsten Vert-Move skippen!

		add	ax, AtX
		jmp	@@VertLoop

	; Shutdown

@@15:
		CALL	RestoreRegs
		mov	dx, 03ceh		; GC
		mov	al, 05h			; Graphics mode
		mov	ah, UserRegArea[3]
		out	dx, ax
@@ND:
		leave
		ret	ArgSize
WriteBmpText	ENDP

	; CopyString creates a local copy of the string on the stack.

CopyString	PROC NEAR
		MOV	BX, SS
		MOV	ES, BX
		MOV	BX, DS
		LDS	SI, s
		LEA	DI, scopy
		CLD
		LODSB
		MOV	CL, AL
		NOT	CL
		MOV	CH, 0
		ADD	DI, CX
		MOV	sofs, CX
		STOSB
		MOV	CL, AL
		MOV	DX, CX
		REP	MOVSB
		MOV	DS, BX
		TEST	MetaState, ms_Record
		retn
CopyString	ENDP

	; Get bitmap pointer proc
	;
	; In:	ES:SI	TFontRec struc
	;
	; Out:	ES:SI	Bitmapped font information

GetBitPtr	PROC NEAR
		MOV	SI, es:[si].TFontRec.FontHandle
		SHL	SI, 3
		PUSH	bx ax
		LES	BX, SharedList
		LES	SI, es:[BX][SI]
		POP	ax bx
		retn
GetBitPtr	ENDP

	; Switch colors proc
	;

SwitchColor	PROC NEAR
		push	bx
		mov	ax, es:[bx+6]		; get end pos
		add	ax, AtX
		mov	bx, WORD PTR CCach[0]
		push	cx dx si
		call	SetRightPos
		pop	si dx cx
		ror	es:[bx].TCacheHeader.chColor, 8		; switch colors

	; how to switch back color ???

		pop	bx
		ret
SwitchColor	ENDP

	; ClipY proc
	;
	; In:   MaxLen	font height
	;
	; Out:	AX	clipped start y
	;	MaxLen	clipped height
	;	CH	ditto
	;	CF	set if no output
	;	yDelta	y delta

ClipY		PROC NEAR
		MOV	CX, ClipRect.B.y
		MOV	DX, ClipRect.A.y
		SUB	CX, DX
		MOV	AX, aty
		MOV	yDelta, 0
		SUB	DX, AX
		JLE	SHORT @@13
		MOV	yDelta, DX
		sub	MaxLen, dx
		jbe	SHORT @@2
		MOV	AX, ClipRect.A.y
@@13:   	MOV	DX, ClipRect.B.y
		SUB	DX, aty
		CMP	CX, DX
		JLE	SHORT @@16
		MOV	CX, DX
@@16:		OR	CX, CX
		JG	SHORT @@0
@@2:		STC				; no output
		RET
@@0:		cmp	cx, MaxLen
		jg	SHORT @@1
		mov	MaxLen, cx
@@1:		clc				; do output
		ret
ClipY		ENDP

	; Setup the bitmap offset list
	;
	; In:	es:di	Room for list
	;
	; Out:	es:di	Current list position

SetupList	PROC NEAR
		cld
		xor	ax, ax
		stosw				; room for end offset
		stosw
		stosw				; reserved
		mov	ax, 8000H
		mov	MaxPos, ax
		stosw				; horiz-pos sentinel
		dec	ax
		mov	MinPos, ax
		retn
SetupList	ENDP

	; Insert a bitmap offset entry into the list.
	;
	; In:   es:di	Current list position
	;	dx:ax	Offset value
	;	XPos	horizontal position
	;	ss:bp	stack frame
	;
	; [CurAttrib] is used as the reserved word

InsertEntry	PROC NEAR
		push	di ax cx si di
		xor	cx, cx		; words to be copied
		mov	ax, XPos
		cmp	ax, MinPos
		jge	SHORT @@2

		mov	MinPos, ax
@@2:		cmp	ax, es:[di-2]	; compare with prev horiz pos
		jge	SHORT @@1
		add	cx, 4
		sub	di, 8
		jmp	@@2
@@1:		pop	si
		sub	si, 2		; last word to be copied
		mov	di, si
		add	di, 8
		std
		seges
		rep	movsw
		stosw			; store horizontal position
		mov	ax, CurAttrib
		stosw			; store reserved value
		mov	ax, dx
		stosw			; store high offset word
		pop	si cx ax
		stosw			; store offset value
		cld
		pop	di
		add	di, 8
		retn
InsertEntry	ENDP

	; Insert a vertical-movement sentinel
	;
	; In:	es:di   current list position
	;       XPos	horizontal position
	;	dx	vertical movement
	;	ss:bp	stack frame

InsertVertMove	PROC NEAR
		cmp	WORD PTR es:[di-6], -1
		jnz     SHORT @@1
					; update last move
		add	es:[di-4], dx
		jnz	SHORT @@0

		sub	di, 8		; has become zero
@@0:
		retn
@@1:					; create new move
		cld
		mov	ax, maXPos
		stosw			; offset word: horiz pos
		mov	ax, -1
		stosw			; high word: "vertical move"
		mov	ax, dx
		stosw			; attribute: vertical movement
		mov	ax, 8000H
		stosw			; horiz position: left-side sentinel
		retn
InsertVertMove	ENDP

	; Prepare list for use in WriteBmpText
	;
	; In:	es:di   current (last) list position
	;	dx	horizontal max pos
	;
	; Out:  es:di	room for next data in temp mem
	;	ax	horizontal first pos
	;
	; The first reserved is stored in [CurAttrib].

PrepareList	PROC NEAR
		mov	ax, -1
		cmp	ax, es:[di-6]
		jnz	SHORT @@1		; last item wasn't vert move

		sub	di, 8
@@1:
		cld
		mov	ax, dx
		stosw			; offset word: horiz pos
		mov	ax, -1
		stosw			; high word: "vertical move"
		xor	ax, ax
		stosw			; attribute: vertical movement
		mov	ax, 8000H
		stosw			; horiz position: left-side sentinel

		mov	ax, WORD PTR TempMem[0]
		mov	es:[di], ax		; next word := start offset
		xchg	ax, di
		stosw				; store end offset
		mov	dx, es:[di+12]
		mov	bx, es:[di+10]
		mov	CurAttrib, bx
		mov	es:[di+4], dx		; store horiz start pos
		mov	di, ax
		mov	ax, dx
		retn
PrepareList	ENDP

	; Handle marker characters, test version
	;
	; In:	AL	the very character
	;       SS:BP	stack frame
	;
	; Out:	CF	clear if marker
	;
	; The [CurAttrib] value is changed.

HandleMarker	PROC NEAR
		cmp	al, Marker
		stc
		jnz	SHORT @@1
		xor	CurAttrib, ftForeColor+ftBkColor
@@1:		retn
HandleMarker	ENDP

; Create a bitmap offset list in the TempMem.
;
; Structure:	DWORD	end pointer
;		WORD	? (reserved)
;		WORD	-32768 (sentinel) / Horiz start pos
;		repeatedly
;		  DWORD	  Bitmap pointer
;		  WORD	  Attrib (reserved)
;		  WORD	  Horiz pos
;		end
;		DWORD	?
;		WORD	?
;		WORD	?
;
; Special Segments:
; 0	Keep Segment
; -1	Vertical Movement (0 ist end-of-list)
; -2	Already processed entry
;
; In:	ss:bp	stack frame
;	es:di	room for data in TempMem
;
; Out:	es:di	room for next data in TempMem
;	ax	horizontal first pos

	; CPI version

CpiCreateList	PROC NEAR
		call	SetupList
		lea	bx, scopy
		add	bx, sofs		; SS:BX string
		mov	cl, ss:[bx]
		inc	bx
		xor	ch, ch			; CX string length
		mov	dl, BYTE PTR FontLen
		mov	dh, BYTE PTR Charspace	; DL height
		add	dh, 8			; DH horiz delta
		mov	XPos, 0			; init horiz pos
		or	CurAttrib, ftCharStart
@@1:		mov	al, ss:[bx]
		inc	bx
		call	HandleMarker
		jnc	SHORT @@4
@@2:		mul	dl
		push	dx
		xor	dx, dx
		call	InsertEntry
		pop	dx
		mov	al, dh
		cbw
		add	XPos, ax
@@4:		loop	@@1
@@3:		or	dh, dh
		mov	dx, 8
		js	SHORT @@5
		mov	dx, XPos
@@5:		call	PrepareList
		retn
CpiCreateList	ENDP

	; MaxPos := max(MaxPos, Reg)

DoMaxPos	MACRO	Reg
		LOCAL	@@0
	IFB <Reg>
		mov	ax, XPos
		cmp	ax, MaxPos
		jle	SHORT @@0

		mov	MaxPos, ax
@@0:
	ELSE
		cmp	Reg, MaxPos
		jle	SHORT @@0

		mov	MaxPos, Reg
@@0:
	ENDIF
		ENDM

	; Win version

WinCreateList	PROC NEAR
		call	SetupList
		lea	bx, scopy
		add	bx, sofs		; SS:BX string
		mov	cl, ss:[bx]		; CL string length
		inc	bx
		mov	XPos, 0
		mov	dx, FontLen

		push	ds
		lds	si, Bitmap

@@4:		push	bx
		mov	al, ss:[bx]
		or	CurAttrib, ftCharStart

		call    HandleMarker
		jnc	SHORT @@7

		mov	bl, al
		xor	bh, bh
		MOV	AL, [SI][BX]		; translation
		MUL	sEntry
		MOV	BX, AX
		add	bx, si			; DS:BX+256 := @Entry
		push	si
		MOV	si, [BX+258]		; get address
		add	si, WinDelta
		mov	ch, [BX+256]		; get width

@@2:		mov	ax, si
		push	dx
		xor	dx, dx
		call	InsertEntry
		pop	dx
		and	CurAttrib, NOT ftCharStart

		sub	ch, 8
		jbe	SHORT @@1
		add	XPos, 8
		add	si, dx
		jmp	@@2

@@1:		add	ch, 8			; correct value
		mov	al, ch
		xor	ah, ah
		add	ax, XPos
		DoMaxPos ax
		add     ax, Charspace
		DoMaxPos ax
		mov	XPos, ax
		pop	si			; load Bitmap offset
@@7:		pop	bx			; load string offset
		inc	bx
		dec	cl
		jnz	@@4			; next char

@@6:		pop	ds
		mov	dx, MaxPos
		call	PrepareList
		retn
WinCreateList	ENDP

	; Win Huge version

WinHugeCreateList PROC NEAR
		call	SetupList
		lea	bx, scopy
		add	bx, sofs		; SS:BX string
		mov	cl, ss:[bx]		; CL string length
		inc	bx
		mov	XPos, 0

		push	ds
		lds	si, Bitmap

@@4:		push	bx
		mov	al, ss:[bx]
		or	CurAttrib, ftCharStart

		call    HandleMarker
		jnc	@@7

		mov	bl, al
		xor	bh, bh
		shl	bx, 4			; TYPE TABCLong = 16
		add	bx, si			; DS:BX = @Entry
		push	si
		mov	dx, [bx+12]		; get D height
		or	dx, dx
		jz	SHORT @@5

		call    InsertVertMove
@@5:
		mov	ax, [bx+6]
		add	XPos, ax		; add A width
		MOV	ax, [bx]		;
		mov	dx, [bx+2]		; dx:ax Bits
		mov	ch, [bx+8]		; get B width
@@2:
		call	InsertEntry		; preserves registers...
		and	CurAttrib, NOT ftCharStart

		sub	ch, 8
		jbe	SHORT @@1
		add	XPos, 8
		add	ax, FontLen
		jmp	@@2
@@1:
		add	ch, 8			; correct value
		mov	al, ch
		xor	ah, ah
		add	ax, XPos
		DoMaxPos ax
		add	ax, [bx+10]		; add C width
		DoMaxPos ax
		add     ax, Charspace
		DoMaxPos ax
		mov	XPos, ax
		test	Attr, ftVerticalMoves
		jz	SHORT @@3

		mov	dx, [bx+14]		; get H vertical movement
		or	dx, dx
		jz	SHORT @@3		; no movement

		call	InsertVertMove
@@3:
		pop	si			; load Bitmap offset
@@7:		pop	bx			; load string offset
		inc	bx
		dec	cl
		jnz	@@4			; next char

@@6:		pop	ds
		mov	dx, MaxPos
		call	PrepareList
		retn

WinHugeCreateList ENDP

CODE		ENDS

		END
