*-----------------------------------------------------*
*                PlusCR Version 1.0                   *
*                                                     *
*       Copyright August 1989 - by Bill Nelson        *
*             Midnight Logic Software                 *
*                                                     *
*      This is a FREELY REDISTIBUTABLE PROGRAM        *
*                                                     *
* Please report any bugs or problems you find         *
* (there PROBABLY are some!) - and any suggestions    *
* for further functionality would also be welcomed.   *
* Happy Assembling!                                   *
*                                                     *
*   v 1.0            00:00:01             08/08/89    *
*                                                     *
*-----------------------------------------------------*
*                                                     *
* This program will add CR to existing LF chars, for  *
* transfer to MS-DOS or other systems that require    *
* both characters.  If file is ONLY CR chars, OR if   *
* file has already been processed, it will make no    *
* changes.  It works in conjunction with its partners *
* StripCR and StripLF to provide complete conversion  *
* capabilities to and from any system.                *
*                                     Bill Nelson     *
*-----------------------------------------------------*


   bra   Start                   ; Jump into Startup.ASM

   INCLUDE  "INCLUDES/Header.ASM"

_Main

CheckParameters
   move.l    CmdLen,d0           ; Check if user entered filename
   cmpi.l    #1,d0               ; on the command line
   beq       BadArgs             ; if not, exit with explanation
   move.l    Command,a1          ; check if ? is parameter
   cmpi.b    #'?',(a1)           ;
   beq       Usage
   move.l    Command,d1          ; or set it up for CheckExists
   move.l    d1,FileNm           ; and store pointer for later access
   bra       OpenFile

BadArgs
   QPrint    StdErr
   dc.b      10,'Bad Arguments',10,0
   EvenPC
Usage
   QPrint    StdErr              ; ? on Command Line, so we explain
   dc.b      10,'     Usage: PlusCR filename',10
   dc.b      10,'     Copyright July 1989 by'
   dc.b      10,'Bill Nelson  of Midnight Logic Software',10,0
   EvenPC

CheckInteractive
   move.l    StdIn,d1            ; make sure we weren't RUN
   DosCall   IsInteractive       ; because then we can't GET a filename!
   tst.l     d0                  ; we WERE RUN
   beq       WayOut              ; bye.....
Interactive
   QPrint    StdOut              ; not RUN, ask for filename
   dc.b      10,'  Enter a Filename, or RETURN to exit'
   dc.b      10,'  Filename? ',0
   EvenPC

GetFileName
   DosRead   StdIn,#KeyBuff,#80  ; and see if they want a file after all!
   cmpi      #1,d0               ; was it RETURN char only
   beq       QuitandExit         ; yes - wants out...
   lea       KeyBuff(pc),a0      ; PTR to buff location, for calculation
   clr.b     -1(a0,d0)           ; of end of input, put 0 byte there (over CR)
   move.l    #KeyBuff,d1         ; put PTR to filename in d1 for _CheckExists
   move.l    d1,FileNm           ; and store pointer for later access


*********  Open the file    **********


OpenFile
   bsr       _CheckExists        ; try for Lock on file
   tst.l     d0
   beq       NoSuchFile          ; error message, and get out
   move.l    d0,FileLock         ; stash it for other uses!
   bsr       _GetFileSize        ; find out the file size - how much MEM?
   tst.l     d0
   beq       MemFail             ; couldn't get the filesize (mem?)
   move.l    d0,FileSize
   AllocPubMem FileSize          ; alloc enough mem for file buffer
   tst.l     d0                  ; See if call made it
   beq       MemFail             ; or leave...
   move.l    d0,FileMemBuf       ; otherwise, store PTR to memory
                                 ; (automatically LONG aligned by EXEC)
   move.l    FileNm,d1           ; put PTR to filename in d1
   move.l    #MODE_ReadOnly,d2   ; for reading
   DosCall   Open
   tst.l     d0                  ; see if a handle was returned (success)
   beq       OpenTrouble         ; No? Skip the rest
   move.l    d0,FilePTR          ; or store handle if successful
   bra       ReadFile            ; and go read the file in already!

OpenTrouble
   QPrint    StdErr
   dc.b      'Cannot open the file...',13,10,10,0
   EvenPC
   bra       Error

NoSuchFile
   QPrint    StdErr
   dc.b      10,'Unable to find requested file...',13,10,10,0
   EvenPC
   bra       Error

