  
French		SET	1	;à un pour assembler messages en Français

VERSION		=	"1"
REVISION	=	"0"
REVA		=	"0"
YEAR		=	"3"
        *************************************************
	*		    Nikita			*
	*-----------------------------------------------*
	* Nikita © 1993 Philippe Girolami		*
	*  Un programme qui intercepte tout appel à	*
	* l'appel d'intuition OpenScreen pour		*
	* obliger l'ouverture en PubScreen sous 2.0.	*
	*************************************************
	* 20/05/93: V 0.00	* Interception et flashage écran
	* 20/05/93: V 0.01	* Ajout d'un menu Workbench pour désactiver
	* 20/05/93: V 0.02	* Travail sur transformation d'un custom en public
	* 30/05/93: V 0.10	* Suite mais façon de faire <>:si OpenScreen, appel avec Tag List pour Pub.
	* 30/05/93: V 0.20	* Interception de Close Screen si n'arrive pas a fermer a cause fenêtres
	* 30/05/93: V 1.00	* 1ère version qui marche sans bug.
	*************************
	
* Directives Assembleur

; Includes
	include	'ram:alarming.gs'
	include	"Include2.0:Include/workbench/wb_lib.i"
	include	"Include2.0:Include/workbench/workbench.i"
;macros
CALLWB	MACRO
	move.l	_WorkbenchBase,a6
	jsr	_LVO\1(a6)
	ENDM
TXT	MACRO
	dc.b	"\1",0
	EVEN
	ENDM
;
RegSave	REG	a0-a6/d1-d7	;régistres à sauver

 *************
 * Programme *
 *************

	SECTION	Philippe,CODE
	
Début:  bra.s   Startup                 ;MA SIGNATURE DE PROGRAMME
        dc.b    "Nikita V",VERSION,".",REVISION,"",REVA," © 1993 Philippe Girolami, DP à distribuer..."
        even

Startup:
        sub.l   a1,a1
        CALLEXEC	FindTask
        move.l  d0,a2
        tst.l   pr_CLI(a2)
        bne.s   FromCLI

        lea     pr_MsgPort(a2),a0
        CALLEXEC	WaitPort
        lea     pr_MsgPort(a2),a0
        CALLEXEC	GetMsg
        move.l  d0,WBMsg

FromCLI:

        bsr     Main
	
	move.l  WBMsg(pc),d0
        beq.s   More
        move.l  d0,a1
        CALLEXEC	Forbid		;réponse pour workbench qu'il peut nous faire quitter
        CALLEXEC	ReplyMsg
More:   moveq   #0,d0
        rts

WBMsg:  dc.l    0

	
****************
* Routine Main *
****************
Main
;signale en désactgivé
	move.b	#$ff,NikitaState
; Ouvre intuition d'abord
	lea	intname,a1
	move.l	#36,d0		;version 2.00 pour avoir CreateMsgPort
	CALLEXEC	OpenLibrary
	move.l	d0,_IntuitionBase
	tst.l	d0
	bne	.ok
	lea	intname,a1
	move.l	#0,d0
	CALLEXEC	OpenLibrary
	move.l	d0,_IntuitionBase
	tst.l	d0
	beq	ErrorIntuitionOpen
	lea	VersStruct,a1	;affiche requester car on n'a pas Release 2
	lea	ReqIDCMP,a2
	move.l	#0,a3
	CALLINT	EasyRequestArgs

	move.l	_IntuitionBase,a1
	CALLEXEC	CloseLibrary
	rts			;et bye bye
	
;vérifie que Nikita pas déjà chargé
.ok	lea	PortName,a1
	CALLEXEC	Forbid	;interdit multitache->le port reste
	CALLEXEC	FindPort	;cherche port
	CALLEXEC	Permit	;autorise
	tst.l	d0	;retour
	beq	.prog	;si 0 alors pas de port de ce nom-> premiere chargure
	move.l	#0,a0			;Requester sur Workbench ou Default Window
	lea	ExistsStruct,a1		;easy structure
	lea	ReqIDCMP,a2		;IDCMP_ptr
	move.l	#0,a3			;ArgList
	CALLINT	EasyRequestArgs		;Display un Requester
