*-----------------------------------------------------*
*                CType 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    *
*                                                     *
*-----------------------------------------------------*


WBC          EQU      1          ; will need console if from WB

   bra   Start                   ; Jump into Startup.ASM

   INCLUDE  "INCLUDES/Header.ASM"

Quit         EQU      0          ; some EQUates for later readability
Up           EQU      1
Down         EQU      2
Top          EQU      3
Bottom       EQU      4
Again        EQU      5
Assist       EQU      6
PageUp       EQU      7
PageDown     EQU      8
Other        EQU      9

_Main

   move.l    EndFromWB,d0        ; was this started from WB
   beq       CheckParameters     ; no, do the CLI stuff
   move.l    WBMsg,a0            ; yes, set WBMsg up for offset access
   move.l    sm_NumArgs(a0),d3   ; how many args were provided
   cmp.l     #1,d3               ; if one, then no filename given
   beq       NoArgs              ; treat same as BadArgs from CLI
   move.l    sm_ArgList(a0),a2   ; setup arglist for offset access
   move.l    #wa_SIZEOF,d2       ; put size of WBArg in d2, to access 2nd ARG
   move.l    0(a2,d2),d1         ; ptr to directory lock into d1 (2nd ARG)
   DosCall   CurrentDir          ; change to directory of specified file
   move.l    d0,OldDir           ; and save where we came from
   move.l    wa_Name(a2,d2),d1   ; put PTR to filename in d1
   move.l    d1,FileNm           ; and store for opening file after getting lock
   bra       OpenFile            ; and skip to the Openfile routine
NoArgs
   move.l    sm_ArgList(a0),a2   ; get start of ArgList
   move.l    (a2),d1             ; stick it in d1
   DosCall   CurrentDir          ; and set our current dir to location of
   move.l    d0,OldDir           ; CType (and save where we were)
   bra       Usage               ; and get a filename from user (?)

CheckParameters
   move.l    CmdLen,d0           ; Check if user entered filename
   cmpi.b    #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,' CLI Usage: CType filename'
   dc.b      10,' WB  USage: Click CType, Shift/doubleclick text file',10
   dc.b      10,' A FREELY REDISTRIBUTABLE text file reader',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,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,FileChars        ; tells us how many were read
   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...
   move.l    #0,FileLock         ; and clear the storage (for later use!)



********  Various Calculations for later  **************


CalcKBytes
   Zero      d0                  ; clear out the regs I use here
   Zero      d1                  ;
   move.l    FileSize,d0         ; total filesize into d0
   cmpi.l    #9999,d0            ;
   ble       SmallerFile         ; less than 10000 bytes, display as such
   divu      #1024,d0            ; divide by bytes in a KByte
   move.w    d0,d1               ; move only the word value to d1
   swap      d0                  ; flip upper to lower word in d0
   cmpi.w    #512,d0             ; is remainder above 1/2 K?
   blt       1$                  ; if less, skip this next
   addq      #1,d1               ; round up if greater than 1/2K
1$
   lea       KByteTot(pc),a0     ; stuff it into string for end of page
   bsr       _ASCIIConv          ; in ASCII :-)
   bra       CalcForPercent

SmallerFile
   move.l    d0,d1               ; put filesize in d1
   lea       KByteTot(pc),a0     ; stuff it into string for end of page
   bsr       _ASCIIConv          ; in ASCII
   adda.l    #1,a0               ; add 1 to point past end of number
   move.b    #' ',(a0)           ; stuff space over the "K" in KBytes :-)


CalcForPercent
   Zero      d0                  ; clear out REG we need
   Zero      d1                  ; to ensure "clean" result
   move.l    FileSize,d0         ; get filesize/100
   divu      #100,d0             ; to make % calculation fit in WORD
   move.w    d0,d1               ; thus allowing DIVU to work!
   beq       1$                  ; unless is ZERO result! (no GURU 5 please!)
   move.w    d1,HunFileSize      ; store it for calculation done at end of page
   bra       GetThePrefs
1$
   move.w    #1,HunFileSize      ; never less than 1 for divisor!
   move.b    #1,SmallFile        ; and mark as file that needs no further calc!


******* Get data on the WorkBench screen  *********


GetThePrefs
   bsr       _GetPreferences     ; find out current Prefs settings
   tst.l     d0                  ; did it work?
   beq       Error               ; no - get out

FillInParams
   Zero      d1                  ; make sure ONLY our value in d1
   move.b    ColSizeChg,d1       ; change in width (pixels)
   addi      #640,d1             ; add in 640
   lea       Wide(pc),a0         ; and get the ASCII equivalent
   bsr       _ASCIIConv          ; and write it into the string we later
   lea       Wide(pc),a0         ; pass to the OPEN call for a window
   move.b    #'/',(a0)           ; add in the '/' in the right place!
   Zero      d1
   move.b    RowSizeChg,d1       ; same thing for height (pixels)

_AbsExecBase    equ 4
VBlankFrequency equ $212

   movea.l   _AbsExecBase,a0
   cmpi.w    #50,VBlankFrequency(a0)  THIS IS A PATCH
   beq.s     isNTSC                   FOR THE PAL AMIGA
   addi.w    #56,d1
isNTSC addi      #200,d1         ; add the standard height
   move.b    LaceTogl,d0         ; interlace on?
   beq       1$                  ; no, we have the value
   lsl       #1,d1               ; yes. multiply by 2 ( << for C fans :-)
1$
   lea       High(pc),a0         ; and stuff it in the string as well
   bsr       _ASCIIConv          ; with the same "brute force" technique
   lea       High(pc),a0
   move.b    #'/',(a0)           ; with the / separator



*********  Open a window for I/O  **********
*********  (of the size discovered above)


OpenWin
   move.l    #RawName,d1         ; Set up a RAW window for single keystroke eval
   move.l    #MODE_NewFile,d2    ; always as a new file
   DosCall   Open                ; using the string we built above
   tst.l     d0                  ; see if a handle was returned (success)
   beq       Error               ; CAN'T open it - skip rest of it
   move.l    d0,RawHnd           ; got it, store it for output later

CalcCols
   DosPrint  RawHnd,#GetWinStat
   move.l    #1000000,d2         ; wait 1 sec for incoming
   move.l    RawHnd,d1           ; in our window
   DosCall   WaitForChar         ; we don't BUSY LOOP looking, but
   DosRead   RawHnd,#Control,#20 ; we want it all
   cmpi.w    #12,d0
   blt       SizeProb            ; less than 12 chars - something weird!
   Zero      d0
   lea       Control(pc),a0
   adda.l    #5,a0               ; point to first useful character
   move.l    a0,a2               ; "store" ptr
   lea       PromptPos(pc),a1    ; set ptr to string for placing prompt!
