*****************************************************************************
*
* RemLib.asm	by	HEIKO RATH 
*			copyright 1987/88 by the Software Brewery
*
* The purpose of this program is to remove a library from the librarylist.
* To be save, it only removes librarys with an OpenCnt of 0.
* To get a list of all librarys use RemLib without an argument.
*								Heiko Rath
* Version 1.00 - printed all libraries with one Write (with many libs -> GURU)
* Version 1.01 - prints every row with an extra Write
* Version 1.05 - now features positive and negative size of library
* Version 1.10 - now stops on CTRL-C
* Version 1.11 - worked on error texts
*
*
* This program is
*  
* Copyright (c) 1988 by Heiko Rath and the Software Brewery.
* 
* It may be freely distributed for non-profit only.
* The distribution must contain ALL parts, in this case the following
* files:
* 
* RemLib
* RemLib.asm
* 
* Putting it on a commercial product is usually as easy as sending
* a letter to the author.
*
*****************************************************************************
*______  /          
*______\O                     - The Software Brewery - 
*      \\ 
*       o           Sparkling, fresh software from West-Germany
*
*     @@@@@             Straight from the bar to your Amiga
*     |~~~|\ 
*     | | |/ 
*     |___|        With our regards to the Software Distillery
*
*Christian Balzer alias <CB>, Lattice C, user interfaces, beer addict. 
*Heiko Rath alias <HR>, Assembler, ROM-Kernal stuff, Marabou & beer addict. 
*Ralf Woitinas alias RAF, Assembler, anything, Ray-Tracing addict.
*Andrew Kopp alias Charlie, Aztec C, Hardware & communications, beer addict.
*Armin Sparr alias MARVIN, Aztec C, ARexx macros, Campari addict.
*Christof Bonnkirch alias KEY, Aztec C, Hardware & Devices, beer addict.
*
*Beverages: Altenmuenster Brauer Bier, Urfraenkisches Landbier, Jever.
*
*Send exotic drinks, mail, comments and flames to:
*
*The Software Brewery
*Christian Balzer		UUCP: decwrl!frambo.dec.com!schabacker
*Im Wingertsberg 45		ARPA: schabacker@frambo.dec.com
*D-6108 Weiterstadt		CIS : 71001,210 (be brief!)
*WEST GERMANY (F.R.G.)		Fone: +49 6150 4151 (18:00-21:00 CET!)
*
*
*Send the above stuff, beautiful girls and of course MARABOU-CHOCOLATE to:
*
*Heiko Rath (HHHEEELLLPPP, I'm running out of MARABOU chocolate!!!!!!!)
*Raiffeisenstr.10a
*D-6108 Weiterstadt
*WEST GERMANY (F.R.G.)
*

Version		MACRO
		dc.b	'1.11'
		ENDM

ExecBase	Equ	4

***
*** Exec Offsets:
***
OpenLibrary	Equ	-552		;OpenLibrary (LibName,version)(a1,d0)
CloseLibrary	Equ	-414		;CloseLibrary (Library)(a1)
Forbid		Equ	-132		;Forbid ()()
Permit		Equ	-138		;Permit ()()
AllocMem	Equ	-198		;AllocMem (bytesize,requirement)(d0,d1)
FreeMem		Equ	-210		;FreeMem (memoryblock,bytesize)(a1,d0)
FindName	Equ	-276		;FindName (list,name) (a0,a1)
RemLibrary	Equ	-402		;RemLibrary (library)(a1)
SetSignal	Equ	-306		;SetSignal (newSignals,signalMask)(d0,d1)

***
*** DOS Offsets:
***
OutPut		Equ	-60		;OutPut ()
Input		Equ	-54		;Input ()
Write		Equ	-48		;Write (file,buffer,length)(d1,d2,d3)

***
*** I use these Macros to make things easier for me
***

doit:	MACRO
	move.l	#HeadLine,d2		;address of HeadLine to d2
	bsr	TextOutPut		;output HeadLine
	move.l	\1,d0			;offset of listhead to d0
	bsr	Showlib			;output library-list
	ENDM

***
*** Here we go:
***
	move.l	sp,d6			;store stack pointer on stack
	move.l	a0,a2			;save cmdline address
	sub.w	#1,d0
	clr.b	0(a2,d0.w)		;make the cmdline null terminated

	move.l	ExecBase,a6		;Execaddress to a6 (only to be sure)
	move.l	#DOSNAME,a1		;Librarynamepointer to a1
	moveq	#0,d0			;any version
	jsr	OpenLibrary(a6)		;try to open DOS-Libary
	tst.l	d0			;is d0 = NULL?
	beq	ErrorExit		;exit if call wasn't successfull
	move.l	d0,DOSBase		;save DOSBasepointer
	move.l	d0,a6			;move DOSBasepointer to a6
	jsr	OutPut(a6)		;identify the initial output handle
	move.l	d0,stdout		;save stdout

	move.l	#Text,d2
	bsr	TextOutPut

SkipSP:	
	move.b	(a2)+,d1		;skip spaces
	beq	ShowTheLibs		;if NULL-String then /* show librarys */
	cmp.b	#' ',d1			;is it a Space ?
	beq.b	SkipSP			;yes -> SkipSP

	cmp.b	#'?',d1			;is it '?' ?
	beq	ShowHow			;yes -> ShowHow

	cmp.b	#'"',d1			;is it '"' ?
	bne.b	001$			;yes -> 001$
	add.l	#1,a2
	move.l	a2,a1
002$:
	move.b	(a1)+,d1
	beq	NoSuchLibrary
	cmp.b	#'"',d1
	beq.b	003$
	bra.b	002$
003$:
	sub.l	#1,a1
	move.b	#0,(a1)
001$:
	sub.l	#1,a2			;decrement address by one
	move.l	ExecBase,a6		;ExecBase to a6
	move.l	a6,a0			;ExecBase to a0
	add.l	liblist,a0		;address of librarylist to a0
	move.l	a2,a1			;address of string to a1
	jsr	FindName(a6)		;search for the given name
	tst.l	d0			;is there a library with the given name

	beq.b	NoSuchLibrary		;no -> NoSuchLibrary

	move.l	d0,a1			;copy address of library to a1
	move.w	32(a1),d0		;get OpenCnt
	tst.w	d0			;is the OpenCnt = 0?
	bne.b	NotZero			;no -> say that the library is still open
	jsr	RemLibrary(a6)		;try to close the library
	tst.l	d0
	bne.b	Success			;->Success

	move.l	#FailedToRemove,d2
	bsr	TextOutPut
	bra.b	CloseDOS

Success:
	move.l	#Successfull,d2
	bsr	TextOutPut
	bra.b	CloseDOS

NoSuchLibrary:
	move.l	#NotFound,d2
	bsr	TextOutPut
	bra.b	CloseDOS

NotZero:
	move.l	#NotAbleToClose,d2
	bsr	TextOutPut
	bra.b	CloseDOS

ShowTheLibs:
	doit	liblist			;output Librarylist

CloseDOS:
	move.l	ExecBase,a6		;ExecBase to a6
	move.l	DOSBase,a1		;DOS-pointer to a1
	move.l	ExecBase,a6		;Exec-pointer to a6
	jsr	CloseLibrary(a6)	;close DOS
ErrorExit:
	move.l	d6,sp			;restore stack pointer
	rts				;CLI here we go again!!!!

ShowHow:
	move.l	#HelpText,d2
	bsr	TextOutPut
	bra.b	CloseDOS

*****************************************************************************
*
*	Showlib II				11.1.87 modified on 18.10.88
*			by	Heiko Rath
*				Raiffeisenstr.10a
*				D-6108 Weiterstadt
*				WEST GERMANY (F.R.G.)
*
*
* PURPOSE:			print out Librarylist (address of Node,
*				type, priority, name of Node, version, revision,
*				opencount, negative size, positive size)
*
* ROUTINETYPE:			subroutine
*
* SYNTAX:			bsr Showlib	(Exec-offset to librarylist)(d0)
*
* ENTRY CONDITIONS:		needs DOSlibrary opened and stdout defined
*				also needs DOS-'Write' offset -48 defined.
*				It also needs binhex subroutine.
*
* RETURNS:			none
*
* BUGS:				none
*
* NOTE:				none
*
* CHANGED:			nothing
*
* USAGE:			move.l	LibraryListOffset,d0
*				bsr	Showlib
*
*****************************************************************************
Showlib:
	movem.l	d0-d7/a0-a6,-(sp)	;save registers

	move.l	ExecBase,a6		;ExecBase to a6
	jsr	Forbid(a6)		;forbid taskswitching (very important,
					; 'cause we are accessing Systemdata)

	move.l	a6,a0			;Execpointer to a0
	add.l	d0,a0			; + librarylistoffset=address of listhead
	move.l	a0,ListHead		;save address of listheader -=> ListHead
	move.l	(a0),a1			;get address of 1.Node to a1
	move.l	a1,Node			;save address of 1.Node -=> Node
	addq.l	#4,a0
	cmp.l	a1,a0			;list empty?
					;(test if listhead points to listhead+4)
	beq	PrintLF			;yes -=> send LF and exit

	moveq.l	#1,d1			;set counter to 1 'cause there is at least
					; one node in the list
MyCountLoop:
	move.l	(a1),a1			;get address of next node to a1
	tst.l	(a1)			;see if contents of (a1) is NULL
	beq.b	EndCount		;leave counting loop
	addq.l	#1,d1			;increment counter by one
	bra.b	MyCountLoop		;do this once more

EndCount:
	move.l	d1,NodeCount		;save number of Nodes

	move.l	#71,d0			;number of bytes per node
	mulu	d1,d0			;bytes per node * NodeCount
	addq.l	#1,d0			;add one for the bufferterminating Null
	move.l	d0,MyMemoryLength	;save lenght of Memoryblock
	move.l	#$10001,d1		;requirements:MEMF_Public & Clear
	jsr	AllocMem(a6)		;get memory from system
	move.l	d0,MyMemoryBlock	;save address of Memoryblock
	move.l	d0,MyMemoryOffset	;save address of Memoryblock 2.time
	tst.l	d0			;see if call was successfull
	bne	MoveNodeToBuffer	;yes -=> MoveNodeToBuffer

	move.l	#Err,d2			;this code is only here, to inform the
	bsr	TextOutPut		; user that the AllocMem call wasn't
	bra	PrintLF			; successfull

MoveNodeToBuffer:
	move.l	d0,a0			;get address of MemoryBlock to a0
	move.l	MyMemoryLength,d1	;get length to d1

fill:
	move.b	#' ',(a0)+		;fill MyMemoryBlock with spaces
	dbeq.b	d1,fill			;is d1=NULL? (no-=>d1=d1-1-=>fill)

TheLoop:
	move.l	MyMemoryOffset,a0	;get address of MyMemoryOffset to a0
	move.l	Node,a1			;get address of current node to a1

	add.l	#10,a1			;address of namepointer to a1
	move.l	(a1),a1			;get address of nodename to a1
	moveq.l	#0,d1			;this is faster than clr.l d1
	moveq.l	#0,d2			;set this to NULL for strlen

strlen:
	cmp.b	(a1)+,d2		;NULL?
	beq.b	strlentest		;yes -=>strlentest
	addq.l	#1,d1			;increment d1 by one (stringlength)
	bra.b	strlen			;do the loop once more

strlentest:
	cmp.b	#20,d1			;see if string is greater #20
	ble.b	DoCopy			;no (less or equal)-=>DoCopy
	move.l	#20,d1			;set max.length to 20

DoCopy:
	move.l	Node,a1			;get address of node to a1
	add.l	#10,a1			;address of namepointer to a1
	move.l	(a1),a1			;get address of nodename to a1
	tst.l	d1			;see if d1=0
	bne	DoTheCopy		;jump only if d1<>0
	move.l	#NoName,a1		;get address of NoName to a1
	moveq.l	#7,d1			;set length to 7 (length of 'No Name')

DoTheCopy:
	subq.l	#1,d1			;decrement d1 by 1

CopyLoop:
	move.b	0(a1,d1),0(a0,d1)	;copy source to destination
	dbf	d1,CopyLoop		;decrement d1, if d1<0 then out of loop

	move.l	MyMemoryOffset,a0	;get address of MyMemoryOffset to a0
	move.b	#'$',21(a0)		;store '$'
	move.b	#'$',35(a0)		;store '$'
	move.b	#10,69(a0)		;store LF
	move.b	#0,70(a0)		;store end of string

	move.l	Node,a1			;get Nodeaddress to a1
	addq.l	#8,a1			;add 8 to get address of Type
	moveq.l	#0,d0			;clear d0
	move.b	(a1),d0			;get Type to d0
	move.l	MyMemoryOffset,a0
	add.l	#31,a0
	bsr	bindecb			;convert to ASCII

	move.l	Node,a1			;get Nodeaddress to a1
	add.l	#9,a1			;add 1 to get address of Priority
	moveq.l	#0,d0
	move.b	(a1),d0
	move.l	MyMemoryOffset,a0
	add.l	#35,a0
	bsr	bindecb

	move.l	Node,a1			;get Nodeaddress to a1
	add.l	#32,a1			;add 32 to get address of OpenCnt
	moveq.l	#0,d0			;clear d0
	move.w	(a1),d0			;get OpenCnt to d0
	move.l	MyMemoryOffset,a0
	add.l	#39,a0
	bsr	bindecw			;convert OpenCnt to ASCII

	move.l	Node,a1			;get Nodeaddress to a1
	add.l	#20,a1
	moveq.l	#0,d0
	move.w	(a1),d0			;Version
	move.l	MyMemoryOffset,a0
	add.l	#45,a0
	bsr	bindecw

	move.l	Node,a1
	add.l	#22,a1
	moveq.l	#0,d0
	move.w	(a1),d0			;Revision
	move.l	MyMemoryOffset,a0
	add.l	#51,a0
	bsr	bindecw

	move.l	Node,a1
	add.l	#16,a1
	moveq.l	#0,d0
	move.w	(a1),d0			;NegSize
	move.l	MyMemoryOffset,a0
	add.l	#57,a0
	bsr	bindecw

	move.l	Node,a1
	add.l	#18,a1
	moveq.l	#0,d0
	move.w	(a1),d0			;PosSize
	move.l	MyMemoryOffset,a0
	add.l	#63,a0
	bsr	bindecw

	move.l	Node,d0			;get Nodeaddress to d2
	move.l	MyMemoryOffset,a0	;get address of MyMemoryOffset to a0
	add.l	#22,a0			;add 22 to get storeaddress
	bsr	binhex			;convert address to ASCII

	add.l	#71,MyMemoryOffset	;do this for the next loop
	move.l	Node,a1			;get nodeaddress to a1
	move.l	(a1),Node		;save address of next node
	move.l	MyMemoryOffset,d0	;get MyMemoryOffset to d0
	addq.l	#1,d0
	move.l	MyMemoryBlock,d1	;get MyMemoryBlock to d1
	add.l	MyMemoryLength,d1	;add MyMemoryLength to d1
	cmp.l	d0,d1			;see if we have to loop once more
	bne	TheLoop			;if <> -=> TheLoop
	move.l	MyMemoryBlock,a0	;get address of MyMemoryBlock to a0
	add.l	MyMemoryLength,a0	;add length to MyMemoryBlock
	subq.l	#1,a0			;decrement address by one
	move.b	#0,(a0)			;set last byte of MyMemoryBlock to NULL

	move.l	NodeCount,d3		;get number of nodes to d3
	move.l	MyMemoryBlock,d2	;get address of MyMemoryBlock to d2
FinallyPrintIt:
	bsr	TextOutPut		;print one line
	add.l	#71,d2			;increment string startaddress by 71
	clr.l	d0			;clear newSignals
	clr.l	d1			;clear signalMask
	jsr	SetSignal(a6)		;get the signalmask of our task
	btst	#12,d0			;is the CTRL-C Bit set?
	bne	CTRL_C_Break		;if yes -> CTRL_C_Break
	tst.l	d3			;get desired flag to CCR
	dbeq	d3,FinallyPrintIt	;is d3=NULL? (no-=>d3=d3-1-=>FinallyPrintIt

	move.l	MyMemoryBlock,a1	;get address of MyMemoryBlock to a1
	move.l	MyMemoryLength,d0	;get length of MyMemoryBlock to d0
	jsr	FreeMem(a6)		;free the allocated RAM

PrintLF:
	move.l	#LF,d2			;get address of LF-string to d2
	bsr.b	TextOutPut		;and get it out via DOS-Write & stdout
	jsr	Permit(a6)		;permit taskswitching (I think Dos enables
					; this for you, but I do this to be sure
					; that taskswitching is now allowed.)
	movem.l	(sp)+,d0-d7/a0-a6	;restore Registers
	rts

*****************************************************************************
*
*	TextOutPut
*			by	Heiko Rath
*				Raiffeisenstr.10a
*				D-6108 Weiterstadt
*				WEST GERMANY (F.R.G.)
*
* PURPOSE: 		output a NULL-terminated string via stdout
*
* ROUTINE TYPE: 	subroutine
*
* SYNTAX:		bsr	TextOutPut	(stringaddress)(d0)
*
* ENTRY CONDITIONS:	needs DOSlibrary opened and stdout defined
*			also needs DOS-'Write' offset -48 defined.
*
* RETURNS:		none
*
* NOTE:			its better if the string is really NULL-terminated
*
* CHANGED:		nothing
*
* USAGE:		move.l	#Textaddress,d2
*			bsr	TextOutPut
*
*****************************************************************************

TextOutPut:
	movem.l	d0-d7/a0-a6,-(sp)	;save registers
	move.l	d2,a0			;address to a0
	clr.l	d3			;count = 0

CountLoop:
	tst.b	(a0)+			;is it NULL ?
	beq.b	PMsg			;yes: -=> determine length
	addq.l	#1,d3			;count = count+1
	bra.b	CountLoop		;test next byte

PMsg:
	move.l	stdout,d1		;get stdout to d1
	move.l	DOSBase,a6		;move DOSBase to a6
	jsr	Write(a6)		;write the Text
	movem.l	(sp)+,d0-d7/a0-a6	;reserve registers
	rts

***********************************************************************
*
*	 binhex
*		 	by Heiko Rath
*
* PURPOSE: Convert a binary value in a register to
*	    a hex ASCII string at the destination address
*          
* ROUTINE TYPE: SUBROUTINE
*
* SYNTAX: bsr	binhex	(source(long),destination) (d0.l,a0)
*	   bsr	binhexw	(source(word),destination) (d0.w,a0)
*	   bsr	binhexb	(source(byte),destination) (d0.b,a0)
*
* ENTRY CONDITIONS: None
*
* RETURNS: ASCII string in destination address
* NOTE: 	the destination place must contain 8 bytes for any
*	        length (byte, word, longword)
*
* CHANGED: Nothing
*
* USAGE:
*
*	 move	#label,d0
*	 move.l	address,a0	;converts the address at label to
*	 bsr	binhex		;string at address
*				
*	 move	label,d0
*	 move.l	address,a0
*	 bsr	binhex		;conv contents at label
*
*	 move	#value,d0
*	 move.l	address,a0
*	 bsr	binhex		;convert immediate value
*
****************************************************************

binhex:	movem.l	d0-d2/a0,-(sp)		;save registers

	move.l	#7,d2			;get number of counts to d2
	clr.l	d1			;clear work register

001$:	rol.l	#4,d0			;move high nibble to low order
	move.b	d0,d1			;get low order byte to d1
	andi.b	#$f,d1			;isolate low order nibble
	cmp.b	#$0a,d1			;is it a letter or a digit?
	blt.b	002$			;if digit -=> 002$
	add.b	#'A'-'0'-$0A,d1		;offset for letters

002$:	add.b	#'0',d1			;convert to ASCII
	move.b	d1,(a0)+		;store it and increment storeaddress
	dbf.b	d2,001$			;do the converting 8 times

	movem.l	(sp)+,d0-d2/a0		;restore registers
	rts

***********************************************************************
*
*	 bindec
*		 	by Heiko Rath
*
* PURPOSE: Convert a binary value in a register to
*	    a dec ASCII string at the destination address
*          
* ROUTINE TYPE: SUBROUTINE
*
* SYNTAX:
*	   bsr	bindecw	(source(word),destination) (d0.w,a0)
*	   bsr	bindecb	(source(byte),destination) (d0.b,a0)
*
* ENTRY CONDITIONS: None
*
* RETURNS: ASCII string in destination address
* NOTE: 	the destination place must contain 5 bytes for any
*	        length (byte, word). Don't use longwords!
*
* CHANGED: Nothing
*
* USAGE:
*
*	 move	#label,d0
*	 move.l	address,a0	;converts the address at label to
*	 bsr	bindec		;string at address
*				
*	 move	label,d0
*	 move.l	address,a0
*	 bsr	bindec		;conv contents at label
*
*	 move	#value,d0
*	 move.l	address,a0
*	 bsr	bindec		;convert immediate value
*
****************************************************************

bindecb:
	movem.l	d0-d2/a0,-(sp)		;store registers
	move.l	d0,d1
	move.l	a0,a1
	bra.b	ByteToDec

bindecw:
	movem.l	d0-d2/a0,-(sp)		;save registers
	move.l	d0,d1
	move.l	a0,a1

	divu	#10000,d1
	bsr.b	StoreOneByte
	divu	#1000,d1
	bsr.b	StoreOneByte
ByteToDec:
	divu	#100,d1
	bsr.b	StoreOneByte
	divu	#10,d1
	bsr.b	StoreOneByte
	bsr.b	StoreOneByte

003$:					;003$ is used to clear the
	move.b	(a1)+,d0		; leading zeros
	cmp.b	#'0',d0
	bne.b	002$
	cmp.b	#' ',(a1)
	beq.b	002$
	move.b	#' ',-(a1)
	add.l	#1,a1
	bra.b	003$
002$:
	movem.l	(sp)+,d0-d2/a0		;restore registers
	rts

StoreOneByte:
	add.b	#$30,d1
	move.b	d1,(a0)+
	clr.w	d1
	swap	d1
	rts

CTRL_C_Break:
	move.l	MyMemoryBlock,a1	;get address of MyMemoryBlock to a1
	move.l	MyMemoryLength,d0	;get length of MyMemoryBlock to d0
	jsr	FreeMem(a6)		;free the allocated RAM

	move.b	#1,BreakFlag		;set our internal break flag
	move.l	#BREAK,d2		;get address of Break-string to d2
	bsr	TextOutPut		;and get it out via DOS-Write & stdout
	jsr	Permit(a6)		;permit taskswitching (I think Dos enables
					; this for you, but I do this to be sure
					; that taskswitching is now allowed.)
	movem.l	(sp)+,d0-d7/a0-a6	;restore Registers
	rts

***
*** Variables:
***

DOSBase:	dc.l	0		;this contains the DOSlibraryaddress
stdout:		dc.l	0		;this contains stdout
stdin:		dc.l	0		;this contains stdin
ListHead:
	dc.l	0			;At runtime this contains the
					; address of the listheader
Node:
	dc.l	0			;At runtime this contains the
					; address of the current node
NodeCount:
	dc.l	0			;At runtime this contains the
					; number of nodes in the list
MyMemoryLength:
	dc.l	0			;At runtime this contains the
					; length of the memoryblock
MyMemoryBlock:
	dc.l	0			;At runtime this contains the
					; address of the memoryblock
MyMemoryOffset:
	dc.l	0			;At runtime this contains the
					; address of the memoryblock
					; + 71 Bytes per finished node
BreakFlag:
	dc.b	0			;This is set if we encounter a CTRL-C
	cnop	0,2

***
***Constants:
***
liblist:	dc.l	$17a

DOSNAME:	cstring	'dos.library'
		cnop	0,2
Err:		dc.b	'*** Out of Memory Error ***',0
		cnop	0,2
NoName:		dc.b	'No Name',0
		cnop	0,2
LF:		dc.b	10,0		;LF
		cnop	0,2
BREAK:		dc.b	'***BREAK',10,0
		cnop	0,2
HeadLine:	dc.b	$9b,'4;32;40m'
		dc.b	'Name                  Address  Typ Pri OpenC'
		dc.b	' Vers. Revs.  Neg.  Pos.'
		dc.b	$9b,'0;31;40m',10,0
		cnop	0,2
Text:
	dc.b	$9b,'0;33;40m','Lib-Remover',$9b,'0;31;40m '
	dc.b	$9b,'3;31;40m','V'
	Version
	dc.b	$9b,'0;31;40m'
	dc.b	' by ',$9b,'0;32;40m','Heiko Rath',$9b,'0;31;40m',' - '
	dc.b	$9b,'4;31;40m',169,'1988 by ',$9b,'1;31;40m'
	dc.b	'The Software Brewery',$9b,'0;31;40m',10
	dc.b	'Raiffeisenstr.10a,  D-6108 Weiterstadt,  '
	dc.b	'WEST GERMANY  (F.R.G.)',10,0

Successfull:
	dc.b	10,'Succeeded in removing the library.',10,0
	cnop	0,2
NotAbleToClose:
	dc.b	10,$9b,'0;33;40m','Attention:',$9b,'0;31;40m'
	dc.b	' This library can not be closed, cause OpenCnt > 0.',10,0
	cnop	0,2
FailedToRemove:
	dc.b	10,$9b,'0;33;40m','Attention:',$9b,'0;31;40m'
	dc.b	' Failed to remove the library.',10,0
	cnop	0,2
NotFound:
	dc.b	10,$9b,'0;33;40m','Attention:',$9b,'0;31;40m'
	dc.b	' Library not found.',10,0
	cnop	0,2
HelpText:
	dc.b	10,'Use ',$9b,'0;33;40m','Remlib',$9b,'0;31;40m'
	dc.b	' without argument to display all libraries.',10
	dc.b	'Use ',$9b,'0;33;40m','Remlib',$9b,'0;31;40m'
	dc.b	' "name.library" to remove a library.',10
	dc.b	'Note: It''s only possible to remove libraries with',10
	dc.b	'      an opencount of 0.',10,0