; quand retourne,ce ne peut qu'être Quit
	move.l	_IntuitionBase,a1
	CALLEXEC	CloseLibrary
	rts

.prog	CALLEXEC	CreateMsgPort	;On se fait un port de messages
	tst.l	d0
	beq	ErrorCreateMsgPort
	move.l	d0,OurMsgPort
	move.l	d0,a1			;ajoute à list publique
	lea	PortName,a2
	move.l	a2,10(a1)
	move.b	#1,9(a1)		;structure Node
	CALLEXEC	AddPort

	moveq.l	#0,d0			;n'importequelle version (sera => 36)
	lea	wbname,a1
	CALLEXEC	OpenLibrary
	tst.l	d0
	beq	ErrorOpenWBLibrary
	move.l	d0,_WorkbenchBase
	
.addmenu	;Ajout du menu
	moveq.l	#0,d0			;id
	move.l	d0,d1			;userdata
	lea	Text,a0			;text
	move.l	OurMsgPort,a1		;MsgPort
	move.l	#0,a2			;MUST be NULL for 2.0
	CALLWB	AddAppMenuItemA		;ajoute le menu
	tst.l	d0
	beq	ErrorAddMenu	
	move.l	d0,MenuHandle		;le handle pour l'effacer
;

	bsr	Active
; Gestion du menu ici
Attend	
	move.l	OurMsgPort,a0
	CALLEXEC	WaitPort	;Attend le message de reboot
	move.l	OurMsgPort,a0
	CALLEXEC	GetMsg
	move.l	d0,a1
	CALLEXEC	ReplyMsg	;Renvoit Message à Intuition
	
	move.l	#0,a0			;Requester sur Workbench ou Default Window
	lea	RequestStruct,a1	;easy structure
	lea	ReqIDCMP,a2		;IDCMP_ptr
	move.l	#0,a3			;ArgList
	CALLINT	EasyRequestArgs		;Display un Requester

	cmp.l	#1,d0			;était-ce le "Desactivate"
	beq	Desactivate		;branche si oui
	cmp.l	#0,d0			;était-ce Quit?
	beq	EndNikita		;si oui branche
	bne	Activate		;sinon c'était Activate
; on n'arrive jamais ici

Desactivate
	bsr	Desactive
	bra	Attend
Activate
	bsr	Active
	bra	Attend
Active	;active nikita
	move.b	NikitaState,d0		;activé ou desactivé ?
	beq	.fin			;si=0 alors déjà activé
	move.b	#0,NikitaState		;signale activé.
	move.l	_IntuitionBase,a0	;base de intuition
	lea	NikitaStruct,a2
	lea	NikitaClose,a1
	CALLEXEC	Forbid		;we can do this because we only do
					;it once!
	move.l	_LVOCloseScreen+2(a0),CloseVect
	move.l	_LVOOpenScreen+2(a0),Vect
	move.l	a1,_LVOCloseScreen+2(a0)
	move.l	a2,_LVOOpenScreen+2(a0)
	CALLEXEC	Permit		;réautorise mult-tâche.
.fin	rts
Desactive	;désactive Nikita
	move.b	NikitaState,d0
	bne	.fin			;si <>0 désactivé déjà
	move.b	#$ff,NikitaState			;le note désactivé
	move.l	_IntuitionBase,a0
	move.l	Vect,a2			;remet l'adresse pointée
	move.l	CloseVect,a1
	CALLEXEC	Forbid
	move.l	a1,_LVOCloseScreen+2(a0)
	move.l	a2,_LVOOpenScreen+2(a0)
	CALLEXEC	Permit
.fin	rts
	