WorkLoop
   move.b    (a0),d0             ; get character
   cmpi.b    #';',d0             ; see if it is a separator
   beq       MarkIt              ; first parameter complete
   cmpi.b    #' ',d0             ; space after end of 2nd parameter
   beq       DoneBoth            ; 2nd parameter complete
   move.b    (a0)+,(a1)+         ; pop char into string for posn'g prompt
   bra.s     WorkLoop            ; get next character
MarkIt
   move.l    a0,a3               ; "store" PTR to next parameter (+1 needed!)
   adda.l    #1,a3               ; so we can convert them to values
   move.b    #0,(a0)             ; put a null after 1st parameter
   lea       Control(pc),a1      ; and dummy dest so we can re-use loop :-)
   bra.s     WorkLoop            ; (well - already knew that 1,1 was top corner!)
DoneBoth
   move.b    #0,(a0)             ; put null after 2nd parameter
   move.l    a2,a0               ; ptr to 1st param in a0
   bsr       _ASCII2Val          ; and covert it to value
   sub.w     #2,d1               ; less 1 for Prompt, and 1 for DBRA!
   move.w    d1,NumLines         ; and we have number of lines
   move.l    a3,a0               ; ptr to 2nd param
   bsr       _ASCII2Val          ; convert it to a value
   move.l    d1,ColTotal         ; we have number of useable columns
   bra       FormatLoop          ; (its a LONG for a later compare operation)

SizeProb
   QPrint    StdErr
   dc.b      'Something weird here - maybe TOOOO big a font?'
   dc.b      10,' (I can only handle screen with MORE than 9 lines!)',10,0
   EvenPC
   bra       Error


************  Format file for display  **********
************  we will mess with our copy of the file in memory as much as
************  we want - it only gets saved that way if the user REALLY
************  wants to! (with Print to file).  This way I can eliminate
************  most display problems. like CLS chars, TABS, High-bit-set
************  commands - and also word-wrap.  Takes a second, but saves
************  a LOT of time when displaying the results (the idea WAS
************  SPEED, right?)


FormatLoop
   move.l    FileMemBuf,a2       ; Start of buffer
   move.l    FileChars,a3        ; Number of chars it contains
   adda.l    a2,a3               ; End of buffer now in a3
   move.l    ColTotal,d2         ; and total columns allowed in d2

InitScan
   move.b    (a2)+,d0            ; move byte to d0, and increment a2
   cmpi.b    #' ',d0             ; is byte a space
   beq       IsSpace             ; Yes, check it out
   cmpi.b    #12,d0              ; Is it a Page Break?
   beq       MakeLF              ; get rid of it
   cmpi.b    #9,d0               ; is it a tab?
   beq       MakeSpace           ; turn it into a space
   cmpi.b    #$E,d0              ; is SHIFT OUT char? Write over it so that
   beq       MakeSpace           ; we can read whatever text IS in file
   cmpi.b    #10,d0              ; no, is it a LF?
   beq       LineFeed            ; Yes, go do the necessary
   cmpi.b    #1,BinOK            ; user said binary is OK?
   beq       NotSpecial          ; guess so! skip the rest of these checks
   cmpi.b    #0,d0               ; zero char?
   beq       IsBinary            ; likely a binary file
   cmpi.b    #127,d0             ; is highbit set?
   bgt       IsBinary            ; likely not readable
NotSpecial
   subq.l    #1,d2               ; none of above, decrement columns
   bne       RestOfLoop          ; still columns left, go check for buffer end
   move.l    a2,d0               ; none left, so current addr in d0
   move.l    a4,d1               ; Last space found addr in d1
   sub.l     d1,d0               ; get difference between them
   cmp.l     ColTotal,d0         ; if further than ColTotal, forget wrap!
   bge       MakeLF              ; pretend there's no char there (ulp!)
   move.l    a4,a2               ; closer - set a2 back to LAST space found
   bra       MakeLF              ; and treat as end of line

IsSpace
   subq.l    #1,d2               ; yes, decrement columns
   beq       MakeLF              ; and if none left, go to format line
   move.l    a2,a4               ; otherwise, mark the spot (+1) in a4
   bra       RestOfLoop          ; and check for end of buffer etc.

MakeLF
   move.b    #10,-(a2)           ; LF over it, a2 points to LF for next loop!
   bra       RestOfLoop          ; and check for end of buffer...

MakeSpace
   move.b    #' ',-(a2)          ; change it to a space for now (ugly I know!)
   bra       RestOfLoop          ; and check for end of buffer etc.

LineFeed
   move.l    ColTotal,d2         ; reset counter for columns

RestOfLoop
   cmpa.l    a2,a3               ; compare a2 with End of buffer
   bgt       InitScan            ; if not, get next char
   bra       DisplayFile         ; or, let's SEE what's there!

IsBinary
   QPrint    RawHnd
   dc.b      10,10,'May not be a Text file (contains Binary)...',10
   dc.b      10,$9b,'7m  (O)K or (C)ancel ? ',$9b,'0m',0
   EvenPC
   bsr       _ScanKey
   cmpi.b    #'O',d0
   beq       ItsOK
   cmpi.b    #'o',d0
   beq       ItsOK
   cmpi.b    #'C',d0
   beq       QuitandExit
   cmpi.b    #'c',d0
   beq       QuitandExit
ItsOK
   move.b    #1,BinOK
   bra       NotSpecial



*********  Display the file  ****************
*********  all the formatting is done, so little to do here, except BLAST
*********  it on the screen as quickly as DOS will allow!  Of course, we
*********  DO have to stop at the end of the file, and pause after each
*********  page, and do whatever the user wants in between :-)


DisplayFile
   move.l    RawHnd,CHandle      ; set output handle to window
   move.w    NumLines,d6         ; how many lines per page
   move.b    #10,d5              ; EOL character
   move.l    FileMemBuf,a2       ; set a2 to start of buffer


Pages
   cmpi.b    #1,PrtScFlag        ; is this being printed?
   beq       1$                  ; yes, don't clear screen (form feed!)
   move.l    #12,d0
   bsr       _WrChar             ; Clear the screen
1$
   move.l    a2,LinePtr          ; set lineptr to Current position
   move.l    #0,CharCount        ; set chars to display at zero

ScanLoop
   move.b    (a2)+,d3            ; get next character
   cmp.b     d3,d5               ; is it a LF (EOL) ?
   beq       OutputLine          ; if so, pump line out
   addq.l    #1,CharCount        ; No? up count of chars this line
   cmpa.l    a2,a3               ; compare current posn (a2) w/ buffer end (a3)
   ble       GetOut              ; and leave if EOF, or
   bra       ScanLoop            ; back to get next character

OutputLine
   addq.l    #1,CharCount        ; so LF gets sent with this line
   DosPrint  CHandle,LinePtr,CharCount
   move.l    a2,LinePtr          ; now, update start of line PTR
   move.l    #0,CharCount        ; clear charcount
   cmpa.l    a2,a3               ; check for EndOfFile
   ble       IsEOF               ; get out if at or past EOF
   dbra      d6,ScanLoop         ; or loop till NumLines on the screen
   move.b    #0,EndFlag          ; not EOF, so clear flag
   cmpi.b    #1,PrtScFlag        ; is printing screen to file?
   bne       ReadingTime         ; no, keep going
   bsr       DonePrtSc           ; or go clean up
   bra       ReEntry             ; and simulate having got "again" keystroke

