; DisplayAlert -- © 1992 by Frédéric Delacroix
; This program will display an Intuition-type alert,with the provided text
; and type.
; Usage DisplayAlert [DEADEND] <Text>

	incdir	Include:
	include	exec/exec.i
	include	exec/exec_lib.i
	include	intuition/intuition.i
	include	intuition/intuition_lib.i
	include	libraries/dos_lib.i

TEXTSIZE	EQU	75
LINESIZE	EQU	TEXTSIZE+5
PIXELSIZE	EQU	TEXTSIZE*8

Args=0
ArgLen=4
ArgV=8
ArgC=12
IntBase=16
AlertText=20
AlertLen=24
NumberOfLines=28
CharsOnLastLine=30
AlertString=32
StringSize=36
VARSIZE=40

	lea	Variables(pc),a5
	move.l	a0,Args(a5)
	move.l	d0,ArgLen(a5)
	clr.b	-1(a0,d0)
	moveq.l	#20,d6
	lea	IntuitionName(pc),a1
	moveq	#0,d0
	move.l	4.w,a6
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,IntBase(a5)
	beq	Return
	move.l	ArgLen(a5),d0
	lsl.l	#1,d0
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
	jsr	_LVOAllocMem(a6)
	move.l	d0,ArgV(a5)
	move.l	d0,a1
	beq	CloseInt
	move.l	Args(a5),a0
	move.l	ArgLen(a5),d0
	bsr	Parse
	move.l	d0,ArgC(a5)
	beq.s	DisplayAbout
	move.l	ArgV(a5),a4
	move.l	(a4),a0
	lea	DEADEND.KWRD(pc),a1
	bsr	strcmp
	tst.l	d0
	bne.s	Recovery
	move.l	#DEADEND_ALERT,d7
	move.l	4(a4),AlertText(a5)
	bra.s	DoAlert

DisplayAbout
	lea	DosName(pc),a1
	moveq	#0,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,a6
	beq	FreeArgV
	jsr	_LVOOutput(a6)
	move.l	d0,d1
	lea	About.MSG(pc),a0
	move.l	a0,d2
	move.l	#About.LGT,d3
	jsr	_LVOWrite(a6)
	move.l	a6,a1
	move.l	4.w,a6
	jsr	_LVOCloseLibrary(a6)
	moveq	#0,d6
	bra	FreeArgV

Recovery
	moveq.l	#RECOVERY_ALERT,d7
	move.l	(a4),AlertText(a5)
DoAlert
	move.l	AlertText(a5),a3
	move.l	a3,a0
	bsr	strlen
	move.l	d0,AlertLen(a5)
	divu	#TEXTSIZE,d0
	addq.w	#1,d0
	move.w	d0,NumberOfLines(a5)
	swap	d0
	move.w	d0,CharsOnLastLine(a5)
	swap	d0
	mulu	#LINESIZE,d0
	and.l	#$FFFF,d0
	move.l	d0,StringSize(a5)
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
	jsr	_LVOAllocMem(a6)
	move.l	d0,AlertString(a5)
	beq	FreeArgV
	moveq.l	#0,d4
	move.w	NumberOfLines(a5),d4
	move.l	d0,a4
	moveq.l	#10,d3
FillNextLine
	subq.l	#1,d4
	beq.s	DoLastLine
	clr.b	(a4)+
	move.b	#10,(a4)+
	move.b	d3,(a4)+
	add.l	#10,d3
	move.l	a4,a1
	move.l	a3,a0
	moveq.l	#TEXTSIZE,d0
	bsr	strncpy
	lea	TEXTSIZE(a3),a3
	lea	TEXTSIZE+1(a4),a4
	move.b	#-1,(a4)+
	bra.s	FillNextLine
DoLastLine
	move.l	#PIXELSIZE,d0
	move.w	CharsOnLastLine(a5),d1
	lsl.w	#3,d1
	sub.w	d1,d0
	lsr.w	#1,d0
	move.b	d0,1(a4)
	lsr.w	#8,d0
	move.b	d0,(a4)
	addq.l	#2,a4
	move.b	d3,(a4)+
	move.l	a4,a1
	move.l	a3,a0
	moveq	#0,d0
	move.w	CharsOnLastLine(a5),d0
	bsr	strncpy

	move.l	d7,d0
	move.l	AlertString(a5),a0
	add.l	#10,d3
	move.l	d3,d1
	move.l	IntBase(a5),a6
	jsr	_LVODisplayAlert(a6)
	move.l	d0,d6
	beq.s	ReturnOK
	moveq.l	#5,d6