MemFail
   QPrint    StdErr
   dc.b      10,'Unable to allocate enough memory...',13,10,10,0
   EvenPC
   bra       Error



*********  Read the file in  ***********


ReadFile
   DosRead   FilePTR,FileMemBuf,FileSize
   tst.l     d0
   bgt       KeepGoing           ; greater than 0, is length of useful file
   move.l    FilePTR,d1          ; or shut it down.
   DosCall   Close
   move.l    FileLock,d1         ; better not forget to UNLOCK the file!
   DosCall   UnLock              ; so we do it now...
   move.l    #0,FileLock         ; and clear the storage area
   QPrint    StdErr              ; tell user what happened
   dc.b      10,'Unable to read file...',13,10,10,0
   EvenPC
   bra       Error               ; and skip the country!
KeepGoing
   move.l    d0,FileSize         ; tells us how many were really there
   move.l    FilePTR,d1          ; STILL no trust :-)
   DosCall   Close               ; won't need it again
   move.l    FileLock,d1         ; better not forget to UNLOCK the file!
   DosCall   UnLock              ; so we do it now...
OpenForWrite
   move.l    FileNm,d1           ; put PTR to filename in d1
   move.l    #MODE_NewFile,d2    ; for writing
   DosCall   Open
   tst.l     d0                  ; see if a handle was returned (success)
   beq       OpenTrouble         ; No? Skip the rest
   move.l    d0,FilePTR          ; or store handle if successful


************  Format lines for output  **********

StartLoop
   move.l    FileMemBuf,a2       ; Start of file buffer
   move.l    FileSize,a3         ; Number of chars it contains
   adda.l    a2,a3               ; End of buffer now in a3
   move.l    a2,a4               ; and start of line in a4
   Zero      d6                  ; no CR flag
   Zero      d3                  ; number of chars
FileScan
   move.b    (a2)+,d0            ; move byte to d0, and increment a2
   cmpi.b    #13,d0              ; is byte a CR?
   beq       IsCR                ; Yes, act on it
   cmpi.b    #10,d0              ; is byte a LF
   beq       IsLF                ; do it to it
   addq      #1,d3               ; increment charcount in d3
   cmpa.l    a2,a3               ; compare a2 with End of buffer
   bgt       FileScan            ; if not, get next char
   bra       ExitFile            ; or, let's get outta here

IsCR
   addq.l    #1,d3               ; increment charcount
   moveq     #1,d6               ; mark CR present
   bra.s     FileScan
IsLF
   cmpi.b    #1,d6               ; was there a CR?
   bne       FixIt               ; no - we add one
   addq      #1,d3               ; yes, up the char count
   bsr       _WrLn               ; pump out whole line
   bra       DoneLoop
FixIt
   subq.l    #2,a2               ; back up PTR
   bsr       _WrLn               ; write out line so far
   move.l    #13,d0
   bsr       _WrChar             ; pop a CR in the file
   move.l    #10,d0
   bsr       _WrChar             ; and add the LF on the end
   adda.l    #2,a2               ; and put PTR back to start of next line
DoneLoop
   cmpa.l    a2,a3               ; at end of file?
   beq       CloseFile
   Zero      d3                  ; zero "chars to write"
   Zero      d6                  ; no CR flag
   move.l    a2,a4               ; update "start of line"
   bra       FileScan

_WrLn
   tst.l     d3                  ; zero or fewer chars?
   ble       NoWr                ; don't write anything!
   move.l    a4,d2               ; ptr to start of line
   move.l    FilePTR,d1          ; ptr to output filehandle
   DosCall   Write               ; pump it out
NoWr
   rts

_WrChar                          ; Enter w char to write in d0
   PushAll                       ; Save regs
   lea       CBuff(pc),a1        ; PTR to buffer in a1
   move.b    d0,(a1)             ; Put character in buffer
   DosPrint  FilePTR,#CBuff,#1   ; and write it
   PullAll                       ; Restore regs
   rts

ExitFile
   subq      #1,d3               ; back up 1 char not in file!
   bsr       _WrLn               ; dump line so far
CloseFile
   move.l    FilePTR,d1          ; shut down the file
   DosCall   Close               ;
   QPrint    StdErr
   dc.b      10,'File written OK',10,0
   EvenPC

**************  Ways Out of program  ********************