ReadingTime
   cmp.b     #1,SmallFile        ; was this a small file?
   beq       ForceIt             ; yes, skip the calcs!
   move.l    a2,d1               ; put current "position" in d1 for calcs
   sub.l     FileMemBuf,d1       ; subtract start of buffer from d1
   divu      HunFileSize,d1      ; divide by 1/100 of filesize for %
   swap      d1                  ; flip top and bottom of register
   clr.w     d1                  ; to clear "remainder" - we don't care
   swap      d1                  ; flip it back and
   cmp.w     #100,d1             ; and check if over 100 (can only happen if
   ble       Prompt              ; file is under 1000 bytes)
ForceIt
   move.l    #100,d1             ; if it is, make it 100
Prompt
   lea       CurPos(pc),a0       ; force feed it to string PosPrompt
   bsr       _ASCIIConv
   DosPrint  RawHnd,#PosPrompt   ; print out the resulting prompt
   bsr       _KeyHit             ; wait for a keystroke (sub returns action codes)
   tst.l     d0                  ; see if user wants out
   beq       QuitandExit         ; and exit if so
ReEntry                          ; entry point if from PrtScreen
   cmpi.b    #Up,d0              ; now we check all supported keystrokes
   bne       1$                  ;
   move.b    #0,EndFlag          ; clear the EOF flag - 0=not at end
   bsr       _BackLine
   bra       ReadingTime         ; everything done, get next command
1$
   cmpi.b    #Down,d0
   bne       2$
   cmp.b     #1,EndFlag          ; check EOF flag
   beq       QuitandExit         ; if EOF, then DOWN=EXIT
   bra       _ForLine            ; not EOF, then go ahead a line
2$
   cmpi.b    #Top,d0
   bne       3$
   move.b    #0,EndFlag          ; we're at TOF - so clear EOF flag
   bsr       _TOF
   bra       Another
3$
   cmpi.b    #Bottom,d0
   bne       4$
   cmp.b     #1,EndFlag          ; check if already at EOF
   beq       QuitandExit         ; if we are, then =EXIT
   bsr       _BOF
   move.b    #1,EndFlag          ; otherwise set EOF flag - we're there now!
   bra       Another
4$
   cmpi.b    #Again,d0
   bne       5$
   bsr       _RePage             ; no need to check or set EOF
   bra       Another             ; we've gone nowhere
5$
   cmpi.b    #Assist,d0          ; again, no need to check
   bne       6$                  ; displaying help, and refreshing display
   bsr       _Help               ; automatically on exit
   bra       Another
6$
   cmpi.b    #PageUp,d0
   bne       7$
   bsr       _BackPage           ; once again, we've backed up
   move.b    #0,EndFlag          ; so we clear the EOF flag
   bra       Another
7$
   cmpi.b    #PageDown,d0
   bne       Another
   cmp.b     #1,EndFlag          ; better check if EOF, if so
   beq       QuitandExit         ; then EXIT

Another
   move.w    NumLines,d6         ; all done, so reset loop counter
   bra       Pages               ; and show appropriate page


GetOut
   DosPrint  CHandle,LinePtr,CharCount
   Zero      d0                  ; dump last line to user
   move.b    #10,d0              ; and add the missing LF
   bsr       _WrChar
IsEOF
   move.b    #1,EndFlag          ; flag for EOF
   cmpi.b    #1,PrtScFlag        ; were we "printing"?
   beq       1$                  ; sort that out instead!
   bra       ReadingTime         ; or check for next keyhit
1$
   bsr       DonePrtSc           ; go clean up flags etc
   bra       ReEntry             ; and simulate returning w/ "again" keystroke


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


QuitandExit
   move.l    EndFromWB,d1        ; see if we started from WB
   beq.s     GoneNow             ; no, normal shutdown
   move.l    OldDir,d1           ; yes, return our CurrentDir as was
   DosCall   CurrentDir          ; before we go and then
GoneNow
   bsr       _ShutDown           ; clean up everyting that Startup doesn't
   bra.s     WayOut              ; and get out


Error
   bsr       _ShutDown
   QPrint    StdOut
   dc.b      10,10,'Press RETURN to Exit...',10,0
   EvenPC
   DosRead   StdIn,#Control,#1
   move.l    #20,d0              ; Set Error returncode


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



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


_ShutDown

CloseRaw
   move.l    RawHnd,d1           ; load Window handle into d1
   tst.l     d1                  ; if its NULL, we didn't get it open
   beq.s     CloseFileMem        ; so don't TRY to close it!
   DosCall   Close
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



_GetPreferences
   AllocChipMem #pf_SIZEOF       ; allocate memory for Preferences STRUCT
   tst.l     d0                  ; (defined in IntEquates.ASM)
   beq       GotPrefs            ; we didn't get it, d0 has "fail" return code
   move.l    d0,pf_PTR           ; and store for later
   move.l    d0,a0               ; and set it as 1st parameter with
   move.l    #pf_SIZEOF,d0       ; number of bytes we want from it
   IntCall   GetPrefs
   tst.l     d0                  ; Should return our PTR to buffer..
   beq       ClosePFMem          ; can't imagine WHY this would happen, but...
   move.l    pf_PTR,a1           ; set up offset access for what we wanted!
   move.b    pf_RowSizeChange(a1),RowSizeChg
   move.b    pf_ColumnSizeChange(a1),ColSizeChg
   move.b    pf_LaceWB(a1),LaceTogl
   moveq     #1,d0               ; we got what we wanted, so return "success"
ClosePFMem
   PushReg   d0                  ; store return code for now
   move.l    pf_PTR,a1           ; pointer to mem we got
   move.l    #pf_SIZEOF,d0       ; sizeof memory we got
   SysCall   FreeMem             ; give it back (we ARE well behaved!)
   PullReg   d0                  ; keep return code!
GotPrefs
   rts                           ; return with "Boolean" result




**************** Get user requests  *********************