***********************	-désallocations
* Fait quitter Nikita * -ramène les anciens vecteurs...
***********************
EndNikita	;terminate Nikita
; On doit attendre que NikitaState2 soit à zéro
.wait
	move.b	NikitaState2,d0
	bne	.wait		;je sais, ce n'est pas Multitasking friendly
		;mais il y a peu de chances que 60
		;programmes appelent en même tps ces routines donc faire 
		;perdre 2ms de tps en tps au max au lieu d'alourdir le prg
		;me parait mieux.
	CALLEXEC	Forbid	;pour qu'on nous vole pas pendant le chgmt
	move.b	NikitaState2,d0	;verifie que personne a fait d'appel
	beq	.ok		;sinon on reattend en defaisant Forbif
	CALLEXEC	Permit
	bra	.wait
.ok	bsr	Desactive		;desactive.
	CALLEXEC	Permit	;tout est "débranché" donc on restaure MTask

	move.l	MenuHandle,a0		;le handle
	CALLWB	RemoveAppMenuItem	;le retire, le menu
	
ErrorAddMenu
	move.l	_WorkbenchBase,a1
	CALLEXEC	CloseLibrary
	
ErrorOpenWBLibrary
.EmptyPort
	move.l	OurMsgPort,a0
	CALLEXEC	GetMsg
	tst.l	d0			;un message ou pas?
	beq	.Emptied		;si branche => =0 donc pas message
	move.l	d0,a1			;sinon répond
	CALLEXEC	ReplyMsg
	bra	.EmptyPort
.Emptied
	move.l	OurMsgPort,a1
	CALLEXEC	RemPort		;enlève de liste publique
	move.l	OurMsgPort,a0
	CALLEXEC	DeleteMsgPort	;Au revoir
	
ErrorCreateMsgPort
	move.l	_IntuitionBase,a1
	CALLEXEC	CloseLibrary

ErrorIntuitionOpen
	rts

	section	NikitaProg,code
********************************************************
* Sous-programme d'interception de l'appel CloseScreen *
********************************************************
NikitaClose	;On fait çà car avec le patch il est possible que des
	;screens restent ouverts car les fenêtres en visite peuvent
	;empecher sa fermeture. Ici on verifie le retour, si c'est à cause
	;d'une fenêtre on affiche un requester pour reessayer ou arreter.
	movem.l	RegSave,-(a7)	;sauve les régistres inutilisés
	add.b	#1,NikitaState2	;signal execution de la routine par 1 autre tâche
	move.l	a0,a4		;sauve l'adresse de l'écran.
.tryagain
	move.l	CloseVect,a5	;CloseScreen en ROM
	jsr	(a5)		;essaye
	tst.b	d0
	bne	.ok		;si = 1 alors pas de problème
;sinon on affiche un requester demandant de fermer les fenêtres.
	move.l	#0,a0			;Requester sur Workbench ou Default Window
	lea	CloseStruct,a1		;easy structure
	lea	ReqIDCMP,a2		;IDCMP_ptr
	move.l	#0,a3			;ArgList
	CALLINT	EasyRequestArgs		;Display un Requester
	tst.l	d0			;=0 alors Cancel sinon Retry
	beq	.ok
	move.l	a4,a0			;ramène adresse écran
	bra	.tryagain		;et retente
.ok	movem.l	(a7)+,RegSave		;ramène l'état des régistres (pas d0)
	sub.b	#1,NikitaState2	;terminé pour cette tache(! code doit être PURE)
	rts				;bye bye, retour au prg appelant.
	
*******************************************************
* Sous-programme d'interception de l'appel OpenScreen *
*******************************************************
NikitaStruct	
	movem.l	RegSave,-(a7)	;sauve les régistres inutilisés
	add.b	#1,NikitaState2	;signal execution de la routine par 1 autre tâche
	move.l	#0,a1		;mise-à-zero de a1 au cas ou pas de Tags.
	move.w	ns_Type(a0),d0	;screen type
	and.w	#CUSTOMSCREEN,d0	;vérifie si bien ouvert en Custom
	cmp.w	#CUSTOMSCREEN,d0	;isole les bits et compare
	bne	ToChange2		;si non, on ne fait rien	
;si oui alors, on va le forcer en public en appelant OpenScreenTagList avec
;  les tags d'ouverture en Public.
	move.l	ns_DefaultTitle(a0),NsName	;modifie le nom.
	lea	GenericScreenTags,a1	;adresse des Tags
