*******************************************************************************
* Upper2Lower (in OS Framework)				   (c) 1995 Beldin/ATX
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* $Release	: 1.0 $
* $Revision	: 1.0 $
* $Date		: 3-1-96 $
*
* $Author(s)	: Written by Beldin (In MC680x0 Assembly under Asm-One)
* $Note(s)	: Position Independacy off a4 - (WARNING: DON`T TRASH A4!)
*		: SysBase Ptr is cached so that if running in fastmem access
*		: to SysBase ptr is faster.
*
* $Purpose	: Convert upper to lower case letters.
*               : Except at the start of sentence.
*******************************************************************************
*-------------- Definition Includes...

		incdir	include:

*- These are just the standard Commodore equ's and lvo's etc amalagamated
*- into 1 file.

		include	os3_gst.i

On	=	1		
Off	=	0
Yes	=	On
No	=	Off

*-------------- Definition of Main Variables (Public) Block...

		STRUCTURE VarsBlock,0

		APTR	_SysBase	/* SysBase base */
		APTR	_DosBase	/* DOS lib base */
		APTR	_DosOutput	/* DOS output base */

		APTR	_ReqToolsBase	/* reqtools base */

		APTR	_FileReq	/* ptr to file requester struct */
		APTR	_FileBuffer	/* ptr to buffer */
		UWORD	_FileLength	/* file lenght in bytes */
		APTR	_FileLock	/* holds the file lock */

		STRUCT	_FileName,34	/* space to keep filename */
		STRUCT	_DosPath,68	/* full dos path */
		STRUCT	_DosDir,68	/* full dir,0 */

		APTR	_ArgsPtr	/* argument pointer */
		APTR	_ArgsLength	/* argument length */


		UBYTE	_QuitFlag	/* 1 = yes, 0 = no */
		LABEL	vars_SIZEOF

*******************************************************************************
*-------------- Determine WB/CLI Enviroment (doesn`t corrupt CLI params)

StartUp:	move.l	d0,d7			;save CLI params len
		move.l	a0,a5			;save CLI params ptr
		suba.l	a1,a1			;clear a1
		move.l	4.w,a6			;get execbase
		CALL	FindTask		;find *THIS* task
		move.l	d0,a4			;get task ptr
		move.l	d7,d0			;restore CLI params len
		move.l	a5,a0			;restore CLI params ptr
		tst.l	pr_CLI(a4)		;did we originate from CLI?
		bne.s	ProgStart		;yes... call our program
		lea	pr_MsgPort(a4),a0	;from wb.. handle wb_startup
		move.l	a0,a4
		CALL	WaitPort		;wait for a message
		move.l	a4,a0
		CALL	GetMsg			;then get it
		move.l	d0,-(sp)
		bsr.s	ProgStart
		move.l	d0,d7			;save CLI Return code
		move.l	4.w,a6
		CALL	Forbid
		move.l	(sp)+,a1
		CALL	ReplyMsg
		move.l	d7,d0			;exit code
		rts
*******************************************************************************

VersionStr:	dc.b	'$VER: Upper2Lower 3-1-96  Beldin/Antrox',0 ;for 'version' command
		cnop	0,4			; longword align code.

*-------------- Allocate our Variables (RS.) Area

ProgStart:	move.l	#vars_SIZEOF,d0		; length for our variables
		move.l	#MEMF_PUBLIC+MEMF_CLEAR,d1 ; we want public mem, cleared
		move.l	(AbsExecBase).w,a6	; get SysBase
		CALL	AllocMem		; allocate it.
		move.l	d0,a4			; ptr to our RS.Variables base
		bne.s	RSValid			; did the alloc fail, if so exit
		moveq	#VAR_ERROR,d0		; Memory allocation fail code
		rts				; exit to dos.