_KeyHit
   move.l    #1000000,d2         ; wait 1 sec for reader to hit a key
   move.l    RawHnd,d1           ; in our window
   DosCall   WaitForChar         ; we don't BUSY LOOP looking, but
   tst.l     d0
   beq       _KeyHit             ; we are determined to get one!
   DosRead   RawHnd,#Control,#8  ; check it out for user's requests
   move.b    Control,d0
   cmpi.b    #$9b,d0             ; is it CSI char?
   beq       ExtendKey           ; if so, check it out

   cmpi.b    #' ',d0             ; <SPACE> char
   beq       ForPage
   cmpi.b    #'3',d0             ; <PG DN> char on Numeric pad
   beq       ForPage

   cmpi.b    #8,d0               ; <BACKSPACE> char
   beq       BackPage
   cmpi.b    #'9',d0             ; <PG UP> char on Numeric pad
   beq       BackPage

   cmpi.b    #'h',d0
   beq       Help
   cmpi.b    #'H',d0
   beq       Help
   cmpi.b    #'?',d0             ; just a ? :-)
   beq       Help

   cmpi.b    #'q',d0
   beq       WantsOut
   cmpi.b    #'Q',d0
   beq       WantsOut
   cmpi.b    #27,d0              ; <ESC> char
   beq       WantsOut
   cmpi.b    #3,d0               ; <CTRL-C> char
   beq       WantsOut

   cmpi.b    #'r',d0
   beq       RePage
   cmpi.b    #'R',d0
   beq       RePage
   cmpi.b    #'5',d0             ; the Centre key on Numeric pad
   beq       RePage
   cmpi.b    #12,d0              ; <CTRL-L> char
   beq       RePage

   cmpi.b    #13,d0              ; <RETURN> char
   beq       ForLine
   cmpi.b    #'2',d0             ; <DOWN ARROW> char on Numeric Pad
   beq       ForLine

   cmpi.b    #127,d0             ; <DELETE> char
   beq       BackLine
   cmpi.b    #'8',d0             ; <UP ARROW> char on Numeric pad
   beq       BackLine

   cmpi.b    #'t',d0
   beq       TOF
   cmpi.b    #'T',d0
   beq       TOF
   cmpi.b    #'<',d0
   beq       TOF
   cmpi.b    #'7',d0             ; <HOME> char on Numeric pad
   beq       TOF

   cmpi.b    #'b',d0
   beq       BOF
   cmpi.b    #'B',d0
   beq       BOF
   cmpi.b    #'>',d0
   beq       BOF
   cmpi.b    #'1',d0             ; <END> char on Numeric pad
   beq       BOF


   cmpi.b    #'e',d0
   beq       EDIT
   cmpi.b    #'E',d0
   beq       EDIT

   cmpi.b    #'/',d0             ; Case Sensitive search
   beq       SRCH
   cmpi.b    #'.',d0             ; Case INsensitive search
   beq       SRCHI

   cmpi.b    #'n',d0             ; repeat last search
   beq       ReSearch
   cmpi.b    #'N',d0
   beq       ReSearch

   cmpi.b    #'p',d0
   beq       PRT
   cmpi.b    #'P',d0             ; Print to ...
   beq       PRT

   cmpi.b    #'*',d0
   beq       PRTSc               ; PrintScreen

   cmpi.b    #'%',d0             ; Goto % in file
   beq       GOTO

   bra       _KeyHit             ; anything else we'll ignore!

ExtendKey
   move.b    Control+1,d0        ; get next character
   cmpi.b    #'?',d0             ; HELP Key?
   beq       Help
   cmpi.b    #'0',d0             ; F1 Key?
   beq       Help
   cmpi.b    #'6',d0             ; F7 Key?
   beq       PRTSc
   cmpi.b    #'1',d0             ; Shifted F7?
   beq       ArrowChk            ; go check if next char is 6
   cmpi.b    #'9',d0             ; F10 Key?
   beq       WantsOut
   cmpi.b    #'A',d0             ; UP ARROW?
   beq       BackLine
   cmpi.b    #'T',d0             ; UP ARROW (shifted) ?
   beq       BackPage
   cmpi.b    #'B',d0             ; DOWN ARROW?
   beq       ForLine
   cmpi.b    #'S',d0             ; DOWN ARROW (shifted) ?
   beq       ForPage
   cmpi.b    #'C',d0             ; RIGHT ARROW?
   beq       BOF
   cmpi.b    #'D',d0             ; LEFT ARROW?
   beq       TOF
   cmpi.b    #' ',d0             ; LEFT or RIGHT ARROW (shifted) ?
   beq       ArrowChk
   bra       _KeyHit             ; don't WANT to know what else user hit!
ArrowChk
   move.b    Control+2,d0
   cmpi.b    #'A',d0             ; RIGHT ARROW? (shifted of course)
   beq       BOF
   cmpi.b    #'@',d0             ; LEFT ARROW? (shifted)
   beq       TOF
   cmpi.b    #'6',d0             ; must have been shifted F7
   beq       PRT
   bra       _KeyHit             ; Ignoring all other keystrokes we got
                                 ; because an impatient user could have
                                 ; loaded us up with more requests than
                                 ; was intended!  Next call will write over
                                 ; whatever was in there...

Help
   moveq     #Assist,d0          ; pass "action code" in d0 to calling routine
   rts
RePage
   moveq     #Again,d0           ; constants EQU'd at start of program
   rts
ForPage
   moveq     #PageDown,d0
   rts
BackPage
   moveq     #PageUp,d0
   rts
TOF
   moveq     #Top,d0
   rts
BOF
   moveq     #Bottom,d0
   rts
WantsOut
   moveq     #Quit,d0
   rts
ForLine
   moveq     #Down,d0
   rts
BackLine
   moveq     #Up,d0
   rts


*****************  Act on User Requests!  *********************



_Help
   bsr       _PrintHelp          ; pretty obvious what this does!
   bsr       _RePage             ; have to redisplay the screen as we left it
   rts

_PrintHelp
   DosPrint  RawHnd,#HelpMesg    ; display it
WaitKey
   move.l    #1000000,d2         ; wait 1 sec for reader to hit a key
   move.l    RawHnd,d1           ; in our window
   DosCall   WaitForChar         ; we don't BUSY LOOP looking, but
   beq       WaitKey             ; we are determined to get one!
   DosRead   RawHnd,#Control,#40 ; clear it out so no leftovers
   rts

_RePage
   bsr       _BackOnePage        ; actually backs up STARTING POINT of page
   rts                           ; we are going to display

_BackOnePage
   move.w    NumLines,d6         ; Numlines as loop counter
   addq.w    #1,d6               ; we start on EOL, so add one to count
BackScan
   cmpi.b    #10,-(a2)           ; step backwards, looking for EOL
   bne       BackScan            ; not found, keep looking
   dbra      d6,BackScan         ; found, loop till numlines=0
   cmpa.l    FileMemBuf,a2       ; test if past start of buffer!
   ble       FixIt               ; set to first page if so
   cmpi.b    #10,(a2)+           ; move back 1 char past last EOL
   rts
FixIt
   movea.l   FileMemBuf,a2       ; set values back as at beginning of file
   rts

_BackPage
   bsr       _BackOnePage        ; back up a2 by Numlines
   bsr       _BackOnePage        ; twice, which will show previous page
   rts

_TOF
   move.l    FileMemBuf,a2       ; back up a2 to start of whole thing
   rts

_BOF
   movea.l   a3,a2               ; set a2 to end of buffer
   adda.l    #1,a2               ; set a2 past EOF by 1
   bsr       _BackOnePage        ; then back up NumLines to display
   rts                           ; final page