ToChange2
; !! Ici il faut être sûr d'avoir IntuitionBase dans a6 !!
	jsr	_LVOOpenScreenTagList(a6)
	move.l	d0,d6		;sauve le retour
	beq	.noscr		;si=0 alors on ne peut le faire Public.
	move.l	d0,a0		;met le screen en "Public state"
	move.w	#0,d0
	CALLINT	PubScreenStatus	;pour enlever l'etat "PRIVATE".
	move.l	d6,d0			;ramène le retour de l'appel d'ouverture
.noscr	movem.l	(a7)+,RegSave		;ramène l'état des régistres (pas d0)
	sub.b	#1,NikitaState2	;terminé pour cette tache(! code doit être PURE)
	rts				;bye bye, retour au prg appelant.

	section	NikitaData,bss
_IntuitionBase	ds.l	1	;base de intuition détourné	
_WorkbenchBase	ds.l	1
OurMsgPort	ds.l	1
MenuHandle	ds.l	1
Vect		ds.l	1	;Addresse en ROM de OpenScreen.
CloseVect	ds.l	1	;idem pour CloseScreen
NikitaState	ds.b	1	;signal si les vecteurs sont détournés(oui=0)
NikitaState2	ds.b	1	;Nbr de tâche appelant OpenScreen(TagList)
				;On ne peut quitter Nikita que si=0
	even

	section	NikitaTxts,data
; Text non affectés par langues différente
intname	TXT	<intuition.library>
wbname	TXT	<workbench.library>
PortName	TXT	<NikitaPort>
RetCan		TXT	<Retry|Cancel>
Nom	dc.b	"Nikita",VERSION,".",REVISION,REVA,0
	even

Text	TXT	<Nikita...>	;Menu Workbench
ReqName		dc.b	"Nikita V",VERSION,".",REVISION,REVA," by Philippe Girolami",0
	even

	IFNE	French
; Textes en Anglais
NotR2	dc.b	"Nikita necessitates",$a
	dc.b	"  Release 2...",0
	even
Exists	TXT	<Nikita already loaded...>
Quit	TXT	<Quit>
ReqTxt		TXT	<Please hit a button...>
ReqGadNames	TXT	<Desactivate|Activate|Quit>
CantClose	dc.b	"Can't close public screen.",$a
		dc.b	"Please close all visitor windows",$a
		dc.b	" and hit Retry.",$a
		dc.b	"(Cancel will leave screen open.)",0
		even

	ELSEIF		;TEXTES EN FRANçAIS

NotR2	dc.b	"Nikita necessite",$a
	dc.b	" la Release 2...",0
	even
Exists	TXT	<Nikita déjà chargé...>
Quit	TXT	<Quitter>
ReqTxt		TXT	<Appuyez sur un des bouttons...>
ReqGadNames	TXT	<Désactiver|Activer|Quitter>
CantClose	dc.b	"Ne peut fermer un écran publique.",$a
		dc.b	"Veuillez fermer toutes les fenêtre",$a
		dc.b	" présentes sur cet écran.",$a
		dc.b	" puis appuyer sur Retry.",$a
		dc.b	"(Cancel gardera l'écran ouvert)",0
		even
	ENDC

VersStruct	dc.l	es_SIZEOF
		dc.l	0
		dc.l	ReqName
		dc.l	NotR2
		dc.l	Quit
ExistsStruct	dc.l	es_SIZEOF
		dc.l	0
		dc.l	ReqName
		dc.l	Exists
		dc.l	Quit
RequestStruct	dc.l	es_SIZEOF
		dc.l	0
		dc.l	ReqName
		dc.l	ReqTxt
		dc.l	ReqGadNames
CloseStruct	dc.l	es_SIZEOF
		dc.l	0
		dc.l	ReqName
		dc.l	CantClose
		dc.l	RetCan
ReqIDCMP	dc.l	0
GenericScreenTags
	dc.l	SA_PubName
NsName	dc.l	0		;en fait on met le nom barre titre ds PubName
	dc.l	TAG_DONE