QuitandExit
   bsr       _ShutDown           ; clean up everything that Startup doesn't
   bra       WayOut              ; and get out


Error
   bsr       _ShutDown
   move.l    #20,d0              ; Set Error returncode


WayOut
   Zero      d0                  ; no REAL problems :-)
   rts                           ; return to Startup.ASM for lib closes etc.

*******************  Subroutines   ************************


_ShutDown
CloseFileMem
   move.l    FileMemBuf,d0       ; test if mem WAS allocated, to avoid
   tst.l     d0                  ; spectacular crash from freeing memory
   beq.s     Shut                ; we didn't own in the first place!
   move.l    d0,a1               ; OK - move it to a1
   move.l    FileSize,d0         ; along with original size
   SysCall   FreeMem
Shut
   Zero      d0                  ; No problems so...
   rts                           ; back to Startup.asm for Lib closes etc.



_CheckExists                     ; enter with filePTR in d1
   move.l    #Access_Read,d2     ; try it as a READ lock
   DosCall   Lock
   rts                           ; let caller evaluate results


_GetFileSize
   AllocChipMem #fib_SIZEOF      ; allocate memory for FileInfoBlock
   tst.l     d0                  ; (defined in DosEquates.ASM)
   beq       GotFileSize         ; no memory, exit with 0 in d0
   move.l    d0,fib_PTR          ; got mem, store PTR for later
   move.l    d0,d2               ; and set it as 1st parameter with
   move.l    FileLock,d1         ; other parameter for Examine()
   DosCall   Examine
   tst.l     d0                  ; Boolean return
   beq       CloseFibMem         ; can't imagine WHY, but give back mem!
   move.l    fib_PTR,a1          ; set up offset access for what we wanted
   move.l    fib_Size(a1),d0     ; now we have a FileSize as "return code"
CloseFibMem
   PushReg   d0                  ; save the "return code" for later
   move.l    fib_PTR,a1          ; ptr to mem we allocated
   move.l    #fib_SIZEOF,d0      ; and size of the memory block
   SysCall   FreeMem             ; and give it back to the system
   PullReg   d0                  ; and reset return code
GotFileSize
   rts

;           Thanx, Jez San, for neat routine!
;
;           (I just modified to use my macros)
;           (and I call it with QPrint to set)
;           (the current value of QHandle... )
; *
; * fastish print string..like JSR p on the old beebon
; * all registers unaffected.
; *
; * Enter with text immediately following the BSR P subroutine call.
; * This then prints the text out, and returns to the PC immediate after
; * where P was called from.  Note: Some debuggers have trouble single stepping
; * this code.  Their fault, not ours!

_P
   move.l    a3,-(a7)
   move.l    4(a7),a3            ;* posn. of text to be printed
   PushReg   d1-d3/a0/a1         ;* save d1,d2,d3,a0,a1
   move.l    a3,d2
P1
   tst.b     (a3)+               ;* } find length of text
   bne.s     P1                  ;* }

   move.l    a3,d3
   subq.l    #1,d3               ;* dont include NULL
   sub.l     d2,d3               ;* now., d3=length of text
   move.l    QHandle,d1          ;* now, d1=handle, d2=posn of text, d3=length
   DosCall   Write
   PullReg   d1-d3/a0/a1         ;* restore regs..
   move.w    a3,d1
   and.b     #1,d1               ;* see if its a non-word aligned
   beq.s     P3
   addq.l    #1,a3
P3
   move.l    a3,4(a7)            ;* stick next instuction posn back on stack
   move.l    (a7)+,a3

   rts                           ;* finish!

********************** Data Storage areas **************************


KeyBuff      ds.b     80         ; storage for filename (80 chars)
Control      ds.b     20         ; storage for user requests etc (20 chars)
CBuff        ds.b     4          ; storage for 1 char user input
FilePTR:     dc.l     0          ; storage for PTR to File
FileLock:    dc.l     0          ; storage for PTR to FileLock
fib_PTR:     dc.l     0          ; storage for PTR to fib_struct memory
FileMemBuf:  dc.l     0          ; storage for PTR to filebuff memory
FileSize:    dc.l     0          ; storage for FileSize
QHandle      dc.l     0          ; storage for QPrint's current handle
FileNm       dc.l     0          ; storage for PTR to filename
   end                           ; tell assembler that's all