_BackLine
   moveq     #1,d6               ; set counter to one, and borrow the
   bsr       BackScan            ; BackScan loop to set page start back 1 line
   PushReg   a2                  ; store current a2 for coming back!
   bsr       _BackOnePage        ; then back up a full page
   cmpa.l    FileMemBuf,a2       ; are we at TOF?
   beq       SkipOutPut          ; yes - forget whole thing :-)
   QPrint    RawHnd
   dc.b      $9b,$54,$9b,'H',0   ; scroll down, and HOME cursor
   EvenPC                        ; to smooth out display
   move.l    #0,CharCount        ; zero the count of chars to display
   move.l    a2,LinePtr          ; set LinePtr to current posn
   bsr       _ScanLine           ; and get the rest of the line
DumpLine
   addq.l    #1,CharCount        ; so LF gets sent with this line
   DosPrint  CHandle,LinePtr,CharCount
   PullReg   a2                  ; return "posn PTR" to bottom of display
   rts
SkipOutPut
   PullReg   a2                  ; we are at TOF, so we have to return the
   bsr       _ScanLine           ; ptr in a2 to where we were BEFORE
   rts

_ScanLine
   move.b    (a2)+,d3            ; get next char
   cmp.b     d3,d5               ; is it a LF (EOL) ?
   beq       DoneLine            ; if so, dump line out
   addq.l    #1,CharCount        ; No? up count of chars this line
   bra       _ScanLine           ; back to get next one
DoneLine
   rts


_ForLine
   bsr       _ClrLine
   Zero      d6                  ; zero Numlines counter
   move.l    a2,LinePtr          ; start lineptr at beginning of buffer
   move.l    #0,CharCount        ; start chars to display at 1
   bra       ScanLoop            ; and use scan from display loop
                                 ; (I learned to program on a C64, and
                                 ; re-using existing routines is a
                                 ; habit by now!)
_PrevLine
   moveq     #0,d6               ; set counter to zero (once thru loop)
   bsr       BackScan            ; and borrow BackScan loop to set the page
   rts                           ; start and back to display it


******************** Call the Editor  ************************


EDIT
   bsr       _ClrLine            ; clear status line
   QPrint    RawHnd
   dc.b      '   ',$9b,'7m  Calling your Editor!  ',$9b,'0m',0
   EvenPC
   lea       EditName(pc),a0     ; get PTR to filename
   move.l    a0,d1               ; set it up for _CheckExists
   bsr       _CheckExists        ; to see if user HAS an editor preference!
   tst.l     d0
   bne       GetEditor           ; OK - it exists
   bsr       _ClrLine
   QPrint    RawHnd              ; error msg
   dc.b      '   ',$9b,'7m - No entry in ENV:Editor - ',$9b,'0m',0
   EvenPC
   bra       EdTrouble

GetEditor
   move.l    d0,FileLock         ; Lock in same place (not needed again)
   bsr       _GetFileSize        ; checking up on size of entry (fits our buff?)
   tst.l     d0                  ; got it?
   bne       CheckEdEntry        ; must have :-)
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      '   ',$9b,'7m - Could not determine size of EDITOR entry - ',$9b,'0m',0
   EvenPC
   bra       EdTrouble

CheckEdEntry
   move.l    d0,EdNum
   cmp.l     #80,d0              ; entry will fit in our buffer?
   ble       GetEdName           ; less or EQ is ok
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      '   ',$9b,'7m - EDITOR entry to big for me to handle! - ',$9b,'0m',0
   EvenPC
   bra       EdTrouble

GetEdName
   lea       EditName(pc),a0
   move.l    a0,d1
   move.l    #MODE_ReadOnly,d2   ; open up ENV:Editor and see what's there
   DosCall   Open
   tst.l     d0
   bne       ReadEdName          ;
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      '   ',$9b,'7m - Could not open ENV:Editor - ',$9b,'0m',0
   EvenPC
   bra       EdTrouble

ReadEdName
   move.l    d0,EdPTR            ; store for closedown later
   DosRead   EdPTR,#KeyBuff,EdNum
   tst.l     d0
   bne       CallEditor
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      '   ',$9b,'7m - Could not read ENV:Editor - ',$9b,'0m',0
   EvenPC
   bra       EdTrouble

CallEditor
   lea       KeyBuff(pc),a0      ; PTR to buff location, for calculation
   clr.b     0(a0,d0)            ; of end of input, put 0 byte there (over CR?)
   lea       KeyBuff(pc),a0
   move.l    a0,d1               ; put PTR to name in d1
   Zero      d2                  ; no input specified
   move.l    StdOut,d3           ; StdOut for output
   DosCall   Execute
   tst.l     d0
   bne       EndEdit
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      '   ',$9b,'7m - I tried - maybe C:Run not available? - ',$9b,'0m',0
   EvenPC
   bra       EdTrouble

EndEdit
   move.l    EdPTR,d1            ; IF is PTR, THEN
   beq       DoneEdit
   DosCall   Close               ; close file
   move.l    #0,EdPTR            ; and clear storage!
   move.l    FileLock,d1
   beq       DoneEdit            ; IF is lock, THEN
   DosCall   UnLock              ; unlock it
   move.l    #0,FileLock         ; and clear storage

DoneEdit
   moveq     #Again,d0           ; Redisplay from where we were
   rts

EdTrouble
   move.l    #50,d1              ; wait a sec for user to read it
   DosCall   Delay
   bra       EndEdit             ; and exit thru cleanup...


****************** Printing options *********************************



PRTSc
   move.b    #1,PrtScFlag        ; set flag for PrtScreen

PRT
   PushReg   d2-d7
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      '   ',$9b,'7m File?  ( RETURN = PRT:   ESC + RETURN = CANCEL ) '
   dc.b      $9b,'0m','  ',$9b,$20,$70,0
   EvenPC
   bsr       _GetInput
   cmpi.b    #1,d0
   beq       DumpPRT             ; just hit RETURN - default to PRT:
   cmpi.b    #5,d0               ; is 4 chars - SER: PAR: PRT: ??
   bne       1$
   bsr       ChkDev              ; check it out...
   tst.l     d0                  ; if zero'd was no match with device name
   bne       OverWrite           ; was match w/ dev name, same as overwrite mode
1$
   lea       KeyBuff(pc),a0      ; diff num of chars, or no match, so
   move.b    (a0),d0             ; get first character
   cmpi.b    #27,d0              ; if its an ESC
   beq       CancelPRT           ; then cancel the job!
   move.l    a0,d1               ; PTR to name in d1
   bsr       _CheckExists        ; try for Lock on file
   tst.l     d0
   beq       OverWrite           ; Is new file, no problem
   move.l    d0,d1               ; old file, we'll unlock it now
   DosCall   UnLock              ; then check on user's wishes...

