**********************************************************************
*                                                                    *
*  SetScr21.asm                                                      *
*                                                                    *
*  A CLI program for WB/KS 2.0+ that intercepts all OpenScreen	     *
*   calls and forces screens to open in the same mode as the         *
*   current workbench screen ( e.g. PRODUCTIVITY mode).              *
*   2.0-style requesters will have the standard 3D look.             *
*                                                                    *
*  The patch is removed if the program is run a 2nd time.            *
*								     *
*  13 May 1992                                                       *
*  Norman Iscove                                                     *
*   bitnet    iscove@utoroci                                         *
*   internet  iscove@galen.oci.utoronto.ca                           *
*								     *
**********************************************************************

OpenScreenTagList equ	-$264
SetFunction	  equ	-$1a4
FindTask	  equ	-$126
OpenLibrary	  equ	-$228
CloseLibrary	  equ	-$19e
UnloadSeg	  equ	-$9c
Output		  equ	-$3c
Write		  equ	-$30
LockPubScreen	  equ	-$1fe
UnlockPubScreen	  equ	-$204
GetVPModeID	  equ	-$318
ViewPort	  equ	44
cli_Module	  equ	60
pr_CLI		  equ	172
SA_Pens		  equ	$8000003a
SA_DisplayID	  equ	$80000032
DETAILPEN	  equ	0
BLOCKPEN	  equ	1
TEXTPEN		  equ	1
SHINEPEN	  equ	2
SHADOWPEN	  equ	1
FILLPEN		  equ	3		;window border fill
FILLTEXTPEN	  equ	1		;window title text
BACKGROUNDPEN	  equ	0
HIGHLIGHTTEXTPEN  equ	2


start:
	move.l	4,a6
	lea	intname(pc),a1
	move.l	#36,d0			;specify 2.0 or above
	jsr	OpenLibrary(a6)
	move.l	d0,intlib
	bne.s	s1
	rts				;fail silently if system is pre-2.0

s1:	lea	dosname(pc),a1
	moveq	#0,d0
	jsr	OpenLibrary(a6)
	move.l	d0,doslib

	move.l	a6,-(sp)
	movea.l	d0,a6			  ;a6 = doslib
	jsr	Output(a6)
	move.l	(sp)+,a6		  ;a6 = execlib
	move.l	d0,stdout

	movea.l	intlib(pc),a1		  ;a1 = intlib
	move.l	-$c4(a1),a0		  ;a0 = &funcentry
	move.l	a0,fentry
	move.l	intext-funcentry(a0),d0   ;d0 = intext/???
	cmp.l	#'SetS',d0
	bne.s	install

remove:
	move.l	oldfunc-funcentry(a0),d0  ;d0 = oldfunc
	movea.l	intlib(pc),a1		  ;a1 = intlib
	movea.l	#-$c6,a0		  ;a0 = offset of OpenScreen
	jsr	SetFunction(a6)		  ;restore original vector
	movea.l	intlib(pc),a1		  ;a1 = intlib
	jsr	CloseLibrary(a6)

	movea.l	fentry,a0		  ;a0 = &funcentry (1st instance)
	move.l	myseg-funcentry(a0),d1
	move.l	a6,-(sp)
	movea.l	doslib(pc),a6
	jsr	UnloadSeg(a6)		  ;remove original instance of SetScr
	move.l	(sp)+,a6		  ;  (present instance will also go)
	lea	outtext,a0
	bra.s	dprint

install:
	movea.l	#-$c6,a0		;a0 = offset of OpenScreen
	movea.l	intlib(pc),a1		;a1 = lib
	move.l	#funcentry,d0		;d0 = &funcentry
	jsr	SetFunction(a6)		;OpenScreen(lib) now points to us
	move.l	d0,oldfunc		;save the original pointer
	suba.l	a1,a1			;following stuff makes sure we stay:
	jsr	FindTask(a6)
	movea.l	d0,a0
	movea.l	pr_CLI(a0),a0		;a0 = &CLI (BPTR)
	adda.l	a0,a0
	adda.l	a0,a0
	move.l	cli_Module(a0),myseg	;save &myseg  (BPTR)
	clr.l	cli_Module(a0)		;now we can't unload!
	lea	intext,a0

dprint:
 ;output text to stdout
 ;enter with a0 = &text, a6 = exec, stdout defined
 ;trashes d0,d1,a0,a1

	movem.l	d2-d3/a6,-(SP)
	movea.l	doslib(pc),a6
	move.l	stdout(pc),d1
	move.l	a0,d2
dp1:	
	tst.b	(a0)+
	bne.s	dp1
	move.l	a0,d3			;address+1 of 1st 0 in text buf
	sub.l	d2,d3
	subq.l	#1,d3
	jsr	Write(a6)
	movea.l	a6,a1		  	;a1 = doslib
	movem.l	(SP)+,d2-d3/a6
	jsr	CloseLibrary(a6)	;close doslib
	moveq	#0,d0			;all's well that ends well
	rts				;exit to CLI parent



funcentry:
* we are intercepting a graphics OpenScreen call
* whoever enters has a0 = &NewScreen
*		     a6 = intuitionbase

	move.l	a0,-(sp)		;a0 = &NewScreen
	lea	wbname(pc),a0
	jsr	LockPubScreen(a6)
	move.l	d0,-(sp)		;d0 = wbscreen
	bne.s	f1

	;no workbench screen, so we exit through original function
	addq	#4,sp			;dump wbscreen from stack
	movea.l	(sp)+,a0
	movea.l	oldfunc,a1
	jmp	(a1)

f1:	move.l	a6,-(sp)
	movea.l	4,a6			;a6 = execlib
	lea	grname(pc),a1
	moveq	#0,d0
	jsr	OpenLibrary(a6)
	movea.l	d0,a6			;a6 = graphicslib
	movea.l	4(sp),a0		;a0 = wbscreen
	lea	ViewPort(a0),a0		;a0 = &ViewPort
	jsr	GetVPModeID(a6)
	move.l	d0,tags+4		;d0 = wbscreen ModeID
	movea.l	a6,a1
	movea.l	4,a6
	jsr	CloseLibrary(a6)	;close graphics.lib
	movea.l	(sp)+,a6		;a6 = intlib
	
	suba.l	a0,a0			;a0 = NULL
	movea.l	(sp)+,a1		;a1 = wbscreen
	jsr	UnlockPubScreen(a6)
	movea.l	(sp)+,a0		;a0 = &NewScreen
	lea	tags(pc),a1		;a1 = tags
	jmp	OpenScreenTagList(a6)	;open screen and return to caller
	

stdout		dc.l	0
myseg		dc.l	0
oldfunc		dc.l	0
fentry		dc.l	0
intlib		dc.l	0
doslib		dc.l	0
tags		dc.l	SA_DisplayID,0,SA_Pens,penlist,0
penlist		dc.w	DETAILPEN,BLOCKPEN,TEXTPEN,SHINEPEN,SHADOWPEN
		dc.w	FILLPEN,FILLTEXTPEN,BACKGROUNDPEN,HIGHLIGHTTEXTPEN,-1
intname		dc.b	'intuition.library',0
		EVEN
dosname		dc.b	'dos.library',0
		EVEN
grname		dc.b	'graphics.library',0
		EVEN
wbname		dc.b	'Workbench',0
		EVEN
intext		dc.b	'SetScr installed',10,0	;17 chars
		EVEN
outtext		dc.b	'SetScr removed',10,0	;15 chars

		END