ReturnOK
	move.l	AlertString(a5),a1
	move.l	StringSize(a5),d0
	move.l	4.w,a6
	jsr	_LVOFreeMem(a6)
FreeArgV
	move.l	ArgV(a5),a1
	move.l	ArgLen(a5),d0
	lsl.l	#1,d0
	jsr	_LVOFreeMem(a6)
CloseInt
	move.l	IntBase(a5),a1
	jsr	_LVOCloseLibrary(a6)
Return
	move.l	d6,d0
	rts

strlen:	moveq	#-1,d0
strlenLoop	tst.b	(a0)+
	dbeq	d0,strlenLoop
	adda.l	d0,a0
	not.l	d0
	rts

strncpy:
	movem.l	d0/a0-a1,-(sp)
	subq.l	#1,d0
.Loop	move.b	(a0)+,(a1)+
	dbeq	d0,.Loop
	beq.s	.Ret
	clr.b	(a1)
.Ret	movem.l	(sp)+,d0/a0-a1
	rts

Parse:	movem.l	a2-a3,-(sp)
	move.l	a1,a3
	move.l	a3,-(sp)
	clr.b	-1(a0,d0)
	move.l	a0,a2
	lea	0(a0,d0.l),a1
SkipEndSpaces
	cmp.b	#" ",-(a1)
	dbhi	d0,SkipEndSpaces
	clr.b	1(a1)
NextWord
	move.b	(a0)+,d1	; Next Character into D1
	beq.s	EndOfString
	cmp.b	#" ",d1		; SPACE ?
	beq.s	NextWord
	cmp.b	#9,d1		; TAB ?
	beq.s	NextWord
	move.l	a2,(a3)+	; Store pointer to word
	cmp.b	#'"',d1		; " ?
	beq.s	Quote
	move.b	d1,(a2)+	; Store character
NextLetter
	move.b	(a0)+,d1
	beq.s	EndOfString
	cmp.b	#" ",d1		; SPACE ?
	beq.s	Unquote
	move.b	d1,(a2)+	; Store character
	bra.s	NextLetter
Unquote
	clr.b	(a2)+
	bra.s	NextWord
Quote	move.b	(a0)+,d1	; quoted string:ignore spaces
	beq.s	EndOfString
	cmp.b	#'"',d1		; " ?
	beq.s	Unquote
	cmp.b	#"*",d1		; * ?
	bne.s	NextQuotedChar
	move.b	(a0)+,d1
	cmp.b	#"n",d1		; n ?
	beq.s	NewLine
	cmp.b	#"N",d1		; N ?
	bne.s	NoNewLine
NewLine
	moveq	#10,d1		; LineFeed
	bra.s	NextQuotedChar
NoNewLine
	cmp.b	#"e",d1		; e ?
	beq.s	Escape
	cmp.b	#"E",d1		; E ?
	bne.s	NextQuotedChar
Escape	moveq	#$1B,d1		; ESC
NextQuotedChar
	move.b	d1,(a2)+
	bra.s	Quote
EndOfString
	clr.b	(a2)
	clr.l	(a3)
	move.l	(sp)+,d0
	sub.l	d0,a3
	move.l	a3,d0
	movem.l	(sp)+,a2-a3
	rts

strcmp:	movem.l	d1-d2/a0-a1,-(sp)
	moveq	#0,d0
strcmpLoop	move.b	(a0)+,d1
	beq.s	strcmpEOS1
	move.b	(a1)+,d2
	beq.s	strcmpSup
strcmpComp	cmp.b	d2,d1
	beq.s	strcmpLoop
	bcc.s	strcmpSup
strcmpInf	moveq	#-1,d0
	bra.s	strcmpRet
strcmpSup	moveq	#1,d0
	bra.s	strcmpRet
strcmpEOS1	tst.b	(a1)
	beq.s	strcmpRet
	moveq	#-1,d0
strcmpRet	movem.l	(sp)+,d1-d2/a0-a1
	rts

DosName	dc.b	'dos.library',0
IntuitionName
	dc.b	'intuition.library',0
DEADEND.KWRD
	dc.b	'DEADEND',0
About.MSG
	dc.b	'DisplayAlert -- by Frédéric Delacroix',10
	dc.b	'Usage: DisplayAlert [DEADEND] <AlertText>',10
	dc.b	' the DEADEND keyword (case sensitive) will make a DEADEND_ALERT',10
	dc.b	' (no return will be possible). Please use quotes ("") for the text',10
	dc.b	' if it contains more than one word. Return code will be WARN if',10
	dc.b	' the left-mouse button is pressed, OK if it''s the right one.',10
About.LGT=*-About.MSG
	even

Variables
	ds.b	VARSIZE