FExists
   bsr       _ClrLine            ; clear stat line
   QPrint    RawHnd
   dc.b      ' ',$9b,'7m File exists - (A)ppend  (O)verwrite or (C)ancel? ',$9b,'0m'
   dc.b      '  ',$9b,$20,$70,0
   EvenPC
   bsr       _ScanKey            ; get key from user
   cmpi.b    #'A',d0
   beq       Append
   cmpi.b    #'a',d0
   beq       Append
   cmpi.b    #'O',d0
   beq       OverWrite
   cmpi.b    #'o',d0
   beq       OverWrite
   cmpi.b    #'C',d0
   beq       CancelPRT
   cmpi.b    #'c',d0
   beq       CancelPRT
   bra       FExists             ; insist on a response!

Append
   lea       KeyBuff(pc),a0
   move.l    a0,d1
   move.l    #MODE_ReadWrite,d2  ; to allow append mode
   DosCall   Open
   tst.l     d0                  ; see if a handle was returned (success)
   beq       PRTError            ; No? Skip the rest
   move.l    d0,PRTFile          ; or store handle if successful
   move.l    d0,d1               ; and put in d1 with
   Zero      d2                  ; no offset in d2
   moveq     #1,d3               ; and OFFSET_END in d3 for a call to
   DosCall   Seek                ; Seek to end of file (where we add on!)
   bra       PrintIt             ; ready to print...

OverWrite
   lea       KeyBuff(pc),a0      ; get PTR to user input
   move.l    a0,d1               ; into d1 as PTR to name
   move.l    #MODE_NewFile,d2    ; overwrite mode
   DosCall   Open                ; and open it up
   tst.l     d0                  ; check for returned handle
   beq       PRTError            ; no - get out
   move.l    d0,PRTFile          ; store it for close down
   bra       PrintIt             ; ready to print

DumpPRT
   lea       PRTName(pc),a0      ; we know the name, so
   move.l    a0,d1
   move.l    #MODE_NewFile,d2    ; as a newfile
   DosCall   Open                ; we open it up
   tst.l     d0
   beq       PRTError            ; it didn't?  :-)
   move.l    d0,PRTFile          ; it did, so store PTR for closedown

PrintIt
   cmpi.b    #1,PrtScFlag        ; was it a PrtSc only?
   beq       PrtScDoIt           ; handle it differently
   DosPrint  PRTFile,FileMemBuf,FileSize
   cmpi.l    #-1,d0              ; oops! not all chars written..
   beq       PRTError

PRTCleanUp
   move.l    PRTFile,d1          ; IF is PTR, THEN
   beq.s     DonePRT
   DosCall   Close               ; close file
   move.l    #0,PRTFile          ; and clear storage!
DonePRT
   moveq     #Again,d0           ; Redisplay from where we were
   PullReg   d2-d7
   rts

CancelPRT
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      $9b,$30,$20,$70,'   ',$9b,'7m - Operation CANCELLED - ',$9b,'0m',0
   EvenPC
   move.l    #50,d1
   DosCall   Delay
   cmpi.b    #1,PrtScFlag        ; if was PrtScreen operation
   bne       1$
   move.b    #0,PrtScFlag        ; cancel THAT too! :-)
1$
   bra       PRTCleanUp

PRTError
   bsr       _ClrLine
   QPrint    RawHnd
   dc.b      $9b,$30,$20,$70,'   ',$9b,'7m - ERROR occurred! - ',$9b,'0m',0
   EvenPC
   move.l    #50,d1
   DosCall   Delay
   bra       CancelPRT

PrtScDoIt
   move.l    PRTFile,CHandle
   moveq     #Again,d0
   PullReg   d2-d7
   rts

DonePrtSc
   move.l    RawHnd,CHandle
   PushReg   d2-d7               ; strictly because next return pulls them!
   move.b    #0,PrtScFlag
   bra       PRTCleanUp


ChkDev
   lea       KeyBuff(pc),a0      ; load PTR to user input
   lea       PRTName(pc),a1      ; and possible value
   bsr       _CompChar           ; and compare
   tst.l     d0                  ; if match, d0 = last char
   bne       MatchFound          ; if zero, then keep checking
   lea       KeyBuff(pc),a0
   lea       PARName(pc),a1      ; next poss to check
   bsr       _CompChar
   tst.l     d0
   bne       MatchFound          ; keep checking if zero
   lea       KeyBuff(pc),a0
   lea       SERName(pc),a1
   bsr       _CompChar
MatchFound
   rts                           ; either way - d0 = success in matching :-)


_CompChar
   move.l    #3,d4               ; countdown of chars for DBRA
   Zero      d0                  ; clear out d0
CompLoop
   move.b    (a0)+,d0            ; move char into d0
   bsr       _ConvChar           ; and get char converted (if needed)
   move.b    (a1)+,d5            ; compare w/char at current posn in name
   cmp.b     d5,d0               ; does it match char in d0?
   beq       CompMore            ; if match, continue check
   cmp.b     d5,d1               ; does it match char in d1?
   beq       CompMore            ; if match continue check
   bra       CompNot             ; otherwise get out
CompMore
   dbra      d4,CompLoop         ; was match: chars left?
   rts
CompNot
   Zero      d0
   rts


********************   Search Operations  ************************
********************
********************  we give up some speed for space here (isn't that
********************  ALWAYS the way it is!) - and use the same search
********************  whether or not we are case sensitive.  We do
********************  2 compares for every character, but what the heck
********************  a 680x0 is pretty quick, right?


SRCH
   PushReg   d5                  ; save it for later!
   bsr       _ClrLine
   Zero      d0
   move.b    #'/',d0             ; echo user command
   bsr       _WrChar
   move.b    #0,SrchType         ; we are case sensitive!
   bra       Search

SRCHI
   PushReg   d5                  ; save it for later
   bsr       _ClrLine
   Zero      d0
   move.b    #'.',d0
   bsr       _WrChar
   move.b    #1,SrchType         ; we are NOT case sensitive!

Search
   bsr       _GetInput
   tst.l     d0
   beq       NoMatch
   move.l    d0,d3               ; store length of string in d3
   subq.l    #1,d3               ; less one!
   move.l    d3,d4               ; and in d4 for testing
   move.l    a2,CurPosn          ; in case we need to know!
   bsr       _BackOnePage        ; to start of displayable page
   bra.s     StartSrch           ; and start search
ReSearch
   PushReg   d5                  ; save it for later
   move.l    SrchOK,d3           ; check if previous valid search
   beq       NoMatch             ; no? skip outta here!
   move.l    d3,d4               ; Yes, copy string length(-1) to d4
   move.l    a2,CurPosn          ; in case we need to know!
   move.l    a5,a2               ; "stored" from last search
StartSrch
   bsr       _ClrLine            ; clear status line
   QPrint    RawHnd
   dc.b      '    ',$9b,'7m  Searching for  -- ',0
   EvenPC
   DosPrint  RawHnd,#KeyBuff     ; with user's string
   QPrint    RawHnd
   dc.b      ' --  ',$9b,'0m',0
   EvenPC