*-------------- From here a4 points to our variables area (DON`T DESTROY A4!)

RSValid:	move.l	a6,(a4)			;cache execptr in Public so if

*-------------- Open all libs we want to use

		lea	LibTags(pc),a0		;pt to library script
		bsr.w	OpenTagLibs		;open libraries
		beq.w	_ShutDown		;if failed to open.. exit

*******************************************************************************
*-------------- Program starts here
*******************************************************************************

*-------------- Find the output window.

		CALLREL	Output,_DosBase
		move.l	d0,_DosOutput(a4)

*-------------- Write the about message to the shell window!

		lea	_AboutMsg(pc),a0
		bsr	_OSPutStr

*-------------- Clear me regs.

		clr.l	_FileBuffer(a4)
		clr.w	_FileLength(a4)
		clr.l	_FileLock(a4)

*-------------- Load file requester.

		lea	_LoadTitle(pc),a3
		bsr.w	_FileRequester
		tst.l	d0
		beq.s	_ShutDown

*-------------- Use dos to find the size and load.

		bsr.w	_DosLoadFile
		tst.l	_FileBuffer(a4)
		beq.s	_ShutDown

*-------------- Write the working message to the shell window!

		lea	_WorkMsg(pc),a0
		bsr	_OSPutStr

*-------------- Swap the cases.

		bsr	_CaseSwap

*-------------- Save file requester.

		lea	_SaveTitle(pc),a3
		bsr.w	_FileRequester
		tst.l	d0
		beq.s	_GetOutOfHere

*-------------- Use dos to save the file.

		bsr.w	_DosSaveFile

*-------------- Free the mem allocated for the _FileBuffer(a4)

_GetOutOfHere:	move.l	_FileBuffer(a4),a1
		tst.l	(a1)
		beq.s	_ShutDown
		clr.l	d0
		move.w	_FileLength(a4),d0
		move.l	(a4),a6			;get SysBase
		CALL	FreeMem

*******************************************************************************
*-------------- Program ends here
*******************************************************************************

*******************************************************************************
* Shutdown() - Free all allocated resources & exit program
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* Frees all previously allocated resources, sanity checks are made so only
* allocated memory/open libraries will be removed.
*******************************************************************************

*-------------- Close Open Libraries

_ShutDown:	lea	LibTags(pc),a0		;ptr to taglist of libs to close
		bsr.w	CloseTagLibs		;close all open libs..
		
*-------------- Free RS Variables Area

		move.l	a4,a1			;ptr to our RS.Variables base
		move.l	#vars_SIZEOF,d0		;no. of bytes to free
		move.l	(a4),a6			;get SysBase
		CALL	FreeMem			;free the memory

		moveq	#SUCCESS,d0		;no return code
		rts				;exit...
*****************************************************************************
*-------------- Swap upper to lower case.

_CaseSwap:	moveq.l	#0,d7
		move.w	_FileLength(a4),d7
		move.l	_FileBuffer(a4),a0	; source
		move.l	_FileBuffer(a4),a1	; destination

		move.b	(a0)+,(a1)+		; skip 1st char

*-------------- We have already done 1 char, and we have to adjust for dbra

		subq.w	#2,d7

.Loop:		move.b	(a0)+,d0

*-------------- Is it an "i"?

		cmpi.b	#"i",d0
		bne.s	.IsItEOP

*-------------- Yes, but has it a space before and after!

		cmpi.b	#" ",-2(a0)
		bne.s	.IsItEOP
		cmpi.b	#" ",(a0)
		bne.s	.IsItEOP

*-------------- Yes!  It should be in upper case then.

		move.b	#"I",(a1)+
		subq.w	#1,d7
		bra	.Loop

*-------------- Is it and End Of Paragraph?

.IsItEOP:	cmpi.b	#".",d0
		beq.s	.EOP
		cmpi.b	#"!",d0
		beq.s	.EOP
		cmpi.b	#"?",d0
		beq.s	.EOP

*-------------- Is it the 1st letter of a paragraph?

.IsItPraStart:	cmpi.b	#$0a,-2(a0)
		bne.s	.WhatCase		; no
		cmpi.b	#$0a,-3(a0)
		bne.s	.WhatCase		; no

*-------------- Is it lower case?

		cmpi.b	#$7a,d0			; "z"
		bgt.s	.Insert			; no, then leave it alone!
		cmpi.b	#$61,d0			; "a"
		blt.s	.Insert			; no, then leave it alone!

		bra.s	.L2U			; yes, then make it upper case
		
*-------------- Is it upper case?

.WhatCase:	cmpi.b	#$5a,d0			; "Z"
		bgt.s	.Insert
		cmpi.b	#$41,d0			; "A"
		blt.s	.Insert

*-------------- Is it an "I"?

		cmpi.b	#"I",d0
		bne.s	.U2L

*-------------- Yes, but has it a space before and after!

		cmpi.b	#" ",-2(a0)
		bne.s	.U2L
		cmpi.b	#" ",(a0)
		bne.s	.U2L
		bra.s	.Insert

*-------------- Convert the char to lower by adding $20

.U2L		addi.b	#$20,d0

.Insert		move.b	d0,(a1)+
		dbra	d7,.Loop
		rts

*-------------- The current char$ is an End Of Paragraph!

.EOP:		move.b	d0,(a1)+		; store the EOP char$
		subq.w	#1,d7			; adjust counter

.FindChar:	move.b	(a0)+,d0		; get the net char$

*-------------- Is the char$ after EOP a letter?

.Upper:		cmpi.b	#$5a,d0			; "Z"
		bgt.s	.Lower
		cmpi.b	#$41,d0			; "A"
		blt.s	.Lower

*-------------- It is already upper case so do nothing.

		bra.s	.Insert

.Lower:		cmpi.b	#$7a,d0			; "z"
		bgt.s	.NotLetter
		cmpi.b	#$61,d0			; "a"
		blt.s	.NotLetter

*-------------- Got it!  Now change it to upper case!

.L2U		subi.b	#$20,d0
		bra.s	.Insert

.NotLetter:	move.b	d0,(a1)+		; store char$
		subq.w	#1,d7			; adjust counter
		bra.s	.FindChar
*****************************************************************************
*-------------- Allocate reqtools file requester

_LoadTitle:	dc.b	"Select a file to load .....",0
		even
_SaveTitle:	dc.b	"Select a file to save .....",0
		even
_ReqTags:	dc.l	RT_ReqPos,REQPOS_CENTERSCR
		dc.l	TAG_DONE
_DeFault_Tags:	dc.l	RTFI_Dir,_DeFaultName
		dc.l	TAG_END
_DeFaultName:	dc.b	'ram:',0
		even

_FileRequester:	PUSHR	a3			; save the title
		move.l	#RT_FILEREQ,d0
		lea	_ReqTags(pc),a0
		CALLREL	rtAllocRequestA,_ReqToolsBase
		move.l	d0,_FileReq(a4)
		beq.w	.ReqError

*-------------- Set are default directory

		lea	_DeFault_Tags(pc),a0
		move.l	d0,a1				; a1 -> file req
		CALLREL	rtChangeReqAttrA,_ReqToolsBase

*-------------- Open the requester

		lea	_ReqTags(pc),a0
		move.l	_FileReq(a4),a1
		lea	_FileName(a4),a2
		clr.b	(a2)
		PULLR	a3			; get the title
		CALLREL	rtFileRequestA,_ReqToolsBase
		tst.l	d0
		beq.s	.FileError

*-------------- Make the full dos path

		lea	_DosPath(a4),a2
		lea	_DosDir(a4),a3

.DoDevice:	move.l	_FileReq(a4),a0
		move.l	rtfi_Dir(a0),a1

.DoDir:		move.b	(a1),(a2)+
		move.b	(a1)+,(a3)+
		bne.s	.DoDir
		cmpi.b	#":",-2(a2)
		beq.s	.NoSlash
.AddSlash:	suba.l	#1,a2
		move.b	#"/",(a2)+
		clr.b	(a3)
		bra.s	.DoName
.NoSlash:	suba.l	#1,a2
.DoName:	lea	_FileName(a4),a0
.Name:		move.b	(a0)+,(a2)+
		bne.s	.Name

*-------------- Close the file requester

.Done:		move.l	_FileReq(a4),a1
		CALLREL	rtFreeRequest,_ReqToolsBase
		move.l	#-1,d0			; all ok so flag it
		rts

*-------------- Selection canceled or failed!

.FileError:	move.l	_FileReq(a4),a1
		CALLREL	rtFreeRequest,_ReqToolsBase

*-------------- Error occured allocating the requester!

.ReqError:	moveq.l	#0,d0
		rts
*****************************************************************************
*-------------- Use the dos library to find the size and load file

_DosLoadFile:

*-------------- Open Dos File

.Open:		lea	_DosPath(a4),a1
		move.l	a1,d1
		move.l	#MODE_OLDFILE,d2
		CALLREL	Open,_DosBase
		move.l	d0,_FileLock(a4)
		beq.s	.Exit

*-------------- Determine it's length

.SeekStart:	move.l	_FileLock(a4),d1
		moveq.l	#0,d2			; distance
		moveq.l	#1,d3			; OFFSET_END
		CALLREL	Seek,_DosBase
		
.SeekEnd:	move.l	_FileLock(a4),d1
		moveq.l	#0,d2			; distance
		moveq.l	#-1,d3			; OFFSET_BEGINNING
		CALLREL	Seek,_DosBase
		move.w	d0,_FileLength(a4)

*-------------- Allocate mem for TextFileBuffer

.Alloc:		move.w	_FileLength(a4),d0
		move.w	#MEMF_CHIP,d1
		CALLREL AllocMem,_SysBase
		move.l	d0,_FileBuffer(a4)
		beq.s	.Close

*-------------- Read Dos File

.Read:		move.l	_FileLock(a4),d1
		move.l	_FileBuffer(a4),d2
		moveq.l	#0,d3
		move.w	_FileLength(a4),d3
		CALLREL	Read,_DosBase

*-------------- Close Dos File

.Close:		move.l	_FileLock(a4),d1
		CALLREL	Close,_DosBase
		clr.l	_FileLock(a4)
.Exit:		rts
*****************************************************************************
*-------------- Use the dos library to save file

_DosSaveFile:

*-------------- Open Dos File

.Open:		lea	_DosPath(a4),a1
		move.l	a1,d1
		move.l	#MODE_NEWFILE,d2
		CALLREL	Open,_DosBase
		move.l	d0,_FileLock(a4)
		beq.s	.Exit

*-------------- Write Dos File

.Write:		move.l	_FileLock(a4),d1
		move.l	_FileBuffer(a4),d2
		moveq.l	#0,d3
		move.w	_FileLength(a4),d3
		CALLREL	Write,_DosBase

*-------------- Close Dos File

.Close:		move.l	_FileLock(a4),d1
		CALLREL	Close,_DosBase
.Exit:		rts
*******************************************************************************
* OSPutStr(string) <NON MODIFIABLE> 
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* Sends a ascii text string to current console output
* 
* $Inputs:	: a0.l = String ptr (null terminated)
* $Output	: void
* $SR-Flags	: void
*******************************************************************************

_OSPutStr:	move.l	a0,d2

*-------------- Calculate string length.

		moveq	#-1,d3			; d4 = 0
.getlen2:	addq.l	#1,d3			; Increase string length by 1.
		tst.b	(a0)+			; Increase position.
		bne.s	.getlen2		; nope not found, so keep on.

*-------------- Write string to console.

		move.l	_DosOutput(a4),d1	; Dos output.
		move.l	_DosBase(a4),a6		; Dos base.
		CALL	Write			; Print error msg to cli.
		rts
******************************************************************************
* OpenTagLibs(library_taglist) <NON MODIFIABLE> 
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* $Inputs	: a0.l	= Taglist Pt
* $Format eg;	: dc.w	DOSName-*,_DOSBase,36
*		:
* $Output	: d0.b  = $FF.B if FAILED & $00.B if OKAY
* $SR-Flags	: Z-Flag cleared on FAIL
******************************************************************************
		
OpenTagLibs:	PUSH	d1-d7/a1-a3/a5-a6	;save registers
		move.l	_SysBase(a4),a6		;SysBase in a6
		move.l	a0,a5
.find_tag:	tst.w	(a5)			;TAG_DONE?
		beq.s	.tag_done		;end of taglist?
		move.l	a5,a1			;start of script
		add.w	(a5)+,a1		;a1=library name pt
		moveq	#0,d7			;clear d7
		move.l	d7,d0			;clear d0 for version no.
		move.w	(a5)+,d7		;d7=_XXXBase pt
		move.w	(a5)+,d0		;d0=lib version.
		PUSHR	a1			;stack libname pt
		CALL	OpenLibrary		;try to open desired library
		PULLR	a1			;get libname pt
		move.l	d0,(a4,d7.w)		;save lib base (to RS.)
		bne.s	.find_tag		;did it open? if so open next..
		sf.b	d0			;set Z Flag (d0=$00.B) FAILED!
		bra.s	.pullexit		;clean up stack and return
.tag_done:	st.b	d0			;clear Z Flag (d0=$FF.B) OKAY!
.pullexit:	PULL	d1-d7/a1-a3/a5-a6	;restore registers
		tst.b	d0
		rts				;libraries opened succefully!

CloseTagLibs:	PUSH	d0-d7/a0-a3/a5-a6	;save registers
		move.l	a0,a5			;make copy of taglist ptr
		move.l	_SysBase(a4),a6		;SysBase in a6
.find_tag:	tst.w	(a0)+			;TAG_DONE?
		beq.s	.tag_done		;end of taglist?
		move.l	a4,a1			;get RS. base
		add.w	(a0)+,a1		;create LibBase pt
		move.l	(a1),d0			;is this library open?
		beq.s	.find_tag		;no.. so don`t close it..
		move.l	d0,a1			;base of library to close
		tst.w	(a0)+			;skip version
		PUSHR	a0			;stack script pt
		CALL	CloseLibrary		;close this library
		PULLR	a0			;get script pt
		bra.s	.find_tag		;next tagitem please!
.tag_done:	PULL	d0-d7/a0-a3/a5-a6	;restore registers
script_done:	rts				;all open libraries closed..
******************************************************************************
*- String & Data Variable definitions

*-------------- Open Library definition script

LibTags:	dc.w	DosName-*,_DosBase,36
		dc.w	ReqToolsName-*,_ReqToolsBase,36
		dc.w	TAG_DONE

DosName:	dc.b	"dos.library",0
ReqToolsName:	dc.b	"reqtools.library",0

_AboutMsg:	dc.b	$0a,$0a
		dc.b	$9b,"1;31;40m"
		dc.b	" Upper2Lower v1"
		dc.b	$9b,"0;31;40m"
  		dc.b	" -  all code by: Beldin/Anthrox "
  		dc.b	$0a,$0a
		dc.b	" Convert chars from upper to lower case. "
		dc.b	$0a
		dc.b	" Except the 1st char of a new sentence. "
		dc.b	$0a,$0a
		dc.b	" Small `i's are converted to upper case if,"
		dc.b	$0a
		dc.b	" there is a space before and after!."
		dc.b	$0a,$0a
		dc.b	0
		even
_WorkMsg:	dc.b	$0a
		dc.b	" Working on convert!  - Please Wait - "
		dc.b	$0a,$0a
		dc.b	0

		END
