; $VER: antitopaz.a 36.1 (26.3.95)

******* AntiTopaz ************************************************************
*
*   NAME
*	AntiTopaz - gets rid of the ugly topaz.font/8.
*
*   SYNOPSIS
*
*	[Run >NIL:] AntiTopaz
*	Break `Status COM=AntiTopaz`
*
*   DESCRIPTION
*
*	AntiTopaz patches graphics.library/OpenFont() to substitute
*	topaz.font/8 with the system default font.
*
*	To start AntiTopaz just run it or click its icon. You can place it
*	in your User-Startup or WbStartup.
*
*	AntiTopaz can be removed by sending it a break signal (when it's
*	running as a CLI process) or running it again (via both Shell and
*	Workbench).
*
*   NOTES
*
*	Don't use a system default font bigger than 8x8 pixels, layout for
*	the programs affected will get totally f'd up.
*
*   BUGS
*
*	Doesn't affect Workbench execute/rename/info windows. Use another
*	patches (such as WorkbenchPlus) for them...
*
*   COPYRIGHT
*
*	AntiTopaz is public domain. Do whatever you want with it.
*
*   AUTHOR
*
*	Lauri Aalto <lauri.aalto@fipnet.fi>
*
******************************************************************************

	include	graphics/text.i
	include	graphics/gfxbase.i
	include	libraries/commodities.i

	include	lvo/graphics_lib.i
	include	lvo/intuition_lib.i
	include	lvo/commodities_lib.i

	include	macros.i

	include	antitopaz_rev.i

; The code begins.

AntiTopaz
	moveq	#RETURN_FAIL,d7		; default RC = 20
	moveq	#0,d5			; no WbStartup (yet)

	suba.l	a1,a1
	move.l	(_AbsExecBase).w,a6
	flib	FindTask		; find our process
	move.l	d0,a2
	lea	(pr_MsgPort,a2),a0	; a port allocated for us
	move.l	a0,d4			; store it
	tst.l	(pr_CLI,a2)		; are we a CLI process?
	bne	.cli

; No CLI structure, so we're launched from Workbench. Let's get the WbStartup message.

.wb	move.l	d4,a0
	flib	WaitPort		; wait until the message arrives
	move.l	d4,a0
	flib	GetMsg			; and get it
	move.l	d0,d5			; store it for later use

; Open libraries.

.cli	lea	(gfxname,pc),a1
	moveq	#36,d0			; v36 required
	flib	OpenLibrary
	tst.l	d0
	beq	.nogfx
	move.l	d0,a5			; we use register variables

	lea	(intname,pc),a1
	moveq	#36,d0
	flib	OpenLibrary
	tst.l	d0
	beq	.noint
	move.l	d0,a4
	move.l	a6,a3			; cache SysBase

; Ensure our uniqueness and kill out clone if we're already running.

	flib	Forbid

	lea	(port,pc),a2		; port name
	move.l	a2,a1
	flib	FindPort		; try to find it
	tst.l	d0
	bne	.dupe			; if it exists, send a signal & quit
	
	move.l	d4,a1			; our port
	move.l	a2,(LN_NAME,a1)		; give it a name
	flib	AddPort			; and add it to the public ports list

	flib	Permit

; Install our patch.

	flib	Forbid			; avoid messups with other patches

	move.l	a5,a1			; GfxBase
	lea	(newOpenFont,pc),a0	; the new OpenFont()
	move.l	a0,d6			; cache it
	move.l	a0,d0
	move.w	#_LVOOpenFont,a0
	flib	SetFunction		; patch it
	lea	(oldOpenFont,pc),a0
	move.l	d0,(a0)			; store old OpenFont()

	flib	CacheClearU		; avoid cache problems

	flib	Permit

; The main loop. Let's wait for a break signal.

.loop	move.l	#SIGBREAKF_CTRL_C,d0	; signal we're waiting for
	flib	Wait

	move.l	a4,a6			; IntuitionBase
	suba.l	a0,a0			; beep all screens
	flib	DisplayBeep		; first beep to indicate signal

	move.l	a3,a6
	flib	Forbid			; kill task switching

	move.l	a5,a1
	move.w	#_LVOOpenFont,a0
	move.l	(oldOpenFont,pc),d0
	flib	SetFunction		; try to put the old OpenFont() back
	cmp.l	d6,d0			; has someone patched over us?
	beq	.quit			; no -> we're ok to quit

	move.l	a5,a1			; Someone patched over us, so we'll
	move.w	#_LVOOpenFont,a0	; put the successive patch back and
	flib	SetFunction		; keep waiting.

	flib	Permit

	move.l	a4,a6			; IntuitionBase
	suba.l	a0,a0			; beep all screens
	flib	DisplayBeep		; second beep to indicate failure

	lea	(PatchActive,pc),a0
	clr.b	(a0)			; disable our patch

	move.l	a3,a6
	flib	CacheClearU		; and avoid cache collisions

	bra	.loop			; keep waiting for ^C

.quit	flib	Permit

	moveq	#RETURN_OK,d7		; successful exit -> rc = 0

	tst.l	d4			; did we AddPort()?
	beq	.noport			; no -> don't RemPort()
	move.l	d4,a1
	flib	RemPort

.noport	move.l	a4,a1			; close intuition.library
	flib	CloseLibrary

.noint	move.l	a5,a1			; close graphics.library
	flib	CloseLibrary

.nogfx	tst.l	d5
	beq	.exit			; no WbStartup
	flib	Forbid			; RemTask() breaks
	move.l	d5,a1
	flib	ReplyMsg		; reply WbStarup message

.exit	move.l	d7,d0			; set return code & exit
	rts

; Send a signal to the existing AntiTopaz.

.dupe	move.l	d0,a0			; MsgPort
	move.l	#SIGBREAKF_CTRL_C,d0	; just signal a break signal
	move.l	(MP_SIGTASK,a0),a1
	flib	Signal

	moveq	#0,d4			; don't free our port

	bra	.quit			; exit

; The new OpenFont() routine.

newOpenFont
	tst.b	(PatchActive,pc)	; are we still enabled?
	beq	.old			; no -> call the original routine

	pushm	a1-a2

	move.l	(ta_Name,a0),a1		; Is the font being opened topaz.font?
	lea	(topaz,pc),a2
.cmplp	cmpm.b	(a1)+,(a2)+
	bne	.not
	tst.b	(a2)
	bne	.cmplp

	cmp.w	#8,(ta_YSize,a0)	; is the size requested 8?
	bne	.not

; ta_Name was "topaz.font", so we'll substitute the TextAttr fields with ones picked from
; GfxBase->DefaultFont.

	move.l	(gb_DefaultFont,a6),a1
	move.l	(LN_NAME,a1),(ta_Name,a0)
	move.w	(tf_YSize,a1),(ta_YSize,a0)

.not	pullm	a1-a2

.old	move.l	(oldOpenFont,pc),-(sp)	; call the old function
	rts

oldOpenFont	dc.l	0		; space for old function pointer
PatchActive	dc.b	~0		; we're enabled by default

port	dc.b	'AntiTopaz',0
topaz	dc.b	'topaz.font',0
gfxname	dc.b	'graphics.library',0
intname	dc.b	'intuition.library',0

	VERSTAG