FirstChar
   Zero      d0                  ; clear out d0
   lea       KeyBuff(pc),a0      ; PTR to string in a0
   move.b    (a0)+,d0            ; move first char into d0
   bsr       _ConvChar           ; and get char converted (if needed)
SrchLoop
   move.b    (a2)+,d5            ; compare w/char at current posn in file
   cmp.b     d5,d0               ; does it match char in d0?
   beq       Match1              ; if match, continue check
   cmp.b     d5,d1               ; does it match char in d1?
   beq       Match1              ; if match continue check
   cmpa.l    a2,a3               ; see if past EOF
   ble       NoMatch             ; if we are, then no match, natch
   bra       SrchLoop            ; no match yet, so keep searching

Match1
   move.l    a2,d7               ; store new position in file
MatchLoop
   subq.l    #1,d4               ; lower string count by 1
   beq       Matched             ; if none left, match is good
   move.b    (a0)+,d0            ; get next char of string
   bsr       _ConvChar           ; and set it up for checking
   cmpa.l    a2,a3               ; check against EOF count
   ble       NoMatch             ; at EOF - stop already!
   move.b    (a2)+,d5            ; compare w/char at current posn in file
   cmp.b     d5,d0               ; does it match char in d0?
   beq       MatchLoop           ; if match, continue check
   cmp.b     d5,d1               ; does it match char in d1?
   beq       MatchLoop           ; if match continue check
   move.l    d3,d4               ; otherwise reset string length check
   move.l    d7,a2               ; set a2 back to last unchecked position
   bra       FirstChar           ; and start search for first char again
Matched
   bsr       _PrevLine           ; back up to previous EOL
   move.l    d7,a5               ; "store" location to display from
   adda.l    #1,a5               ; +1, to "restart" search from
   move.l    a5,CurPosn          ; for reasonable value if "re-search" fails
   moveq     #PageDown,d0        ; tell display routine to go from here
   move.l    d3,SrchOK           ; Set flag (w num of chars in string
   PullReg   d5                  ; and reset d5 as before
   rts

NoMatch
   move.l    CurPosn,a2          ; and current posn in file!
   move.b    #0,SrchOK           ; Set flag that search DIDN'T work
   bsr       _ClrLine            ; so "N" command knows not to continue
   QPrint    RawHnd
   dc.b      '    ',$9b,'7m  -- Not Found --  ',$9b,'0m',0
   EvenPC
   move.l    #50,d1              ; and 50 ticks (1 sec)
   DosCall   Delay               ; of delay so it gets seen!
   PullReg   d5                  ; return d5 to previous contents
   moveq     #Again,d0           ; redisplay from where we were
   rts


_ConvChar
   move.l    d0,d1               ; copy it into d1
   cmpi.b    #0,SrchType         ; is case sensitive search?
   beq       NotAlpha            ; do nothing else :-)
   cmpi.b    #'A',d0             ; is char upper case?
   blt.s     NotAlpha            ; lower, not alphabetic
   cmpi.b    #'Z',d0             ;
   ble.s     UpperCase           ; lower or eq, is UpperCase Alpha
   cmpi.b    #'a',d0             ;
   blt.s     NotAlpha            ; lower, not alphabetic
   cmpi.b    #'z',d0             ;
   ble.s     LowerCase           ; lower or eq, is LowerCase Alpha
   bra.s     NotAlpha            ; higher, not alphabetic
UpperCase
   add.l     #32,d1              ; make d1 a lower case copy
   bra.s     NotAlpha            ; and get on with it
LowerCase
   sub.l     #32,d1              ; make d1 an upper case copy
NotAlpha
   rts


*******************  GOTO Percent of File  ***************************


GOTO
   bsr       _ClrLine            ; clear prompt line, and position input
   Zero      d0                  ;
   move.b    #'%',d0             ; print user keystroke as prompt
   bsr       _WrChar
   bsr       _GetInput           ; get user input,
   tst.l     d0                  ; more than zero chars?
   beq       GotoExit            ; NO? do nothing
   lea       KeyBuff(pc),a0      ; put PTR to string in a0
   bsr       _ASCII2Val          ; and convert it to value
   tst.b     d1                  ; and got what back?
   beq       GotoExit            ; zero? get outta here
   addi      #1,d1               ; kludge for rounding errors!
   mulu      HunFileSize,d1      ; multiply by 1/100 of the file's size
   move.l    FileMemBuf,d0       ; start of file in d0
   add.l     d1,d0               ; add it to result of calc
   move.l    d0,a2               ; now we have PTR to display from
   bsr       _PrevLine           ; back up to previous EOL
GotoExit
   moveq     #Again,d0           ; and tell main loop to show from there
   rts



********************  Useful General Subroutines  ********************

_ClrLine
   DosPrint  RawHnd,#ClrLn
   rts

_GetInput                        ; Gets a line of text from the user
   DosPrint  RawHnd,#CursorOn    ; turn on cursor
   PushReg   a5                  ; save a5 for later
   lea       KeyBuff(pc),a5
   clr.l     (a5)                ; Zero the first bit
GetIn1
   bsr.s     _ScanKey            ; Get keyboard Input
   cmp.b     #8,d0               ; is it a backspace?
   beq.s     BackSp
   cmp.b     #127,d0             ; or a delete (treat 'em the same)
   beq.s     BackSp
   bsr       _WrChar             ; Display it onscreen
   cmp.b     #13,d0              ; Return?
   beq.s     ChRet
   move.b    d0,(a5)+            ; Put character into buffer
   bra.s     GetIn1              ; and get next char
BackSp
   cmp.l     #KeyBuff,a5         ; Dont allow backspacing before start!
   beq       GetIn1
   move.b    #8,d0               ; Write a Backspace char
   bsr       _WrChar
   move.b    #32,d0              ; Space over char to disappear
   bsr       _WrChar
   move.b    #8,d0               ; Backspace again for positioning
   bsr       _WrChar
   clr.b     (a5)                ; Zero the current character in buffer
   subq.l    #1,a5               ; Backtrack buffer PTR by one character
   bra       GetIn1
ChRet                            ; RETURN was pressed
   clr.b     (a5)+               ; set a NULL to terminate string
   sub.l     #KeyBuff,a5         ; get num of characters
   move.l    a5,d0               ; and return it in d0
   PullReg   a5                  ; put a5 back as it was
   rts

_ScanKey
   move.l    RawHnd,d1           ; Input window handle
   move.l    #500,d2             ; Time to wait
   DosCall   WaitForChar         ; Anything waiting for us?
   tst.l     d0                  ; False=0
   beq.s     _ScanKey            ; Nothing there - try again
   PushReg   d1-d7/a0-a6         ; got one, save most regs
   DosRead   RawHnd,#CBuff,#1    ; get the char
   Zero      d0                  ; ensure nothing else in d0
   move.b    CBuff,d0            ; Char returned in d0
   PullReg   d1-d7/a0-a6         ; Restore regs
   rts

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


_ASCIIConv                       ; Enter with value for conversion in d1
                                 ; and buffer to store result in a0
   Zero      d0                  ; this routine only handles 4 decimal chars
   bsr       Do_It               ; because I want it to :-)  (for punching
   rts                           ; values into strings like RawName)
Do_It
   divu      #1000,d1            ; get 1000's digit
   bsr       Eval                ; evaluate and move remainder
   divu      #100,d1             ; get 100's digit
   bsr       Eval                ;
   divu      #10,d1              ; get 10's digit
   bsr       Eval                ;
   addq.l    #1,d0               ; if only character, we display the 0
Eval
   add       #48,d1              ; convert to ASCII value
   cmpi.b    #'0',d1             ; is it a leading ASCII Zero char now?
   bne       NotLdZero
   tst.l     d0                  ; test d0 for a previous no-zero char
   bne       NotLdZero           ; if was one, skip the change to space
   move.b    #' ',(a0)+          ; there wasn't - so store space instead
   bra       SetForNext          ; and get ready for next digit
NotLdZero
   addq.l    #1,d0               ; set flag that nonleadZero char preceded this
   move.b    d1,(a0)+            ; store digit
SetForNext
   clr.w     d1                  ; erase lower word
   swap      d1                  ; move remainder into lower word
   rts                           ; return for more (or to caller if done)



_ASCII2Val                       ; Enter with ASCII string PTR in a0
                                 ; returns with value in d1
   Zero      d1                  ; clear it out
   bsr.s     DecLoop
   rts
DecLoop
   bsr.s     GetDigit            ; get converted digit
   blt.s     DecDone             ; less than ASCII 0, not digit (done?)
   cmpi.b    #9,d0               ; test if greater than 9
   bgt.s     DecDone             ; yes? get out
   mulu.w    #10,d1              ; step up previous result by 10
   add       d0,d1               ; and add in the new digit
   bra.s     DecLoop             ; and back for more
DecDone
   rts
GetDigit
   Zero      d0
   move.b    (a0)+,d0            ; get digit, point to next...
   sub.b     #48,d0              ; 48 is ASCII value of 0
   rts                           ; back to work


;           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
FileChars:   dc.l     0          ; storage for Number of chars read
FileSize:    dc.l     0          ; storage for FileSize
EdNum        dc.l     0          ; storage for Editor entry size
EdPTR        dc.l     0          ; storage for Editor entry file PTR
EdLock       dc.l     0          ; storage for Editor entry file lock
PRTFile      dc.l     0          ; storage for PRT file handle
CharCount:   dc.l     0          ; storage for PTR to char to read in Buf
LinePtr:     dc.l     0          ; storage for PTR to start of line
RawHnd       dc.l     0          ; storage for raw window handle
CHandle      dc.l     0          ; storage for Current handle to use
QHandle      dc.l     0          ; storage for QPrint's handle to use
pf_PTR       dc.l     0          ; storage for PTR to Pref struct
FileNm       dc.l     0          ; storage for PTR to filename
OldDir       dc.l     0          ; storage for LOCK on old directory
SrchOK       dc.l     0          ; storage for "was valid Search" flag
CurPosn      dc.l     0          ; storage for current posn in file
ColTotal     dc.l     0          ; storage for total columns
HunFileSize  dc.w     0          ; storage for 1/100 of filesize
NumLines     dc.w     0          ; storage for display lines avail
RowSizeChg   dc.b     0          ; storage for num extra rows
ColSizeChg   dc.b     0          ; storage for num extra cols
LaceTogl     dc.b     0          ; storage for whether interlaced
BinOK        dc.b     0          ; storage for "binary is OK" flag
EndFlag      dc.b     0          ; storage for EOF flag
SmallFile    dc.b     0          ; storage for "is small file" flag
SrchType     dc.b     0          ; storage for "type of last search" flag
PrtScFlag    dc.b     0          ; storage for "print screen" flag
PRTName
   dc.b      'PRT:',0
PARName
   dc.b      'PAR:',0
SERName
   dc.b      'SER:',0
EditName
   dc.b      'ENV:Editor',0
RawName
   dc.b      'raw:0/0'
Wide
   dc.b      '    '
High
   dc.b      '    /'
   dc.b      ' Ctype V1.0  by Bill Nelson       <HELP> for help   <ESC> to exit ',0
PosPrompt
   dc.b      $9b,$30,$20,$70,$F,$9b
PromptPos
   dc.b      '  ;1H       ',$9b,'7m  Displayed '
CurPos
   dc.b      '    '
   dc.b      ' %  of  '
KByteTot
   dc.b      '     KBytes.     <SPACE> for more       ',$9b,'0m',0
ClrLn
   dc.b      $9b,'M',$9b,'F',$9b,'E',0
CursorOn
   dc.b      $9b,$20,$70,0
GetWinStat
   dc.b      $9b,$30,$20,$71,0
HelpMesg
   dc.b      12,$9b,'1;5H',$9b,'33mResult                Command         Alternates      Num Pad  ',$9b,'0m'
   dc.b      $9b,'4;5HForward a PAGE        SPACE           SHIFT-DOWN      PGDN        3  '
   dc.b      $9b,'5;5HForward a LINE        RETURN          DOWN            DOWN        2  '
   dc.b      $9b,'6;5HBackward  PAGE        BACKSPACE       SHIFT-UP        PGUP        9  '
   dc.b      $9b,'7;5HBackward  LINE        DELETE          UP              UP          8  '
   dc.b      $9b,'8;5HTOP of file           <               LEFT            HOME        7  '
   dc.b      $9b,'9;5HBOTTOM of file        >               RIGHT           END         1  '
   dc.b      $9b,'10;5HREFRESH Display       CTRL-L          R               CENTRE      5  '
   dc.b      $9b,'11;5HHELP (show this)      H               HELP            F1          ?  '
   dc.b      $9b,'12;5HQUIT/ESCAPE           CTRL-C          ESC             F10         Q  '
   dc.b      $9b,'14;5HSearch for String     /                             (Case Sensitive)'
   dc.b      $9b,'15;5HSearch for String     .                             (NOT Case sensitive)'
   dc.b      $9b,'16;5HNext Occurrence       N                             (Of previous String)'
   dc.b      $9b,'17;5HMove N% into file     %N                            (where N = number)'
   dc.b      $9b,'18;5HCall your Editor      E                             (Def in ENV:Editor)'
   dc.b      $9b,'19;5HPrint complete file   P               SHIFT-F7      (for WP users!)'
   dc.b      $9b,'20;5HPrint screen only     PrtSc           F7            (or ANY * key)'
   dc.b      $9b,'23;29H',$9b,'7m Any key to Continue ... ',$9b,'0m',0
   EvenPC

   end                           ; tell assembler that's all

