home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 384.lha / Ctype_v2.0 / CType2.a < prev    next >
Text File  |  1990-05-30  |  75KB  |  1,978 lines

  1. *-----------------------------------------------------*
  2. *                CType Version 2.02                   *
  3. *                                                     *
  4. *      Copyright February 1990 - by Bill Nelson       *
  5. *             Midnight Logic Software                 *
  6. *                                                     *
  7. *      This is a FREELY REDISTRIBUTABLE PROGRAM       *     
  8. *                                                     *
  9. * Please report any bugs or problems you find         *
  10. * (there PROBABLY are some!) - and any suggestions    *
  11. * for further functionality would also be welcomed.   *
  12. * Happy Assembling!                                   *
  13. *                                                     *
  14. *   v 2.02          00:00:01             10/05/90     *
  15. *                                                     *
  16. *-----------------------------------------------------*
  17.  
  18. PUR          EQU      1
  19. WBC          EQU      1          ; will need console if from WB
  20. REQ          EQU      1          ; want pure code, Req startup
  21. VS           EQU   1300          ; amount of variable space needed
  22.                                  ; alloc'd in ReqPurStart.ASM
  23.  
  24.    bra       Start               ; Jump into ReqPurStart.ASM
  25.  
  26.    INCLUDE  "INCLUDES:Header.ASM"
  27.  
  28. Quit         EQU      0          ; some EQUates for later readability
  29. Up           EQU      1
  30. Down         EQU      2
  31. Top          EQU      3
  32. Bottom       EQU      4
  33. Again        EQU      5   
  34. Assist       EQU      6
  35. PageUp       EQU      7
  36. PageDown     EQU      8
  37. NewFile      EQU      9
  38. SizeIt       EQU     10
  39. ScrollR      EQU     11
  40. ScrollL      EQU     12
  41. ChangeTab    EQU     13
  42. Next         EQU     14
  43.  
  44. ***  Variables as offsets from a5  ***
  45.  
  46. LineBuff     EQU      0          ; each line as output  (400 chars)
  47. KeyBuff      EQU    400          ; filename              (80 chars)
  48. Control      EQU    480          ; user requests etc     (36 chars)
  49. CBuff        EQU    516          ; 1 char user inputb     (4 chars)
  50. FileReq      EQU    520          ; PTR to FilReq struct       LONG
  51. FilePTR      EQU    524          ; PTR to File                LONG
  52. FileLok      EQU    528          ; PTR to FileLok             LONG
  53. fib_PTR      EQU    532          ; PTR to fib_struct memory   LONG
  54. FileMemBuf   EQU    536          ; PTR to filebuff memory     LONG
  55. FileChars    EQU    540          ; Number of chars read       LONG
  56. FileSize     EQU    544          ; FileSize                   LONG
  57. EdNum        EQU    548          ; Editor entry size          LONG
  58. EdPTR        EQU    552          ; Editor entry file PTR      LONG
  59. PRTFile      EQU    556          ; PRT file handle            LONG
  60. CharCount    EQU    560          ; PTR to char to read in Buf LONG
  61. LinePtr      EQU    564          ; PTR to start of line       LONG
  62. RawHnd       EQU    568          ; raw window handle          LONG
  63. pf_PTR       EQU    572          ; PTR to Pref struct         LONG
  64. FileNm       EQU    576          ; PTR to filename            LONG
  65. OldDir       EQU    580          ; LOCK on old directory      LONG
  66. SrchOK       EQU    584          ; "was valid Search" flag    LONG
  67. EndLine      EQU    588          ; end of current line        LONG
  68. CharCounter  EQU    592          ; charcounter                LONG
  69. ColTotal     EQU    696          ; total columns              LONG
  70. EOL          EQU    600          ; place EOL last found at    LONG
  71. NumLines     EQU    604          ; display lines avail        LONG
  72. NumFiles     EQU    608          ; num files specified        LONG
  73. CurrentFile  EQU    612          ; number of current file     LONG
  74. CurPosn      EQU    616          ; current position in file   LONG
  75. LastPosn     EQU    620          ; last position in file      LONG
  76. PageBot      EQU    624          ; current page bottom        LONG
  77. PageTop      EQU    628          ; current page TOP           LONG
  78. HereNow      EQU    632          ; midline posn               LONG
  79. StartLine    EQU    636          ; start of above line        LONG
  80. HunFileSize  EQU    640          ; 1/100 of filesize          WORD
  81. MUSTFormat   EQU    642          ; MUST FORMAT flag           BYTE
  82. FormatMode   EQU    643          ; State of format mode       BYTE
  83. IsMultiArg   EQU    644          ; flag "in multi-arg mode"   BYTE
  84. RowSizeChg   EQU    645          ; num extra rows             BYTE
  85. ColSizeChg   EQU    646          ; num extra cols             BYTE
  86. LaceTogl     EQU    647          ; whether interlaced         BYTE
  87. EndFlag      EQU    648          ; EOF flag                   BYTE
  88. TopFlag      EQU    649          ; TOF flag                   BYTE
  89. SmallFile    EQU    650          ; "is small file" flag       BYTE
  90. SrchType     EQU    651          ; "type of last search" flag BYTE
  91. PrtScFlag    EQU    652          ; "print screen" flag        BYTE
  92. TabSize      EQU    653          ; user tabsize preference    BYTE
  93. SmallWindow  EQU    654          ; whether undersize window   BYTE
  94. RawName      EQU    655          ; OpenWin string       (85 chars)
  95. Wide         EQU    662          ;
  96. High         EQU    666          ;
  97. FName        EQU    677          ; place to jam in file's name
  98. PosPrompt    EQU    746
  99. PromptPos    EQU    747          ; prompt string        (78 chars)
  100. CurPos       EQU    756
  101. KByteTot     EQU    766
  102. ModeMarker   EQU    787
  103. SPosPrompt   EQU    832          ; SHORT prompt string  (24 chars)
  104. SPromptPos   EQU    833          ;
  105. DirBuff      EQU    856          ; storage for DIR string
  106. FileBuff     EQU    988          ; storage for FILE string
  107. PathName     EQU   1020          ; storage for concat of above
  108. TextReq      EQU   1182          ; TextRequester struct
  109. GetLong      EQU   1228          ; GetLongStruct
  110. GetString    EQU   1262          ; GetStringStruct
  111.                                  ; TOTAL of 1298 bytes
  112.                                  ; EQU'd above for
  113.                                  ; startup to Alloc correctly
  114.  
  115.  
  116.    EvenPC
  117.  
  118. ***  The PROGRAM (at last!)  ***
  119.  
  120.  
  121. _Main
  122.    lea       TextReq(a5),a0
  123.    move.w    #$ffff,TR_KeyMask(a0); set requester to hot keys
  124.    move.w    #3,TR_textcolor(a0)
  125.    move.b    #8,TabSize(a5)      ; initial setting!
  126.    move.l    EndFromWB(a5),d0    ; was this started from WB
  127.    beq.s     CLIEntry            ; no, do the CLI stuff
  128.    move.l    WBMsg(a5),a0        ; yes, set WBMsg up for offset access
  129.    move.l    sm_NumArgs(a0),d3   ; how many args were provided
  130.    subq      #1,d3               ; decrement down to number of FILES
  131.    beq.s     NoArgs              ; were no files, set CurrentDir & call request
  132.    move.l    d3,NumFiles(a5)     ; save number of files requested
  133.    move.l    #1,CurrentFile(a5)  ; and start on first one...
  134.    bra       NextWBArg
  135.  
  136. NoArgs
  137.    move.l    sm_ArgList(a0),a2   ; get start of ArgList
  138.    move.l    (a2),d1             ; stick it in d1
  139.    DosCall   CurrentDir          ; and set our current dir to location of
  140.    move.l    d0,OldDir(a5)       ; CType (and save where we were)
  141.    bra.s     NoCLIArgs
  142. CLIEntry
  143.    move.l    CmdLen(a5),d0       ; Check if user entered filename
  144.    cmpi.b    #1,d0               ; on the command line
  145.    beq.s     NoCLIArgs           ; if not, exit with explanation
  146.    move.l    Command(a5),a1      ; check if ? is parameter
  147.    cmpi.b    #'?',(a1)           ;
  148.    beq.s     Usage
  149.    move.l    Command(a5),a0      ; set File buffer to match
  150.    lea       FileBuff(a5),a1
  151.    bsr       CopyString
  152.    move.l    Command(a5),d1      ; or set it up for CheckExists
  153.    move.l    d1,FileNm(a5)       ; and store pointer for later access
  154.    move.l    #1,NumFiles(a5)     ; number of files to display
  155.    move.l    #1,CurrentFile(a5)  ; and start off on first one
  156.    bra.s     GoGetIt
  157. Usage
  158.    TxtReq    UseTxt(pc),ResumeTxt(pc)
  159. NoCLIArgs
  160.    bsr       GetFileName         ; and get filename from user (?)
  161. GoGetIt
  162.    bra       OpenFile
  163. UseTxt
  164.    dc.b      10,' Enter an (optional) filename ',10
  165.    dc.b      10,' or just start the program up! ',0
  166.    EvenPC
  167.  
  168. NextWBArg
  169.    Zero      d2                  ; clear out d2
  170.    move.l    CurrentFile(a5),d0  ; num of current file as counter
  171. OffSetLoop
  172.    add.l     #wa_SIZEOF,d2       ; add size of WBArg in d2, as offset to arg
  173.    subq      #1,d0               ; decrement cur file counter
  174.    bne.s     OffSetLoop          ; not on it yet - more offset needed
  175.    move.l    WBMsg(a5),a0        ; yes, set WBMsg up for offset access
  176.    move.l    sm_ArgList(a0),a2   ; setup arglist for offset access
  177.    move.l    0(a2,d2),d1         ; ptr to directory lock into d1
  178.    DosCall   CurrentDir          ; change to directory of specified file
  179.    move.l    d0,OldDir(a5)       ; and save where we came from
  180.    move.l    wa_Name(a2,d2),d1   ; put PTR to filename in d1
  181.    move.l    d1,FileNm(a5)       ; and store for opening file after getting lock
  182.    move.l    d1,a0
  183.    lea       FileBuff(a5),a1     ; and copy Filename into buffer for title
  184.    bsr       CopyString
  185.    bra       OpenFile            ; and skip to the Openfile routine
  186.  
  187. GetFileName
  188.    move.l    FileReq(a5),d0      ; already HAVE one?
  189.    bne.s     GetFileAgain        ; yup - DON'T start another!
  190.    AllocPubMem #frq_SIZEOF       ; get memory for filerequester
  191.    tst.l     d0
  192.    beq       MemFail
  193.    move.l    d0,FileReq(a5)      ; store PTR to struct
  194.    move.l    d0,a0
  195.    lea       DirBuff(a5),a1
  196.    move.l    a1,frq_Dir(a0)      ; ptr to buff for directory
  197.    lea       FileBuff(a5),a1
  198.    move.l    a1,frq_File(a0)     ; ptr to buff for filename
  199.    lea       PathName(a5),a1
  200.    move.l    a1,frq_PathName(a0) ; ptr to buff for complete pathname
  201. GetFileAgain
  202.    move.l    FileReq(a5),a0      ; put it in a0
  203.    move.l    #0,frq_Flags(a0)    ; clear flags
  204.    lea       ReqTitle(pc),a1     ; give it a title
  205.    move.l    a1,frq_Title(a0)    ;
  206.    move.w    #40,frq_numlines(a0)
  207.    move.w    #3,frq_dirnamescolor(a0)
  208.    move.w    #2,frq_devicenamescolor(a0)
  209.    or.l      #FRQEXTSELECTM!FRQCACHINGM!FRQLOADINGM,frq_Flags(a0)
  210.    ReqCall   FileRequester       ; and call it up
  211.    tst.l     d0                  ; was it CANCELled?
  212.    beq       GoNow               ; yes - wants out...
  213.    move.l    FileReq(a5),a2      ; or find out what
  214.    move.l    frq_ExtendedSelect(a2),d1
  215.    beq.s     NoExtend            ; no extend select - 1 file only
  216.  
  217. NumFilesSelect
  218.    move.b    #1,IsMultiArg(a5)   ; we are in Multi-Arg mode
  219.    move.l    d1,a2               ; First ESSStruct in a2
  220.    Zero      d2                  ; start counter at zero
  221. 1$
  222.    move.l    es_NextFile(a2),a2  ; get next structure
  223.    addq      #1,d2               ; add 1 to counter
  224.    cmpi.l    #0,a2               ; is this link ptr zero?
  225.    bne.s     1$                  ; nope? do it again
  226.    move.l    d2,NumFiles(a5)     ; yup - counter = # of files
  227.    move.l    #1,CurrentFile(a5)  ; and we start on first file
  228.  
  229. MultiArgs
  230.    move.l    CurrentFile(a5),d2  ; current file is?
  231.    move.l    FileReq(a5),a0      ; get FileReq Struct
  232.    move.l    frq_ExtendedSelect(a0),a2
  233.    subq      #2,d2               ; 
  234.    blt.s     BuildName           ; was first file, HAVE right struct
  235. GetStruct
  236.    move.l    es_NextFile(a2),a2  ; get next struct
  237.    cmpi.l    #0,a2               ; check if zero (counter wrong somehow?)
  238.    beq.s     BuildName
  239.    dbra      d2,GetStruct        ; do again if counter not reached
  240. BuildName
  241.    lea       DirBuff(a5),a0      ; copy DIRname into Pathname
  242.    lea       PathName(a5),a1
  243.    bsr       CopyString
  244.    lea       PathName(a5),a0
  245.    subq      #1,a1               ; back up over null
  246.    cmp.l     a0,a1               ; Dir name was null?
  247.    beq.s     NoSep
  248.    cmp.b     #':',-(a1)          ; was last char of dir a ':' ?
  249.    bne.s     1$
  250.    addq      #1,a1               ; return a1 to correct posn
  251.    bra.s     NoSep               ; no other sep needed
  252. 1$
  253.    addq      #1,a1               ; return a1 to correct posn
  254.    move.b    #'/',(a1)+          ; put in dir separator
  255.  
  256. NoSep
  257.    lea       es_FileName(a2),a0  ; get file name
  258.    bsr       CopyString          ; into PathName for open
  259.    lea       es_FileName(a2),a0
  260.    lea       FileBuff(a5),a1     ; and into FileBuff
  261.    bsr       CopyString          ; so title reflects right file!
  262.    bra.s     SetName
  263.  
  264. NoExtend
  265.    move.b    #0,IsMultiArg(a5)   ; no multiargs active
  266.    move.l    #1,NumFiles(a5)     ; number of files we know of
  267.    move.l    #1,CurrentFile(a5)  ; and this file's number
  268.  
  269. SetName
  270.    lea       PathName(a5),a0     ; load name
  271.    move.l    a0,d1               ; into d1 for _CheckExists
  272.    move.l    d1,FileNm(a5)       ; and store for later
  273.    rts
  274.    
  275. ***  Open the file  ***
  276.  
  277. OpenFile
  278.    tst.l     d1                  
  279.    beq       NextOrExit  
  280.    PushReg   d1
  281.    bsr       _ShutDown
  282.    PullReg   d1
  283.    bsr       _CheckExists        ; try for Lock on file
  284.    tst.l     d0
  285.    beq.s     NoFileFound         ; no exist - I guess we lost it :-(
  286.    move.l    d0,FileLok(a5)      ; stash it for other uses!
  287.    bsr       _GetFileSize        ; find out the file size - how much MEM?
  288.    tst.l     d0
  289.    beq       OpenTrouble         ; couldn't get the filesize (mem?)
  290.    move.l    d0,FileSize(a5)     ; store for later - also in d0 to
  291.    AllocPubMem  d0               ; alloc enough mem for file buffer
  292.    tst.l     d0                  ; See if call made it
  293.    beq       MemFail             ; or leave...
  294.    move.l    d0,FileMemBuf(a5)   ; otherwise, store PTR to memory
  295.                                  ; (automatically LONG aligned by EXEC)
  296.    move.l    FileNm(a5),d1       ; put PTR to filename in d1
  297.    move.l    #MODE_OLDFILE,d2    ; for reading
  298.    DosCall   Open
  299.    tst.l     d0                  ; see if a handle was returned (success)
  300.    beq.s     OpenTrouble         ; No? Skip the rest
  301.    move.l    d0,FilePTR(a5)      ; or store handle if successful
  302.    bsr       _SetUpStrings       ; copy our modifiable strings to work area
  303.    bra       CalcKBytes          ; and get on with it
  304.  
  305. NoFileFound
  306.    TxtReqCt  NoFileMsg(pc),ResumeTxt(pc),FileBuff(a5)
  307.    bra       NextOrExit
  308. NoFileMsg
  309.    dc.b      10,' Could not locate file ',10,10,' <%s> ',0
  310.    EvenPC
  311.  
  312. OpenTrouble
  313.    TxtReq    OpenTroubleMsg(pc),ResumeTxt(pc)
  314.    bra.s     FixFileLok
  315. OpenTroubleMsg
  316.    dc.b      10,' Could not open file ',10,0
  317.    EvenPC
  318.  
  319. MemFail
  320.    TxtReq    MemFailMsg(pc),ResumeTxt(pc)
  321.    bra.s     FixFileLok
  322. MemFailMsg
  323.    dc.b      10,' Not enough memory! ',10,0
  324.    EvenPC
  325.  
  326. FixFileLok
  327.    move.l    FileLok(a5),d1      ; get the lock
  328.    beq.s     1$                  ; wasn't one, skip it!
  329.    DosCall   UnLock              ; free it up
  330. 1$
  331.    move.l    #0,FileLok(a5)      ; and zero the space
  332.    bra       NextOrExit
  333.  
  334. ***  Various Calculations for later  ***
  335.  
  336.  
  337. CalcKBytes
  338.    Zero      d0                  ; clear out the regs I use here
  339.    Zero      d1                  ;
  340.    move.l    FileSize(a5),d0     ; total filesize into d0
  341.    cmpi.l    #9999,d0            ; 
  342.    ble.s     SmallerFile         ; less than 10000 bytes, display as such
  343.    divu      #1024,d0            ; divide by bytes in a KByte
  344.    move.w    d0,d1               ; move only the word value to d1
  345.    swap      d0                  ; flip upper to lower word in d0
  346.    cmpi.w    #512,d0             ; is remainder above 1/2 K?
  347.    blt.s     1$                  ; if less, skip this next
  348.    addq      #1,d1               ; round up if greater than 1/2K
  349. 1$
  350.    lea       KByteTot(a5),a0     ; stuff it into string for end of page
  351.    bsr       _ASCIIConv          ; in ASCII :-)
  352.    bra.s     CalcForPercent
  353.  
  354. SmallerFile
  355.    move.l    d0,d1               ; put filesize in d1
  356.    lea       KByteTot(a5),a0     ; stuff it into string for end of page
  357.    bsr       _ASCIIConv          ; in ASCII
  358.    addq      #1,a0               ; add 1 to point past end of number
  359.    move.b    #' ',(a0)           ; stuff space over the "K" in KBytes :-)
  360.  
  361. CalcForPercent
  362.    Zero      d0                  ; clear out REG we need
  363.    Zero      d1                  ; to ensure "clean" result
  364.    move.l    FileSize(a5),d0     ; get filesize/100
  365.    divu      #100,d0             ; to make % calculation fit in WORD
  366.    move.w    d0,d1               ; thus allowing DIVU to work!
  367.    beq.s     1$                  ; unless is ZERO result! (no GURU 5 please!)
  368.    move.w    d1,HunFileSize(a5)  ; store it for calculation done at end of page
  369.    bra.s     GetThePrefs
  370. 1$
  371.    move.w    #1,HunFileSize(a5)  ; never less than 1 for divisor!
  372.    move.b    #1,SmallFile(a5)    ; and mark as file that needs no further calc!
  373.  
  374. *** Get data on the WorkBench screen ***
  375.  
  376.  
  377. GetThePrefs
  378.    bsr       _GetPreferences     ; find out current Prefs settings
  379.    tst.l     d0                  ; did it work?
  380.    beq       Error               ; no - get out
  381.  
  382. FillInParams
  383.    Zero      d1                  ; make sure ONLY our value in d1 
  384.    move.b    ColSizeChg(a5),d1   ; change in width (pixels)
  385.    addi      #640,d1             ; add in 640
  386.    lea       Wide(a5),a0         ; and get the ASCII equivalent
  387.    bsr       _ASCIIConv          ; and write it into the string we later
  388.    lea       Wide(a5),a0         ; pass to the OPEN call for a window
  389.    move.b    #'/',(a0)           ; add in the '/' in the right place!
  390.    Zero      d1       
  391.    move.b    RowSizeChg(a5),d1   ; same thing for height (pixels)
  392.    addi.l    #200,d1             ; add the standard height
  393.    move.b    LaceTogl(a5),d0     ; interlace on?
  394.    beq.s     1$                  ; no, we have the value
  395.    add.l     d1,d1               ; yes. multiply by 2
  396. 1$
  397.    lea       High(a5),a0         ; and stuff it in the string as well
  398.    bsr       _ASCIIConv          ; with the same "brute force" technique
  399.    lea       High(a5),a0
  400.    move.b    #'/',(a0)           ; with the / separator
  401. SetUpTitle
  402.    lea       FileBuff(a5),a0     ; PTR to filename in a0
  403.    move.l    a0,a2               ; and in a2 for difference
  404.    lea       FName(a5),a1        ; and destination for string in a1
  405.    Zero      d1                  ; initialize counter
  406. LengthChk
  407.    addq      #1,d1               ; increment counter
  408.    tst.b     (a2)+               ; look for end of string
  409.    bne.s     LengthChk
  410.    cmp       #24,d1              ; was it more than 24 chars
  411.    ble.s     MoveName            ; nope - just copy it up
  412. MvLeft
  413.    subq.l    #6,a1               ; back up over "File: " entry
  414. MoveName
  415.    bsr       CopyString          ; copy the string up
  416.    move.b    #' ',-(a1)          ; put space over the zero byte
  417.  
  418. ***  Open a window for I/O (of size we now know)  ***
  419.  
  420. OpenWin
  421.    lea       RawName(a5),a0
  422.    move.l    a0,d1               ; Set up a RAW window for single keystroke eval
  423.    move.l    #MODE_NEWFILE,d2    ; always as a new file
  424.    DosCall   Open                ; using the string we built above
  425.    tst.l     d0                  ; see if a handle was returned (success)
  426.    beq       Error               ; CAN'T open it - skip rest of it
  427.    move.l    d0,RawHnd(a5)       ; got it, store it for output later
  428.    DosPrt    RawHnd(a5),SetMouse(pc)
  429.    bsr.s     CalcCols
  430.    bra       ReadFile
  431.  
  432. CalcCols
  433.    PushReg   a2-a3
  434. GetResponse
  435.    DosPrt    RawHnd(a5),GetWinStat(pc)
  436.    move.l    #1000000,d2         ; wait 1 sec for incoming
  437.    move.l    RawHnd(a5),d1       ; in our window
  438.    DosCall   WaitForChar         ; we don't BUSY LOOP looking, but
  439.    DosRd     RawHnd(a5),KeyBuff(a5),#20 ; we want all that's useful
  440.    lea       KeyBuff(a5),a0
  441.    move.b    (a0)+,d0            ; get first char
  442.    cmpi.b    #$9b,d0             ; is it CSI?
  443.    bne       GetResponse       
  444.    move.b    (a0)+,d0            ; get a char
  445.    cmpi.b    #'1',d0             ; is it a 1?
  446.    bne       GetResponse       
  447.    move.b    (a0)+,d0            ; get a char
  448.    cmpi.b    #';',d0             ; is it a separator
  449.    bne       GetResponse       
  450.    move.b    (a0)+,d0            ; get a char
  451.    cmpi.b    #'1',d0
  452.    bne       GetResponse       
  453.    move.b    (a0)+,d0            ; get a char
  454.    cmpi.b    #';',d0
  455.    bne       GetResponse       
  456.    move.l    a0,a2               ; made it this far, must be Status report!
  457.    lea       PromptPos(a5),a1    ; set ptr to string for placing prompt
  458. WorkLoop
  459.    move.b    (a0),d0             ; get character
  460.    cmpi.b    #';',d0             ; see if it is a separator
  461.    beq.s     MarkIt              ; first parameter complete
  462.    cmpi.b    #' ',d0             ; space after end of 2nd parameter
  463.    beq.s     DoneBoth            ; 2nd parameter complete
  464.    move.b    (a0)+,(a1)+         ; pop char into string for posn'g prompt
  465.    bra.s     WorkLoop            ; get next character
  466. MarkIt
  467.    move.l    a0,a3               ; "store" PTR to next parameter (+1 needed!)
  468.    addq      #1,a3               ; so we can convert them to values
  469.    move.b    #0,(a0)             ; put a null after 1st parameter
  470.    lea       KeyBuff(a5),a1      ; and dummy dest so we can re-use loop :-)
  471.    bra.s     WorkLoop            ; (well - already knew that 1,1 was top corner!)
  472. DoneBoth
  473.    move.b    #0,(a0)             ; put null after 2nd parameter
  474.    move.l    a2,a0               ; ptr to 1st param in a0
  475.    bsr       _ASCII2Val          ; and convert it to value
  476.    subq      #2,d1               ; less 1 for Prompt, and 1 for DBRA!
  477.    ble       GetResponse         ; if 0 or less, wait for another event :-)
  478.    move.l    d1,NumLines(a5)     ; and we have number of lines
  479.    move.l    a3,a0               ; ptr to 2nd param
  480.    bsr       _ASCII2Val          ; convert it to a value
  481.    move.l    d1,ColTotal(a5)     ; we have number of useable columns
  482.    cmp.l     #61,d1              ; smaller than normal prompt string?
  483.    bge.s     1$
  484.    move.b    #1,SmallWindow(a5)  ; mark for SMALL prompt only!
  485.    bra.s     2$
  486. 1$
  487.    move.b    #0,SmallWindow(a5)  ; mark as big enough window
  488. 2$
  489.    lea       PromptPos(a5),a0    ; copy positioning to other
  490.    lea       SPromptPos(a5),a1   ; prompt string
  491.    move.b    (a0)+,(a1)+
  492.    move.b    (a0)+,(a1)+
  493.    PullReg   a2-a3               ; restore our regs
  494.    rts
  495.  
  496. ***  Read the file in  ***
  497.  
  498. ReadFile
  499.    DosRead   FilePTR(a5),FileMemBuf(a5),FileSize(a5)
  500.    tst.l     d0
  501.    bgt.s     KeepGoing           ; greater than 0, is length of useful file
  502.    move.l    FilePTR(a5),d1      ; or shut it down.
  503.    DosCall   Close
  504.    move.l    FileLok(a5),d1      ; better not forget to UNLOCK the file!
  505.    DosCall   UnLock              ; so we do it now...
  506.    move.l    #0,FileLok(a5)      ; and clear the storage area
  507.    TxtReq    NoReadFileMsg(pc),ResumeTxt(pc)
  508.    bra       NextOrExit
  509. NoReadFileMsg
  510.    dc.b      10,' File unreadable or empty ',10,0
  511.    EvenPC
  512.  
  513. KeepGoing
  514.    move.l    d0,FileChars(a5)    ; tells us how many were read
  515.    move.l    FilePTR(a5),d1      ; STILL no trust :-)
  516.    DosCall   Close               ; won't need it again
  517.    move.l    FileLok(a5),d1      ; better not forget to UNLOCK the file!
  518.    DosCall   UnLock              ; so we do it now...
  519.    move.l    #0,FileLok(a5)      ; and clear the storage (for later use!)
  520.  
  521. ***  Check file format  ***
  522.  
  523. FormatCheck
  524.    move.l    FileMemBuf(a5),a2   ; Start of buffer
  525.    move.l    FileChars(a5),a3    ; Number of chars it contains
  526.    adda.l    a2,a3               ; End of buffer now in a3
  527.    Zero      d6                  ; track char/line
  528.  
  529. InitScan
  530.    move.b    (a2)+,d0            ; move byte to d0, and increment a2
  531.    cmpi.b    #10,d0              ; is LF character?
  532.    beq.s     1$
  533.    cmpi.b    #13,d0              ; is CR character?
  534.    bne.s     2$
  535. 1$
  536.    Zero      d6
  537.    bra.s     InitScan       
  538. 2$
  539.    cmpi.b    #$E,d0              ; is SHIFT OUT char?
  540.    beq.s     IsBinary            ; likely binary file
  541.    cmpi.b    #127,d0             ; is highbit set?
  542.    bgt.s     IsBinary            ; likely not readable
  543.    addq      #1,d6               ; up count of chars this line
  544.    cmpi      #512,d6             ; more than 512 chars?
  545.    bgt.s     LineTooLong         ; FORCE format mode!
  546.    cmpa.l    a2,a3
  547.    bgt       InitScan
  548.    move.b    #0,MUSTFormat(a5)   ; made it this far - mark as OK
  549.    bra       DisplayFile
  550.  
  551. LineTooLong
  552.    move.b    #1,MUSTFormat(a5)   ; set both flags
  553.    move.b    #1,FormatMode(a5)
  554.    Zero      d7                  ; clear any format offset!
  555.    lea       ModeMarker(a5),a0
  556.    move.b    #'F',(a0)
  557.    bra.s     DisplayFile
  558.  
  559. IsBinary
  560.    TxtReq    NonASCIIMsg(pc),NoTxt(pc),YesTxt(pc)
  561.    tst.l     d0
  562.    bne       InitScan            ; keep testing (for long lines!)
  563.    bra       NextOrExit
  564. NonASCIIMsg
  565.    dc.b      10,' Non ASCII characters found ',10,10,' Attempt to display anyway? ',10,0
  566.    EvenPC
  567.  
  568. ***  Display the file  ***
  569.  
  570. DisplayFile
  571.    move.b    #1,TopFlag(a5)      ; mark us at TOF
  572.    Zero      d7
  573.    move.l    FileMemBuf(a5),a2   ; set a2 to start of buffer
  574.    move.l    a2,PageTop(a5)
  575. Pages
  576.    bsr.s     _PageSetup
  577.    bsr.s     _PageLoop
  578.    bra.s     ReadingTime
  579.    
  580. _PageSetup
  581.    lea       LineBuff(a5),a4     ; start of Buffer in a4
  582.    move.l    a4,LinePtr(a5)      ; and in LinePtr variable
  583.    move.l    NumLines(a5),d3     ; number of lines per page
  584.    move.l    ColTotal(a5),d2     ; number of columns per page
  585.    moveq     #12,d0
  586.    bsr       _WrChar             ; Clear the screen
  587.    move.l    a2,PageTop(a5)
  588.    rts
  589.  
  590. _PageLoop
  591.    Zero      d6                  ; set chars to display at zero
  592.    bsr       _BuildLine          ; build normal text line
  593.    bsr       _OutputLine         ; dump it to screen
  594.    dbra      d3,_PageLoop        ; loop till NumLines on the screen
  595.    rts
  596.  
  597. ReadingTime
  598.    cmp.b     #1,SmallWindow(a5)  ; is this an underwidth window?
  599.    bne.s     1$                  ; nope - do the prompt stuff
  600.    DosPrt    RawHnd(a5),CursorOff(pc)
  601.    DosPrt    RawHnd(a5),SPosPrompt(a5)
  602.    bra.s     GetAKey
  603. 1$
  604.    cmp.b     #1,SmallFile(a5)    ; was this a small file?
  605.    beq.s     ForceIt             ; yes, skip the calcs!
  606.    move.l    a2,d1               ; put current "position" in d1 for calcs
  607.    sub.l     FileMemBuf(a5),d1   ; subtract start of buffer from d1
  608.    divu      HunFileSize(a5),d1  ; divide by 1/100 of filesize for %
  609.    swap      d1                  ; flip top and bottom of register      
  610.    clr.w     d1                  ; to clear "remainder" - we don't care
  611.    swap      d1                  ; flip it back and
  612.    cmp.w     #100,d1             ; and check if over 100 (can only happen if
  613.    ble.s     Prompt              ; file is under 1000 bytes)
  614. ForceIt
  615.    moveq     #100,d1             ; if it is, make it 100
  616. Prompt
  617.    lea       CurPos(a5),a0       ; force feed it to string PosPrompt
  618.    bsr       _ASCIIConv
  619.    DosPrt    RawHnd(a5),CursorOff(pc)   
  620.    DosPrt    RawHnd(a5),PosPrompt(a5)
  621. GetAKey
  622.    bsr       _KeyHit             ; wait for a keystroke (sub returns action codes)
  623.    tst.l     d0                  ; see if user wants out
  624.    beq       GoNow               ; and exit if so
  625. ReEntry                          ; entry point if from PrtScreen
  626.    cmpi.b    #Up,d0              ; now we check all supported keystrokes
  627.    bne.s     2$
  628.    cmpa.l    a2,a3               ; at bottom?
  629.    bgt.s     1$
  630.    bsr       _BOF                ; redisplay as BOF
  631.    bsr       _PageSetup
  632.    bsr       _PageLoop
  633. 1$
  634.    bra       _BackLine           ; now back up a line
  635. 2$
  636.    cmpi.b    #Down,d0
  637.    bne.s     3$
  638.    bra       _ForLine            ; go ahead a line
  639. 3$
  640.    cmpi.b    #Top,d0
  641.    bne.s     4$
  642.    bsr       _TOF                ; jump to top
  643.    bra       Pages
  644. 4$
  645.    cmpi.b    #Bottom,d0
  646.    bne.s     5$
  647.    bsr       _BOF                ; jump to bottom
  648.    bra       Pages
  649. 5$
  650.    cmpi.b    #Again,d0
  651.    bne.s     6$
  652.    move.l    PageTop(a5),a2      ; just redisplay with current params
  653.    bra       Pages
  654. 6$
  655.    cmpi.b    #Assist,d0
  656.    bne.s     7$
  657.    bsr       _Help               ; call HELP requester
  658.    bra       GetAKey
  659. 7$
  660.    cmpi.b    #PageUp,d0
  661.    bne.s     8$
  662.    bsr       _BackPage           ; back it up 1 page if possible
  663.    bra       Pages
  664. 8$
  665.    cmpi.b    #PageDown,d0
  666.    bne.s     9$                  ; forward a page
  667.    bra       Pages
  668. 9$
  669.    cmpi.b    #SizeIt,d0          ; user requested size change?
  670.    bne.s     10$             
  671.    beq       _Resize             ; do it
  672. 10$
  673.    cmpi.b    #ScrollR,d0         ; Scroll it Right
  674.    bne.s     11$
  675.    beq       _ScrollRight
  676. 11$
  677.    cmpi.b    #ScrollL,d0         ; Scroll it Left
  678.    bne.s     12$
  679.    beq       _ScrollLeft
  680. 12$
  681.    cmpi.b    #ChangeTab,d0       ; user requested tab size change?
  682.    bne.s     13$
  683.    beq       _TabSize            ; do it
  684. 13$
  685.    cmpi.b    #Next,d0            ; hit ESC - wants another file?
  686.    bne       Pages
  687.  
  688. ***  Ways Out of program  ***
  689.  
  690. NextOrExit
  691.    move.l    NumFiles(a5),d0     ; load it with numfiles
  692.    move.l    CurrentFile(a5),d1  ; and our current file
  693.    sub.l     d1,d0               ; 
  694.    bgt.s     GetAnother          ; more to go...
  695. AskAnother
  696.    move.b    #0,IsMultiArg(a5)   ; we know we aren't in middle of multi
  697.    TxtReq    AnotherMsg(pc),NoTxt(pc),YesTxt(pc)
  698.    tst.l     d0
  699.    beq.s     GoNow
  700.    bra.s     GetNewName
  701. AnotherMsg
  702.    dc.b      10,' Display another file? ',10,0
  703.    EvenPC
  704.  
  705. GetNewName
  706.    bsr       GetFileName         ; and get another name
  707.    bra       OpenFile
  708.  
  709. GetAnother
  710.    add.l     #1,CurrentFile(a5)  ; increment number we're displaying
  711.    move.b    IsMultiArg(a5),d1   ; we in multiargs?
  712.    beq       NextWBArg           ; nope. get next WB arg
  713.    bsr       MultiArgs           ; yup - get the name
  714.    bra       OpenFile            ; and on we go
  715.  
  716. GoNow   
  717.    move.l    EndFromWB(a5),d1    ; see if we started from WB
  718.    beq.s     GoneNow             ; no, normal shutdown
  719.    move.l    OldDir(a5),d1       ; yes, return our CurrentDir as was
  720.    DosCall   CurrentDir          ; before we go and then
  721. GoneNow
  722.    bsr.s     _ShutDown           ; clean up everything that Startup doesn't
  723.    bsr.s     _ShutDown2          ; yes, EVERYTHING
  724.    Zero      d0
  725.    rts                           ; GONE
  726.  
  727. Error
  728.    bsr.s     _ShutDown
  729.    bsr.s     _ShutDown2
  730.    moveq     #20,d0              ; Set Error returncode
  731.    rts
  732.  
  733. *** Subroutines ***
  734.  
  735. _ShutDown
  736.  
  737. ReturnMem
  738.    move.l    FileMemBuf(a5),d0   ; ptr to buffer
  739.    beq.s     CloseRaw            ; if not ptr... (!)
  740.    move.l    d0,a1
  741.    move.l    FileSize(a5),d0
  742.    SysCall   FreeMem
  743.    move.l    #0,FileMemBuf(a5)   ; and CLEAR it!
  744. CloseRaw
  745.    move.l    RawHnd(a5),d1       ; load Window handle into d1
  746.    tst.l     d1                  ; if its NULL, we didn't get it open
  747.    beq.s     Shut                ; so don't TRY to close it!
  748.    DosCall   Close
  749.    move.l    #0,RawHnd(a5)       ; clear ptr too!
  750. Shut
  751.    rts
  752.  
  753. _ShutDown2
  754.    move.l    FileReq(a5),d0      ; ptr to FileReq struct
  755.    beq.s     Shut2
  756.    move.l    d0,a0
  757.    ReqCall   PurgeFiles          ; release all assoc mem
  758.    move.l    FileReq(a5),a1
  759.    move.l    #frq_SIZEOF,d0      ; and the FileReq mem itself
  760.    SysCall   FreeMem
  761.    move.l    #0,FileReq(a5)      ; no ptr now!
  762. Shut2
  763.    rts
  764.  
  765. _SetUpStrings
  766.    lea       RawName1(pc),a0     ; PTR to string in a0
  767.    lea       RawName(a5),a1      ; PTR to where it goes
  768.    bsr.s     CopyString          ; copy it up
  769.    lea       PosPrompt1(pc),a0   ; same again
  770.    lea       PosPrompt(a5),a1
  771.    bsr.s     CopyString
  772.    lea       SPosPrompt1(pc),a0  ; same again
  773.    lea       SPosPrompt(a5),a1   ; and fall through to go on back
  774. CopyString
  775.    move.b    (a0)+,(a1)+         ; null-terminated strings are easy
  776.    bne       CopyString          ; to move around in 680x0 asm!
  777.    rts
  778.  
  779. _CheckExists                     ; enter with filePTR in d1
  780.    moveq     #ACCESS_READ,d2     ; try it as a READ lock
  781.    DosCall   Lock
  782.    rts                           ; let caller evaluate results
  783.  
  784. _GetFileSize
  785.    AllocChipMem #fib_SIZEOF      ; allocate memory for FileInfoBlock
  786.    tst.l     d0                  ; (defined in DosEquates.ASM)
  787.    beq.s     GotFileSize         ; no memory, exit with 0 in d0
  788.    move.l    d0,fib_PTR(a5)      ; got mem, store PTR for later
  789.    move.l    d0,d2               ; and set it as 1st parameter with
  790.    move.l    FileLok(a5),d1      ; other parameter for Examine()
  791.    DosCall   Examine
  792.    tst.l     d0                  ; Boolean return
  793.    beq.s     CloseFibMem         ; can't imagine WHY, but give back mem!
  794.    move.l    fib_PTR(a5),a1      ; set up offset access for what we wanted
  795.    move.l    fib_Size(a1),d0     ; now we have a FileSize as "return code"
  796. CloseFibMem                      
  797.    PushReg   d0                  ; save the "return code" for later
  798.    move.l    fib_PTR(a5),a1      ; ptr to mem we allocated
  799.    move.l    #fib_SIZEOF,d0      ; and size of the memory block
  800.    SysCall   FreeMem             ; and give it back to the system
  801.    PullReg   d0                  ; and reset return code
  802. GotFileSize
  803.    rts
  804.  
  805. _GetPreferences
  806.    AllocChipMem #pf_SIZEOF       ; allocate memory for Preferences STRUCT
  807.    tst.l     d0                  ; (defined in IntEquates.ASM)
  808.    beq.s     GotPrefs            ; we didn't get it, d0 has "fail" return code
  809.    move.l    d0,pf_PTR(a5)       ; and store for later
  810.    move.l    d0,a0               ; and set it as 1st parameter with
  811.    move.l    #pf_SIZEOF,d0       ; number of bytes we want from it
  812.    IntCall   GetPrefs
  813.    tst.l     d0                  ; Should return our PTR to buffer..
  814.    beq.s     ClosePFMem          ; can't imagine WHY this would happen, but...
  815.    move.l    pf_PTR(a5),a1       ; set up offset access for what we wanted!
  816.    move.b    pf_RowSizeChange(a1),RowSizeChg(a5)
  817.    move.b    pf_ColumnSizeChange(a1),ColSizeChg(a5)
  818.    move.b    pf_LaceWB(a1),LaceTogl(a5)
  819.    moveq     #1,d0               ; we got what we wanted, so return "success"
  820. ClosePFMem                      
  821.    PushReg   d0                  ; store return code for now
  822.    move.l    pf_PTR(a5),a1       ; pointer to mem we got
  823.    move.l    #pf_SIZEOF,d0       ; sizeof memory we got
  824.    SysCall   FreeMem             ; give it back (we ARE well behaved!)
  825.    PullReg   d0                  ; keep return code!
  826. GotPrefs
  827.    rts                           ; return with "Boolean" result
  828.  
  829. _BuildLine
  830.    addq      #1,d6               ; up count of chars this line
  831.    move.b    (a2)+,d0            ; get next character
  832.    cmp.b     #12,d0
  833.    beq.s     EOLine              ; was CLS, treat as LF
  834.    cmpi.b    #$E,d0
  835.    beq.s     EOLine              ; was SHIFT-OUT - pretend was EOL
  836.    cmpi.b    #10,d0              ; (don't want ALT charset)
  837.    beq.s     EOLine
  838.    cmpi.b    #13,d0
  839.    beq.s     CRatEOL
  840.    cmp       d6,d2               ; end of displayable yet?
  841.    bne.s     1$                  ; nope - skip checks
  842.    cmpi.b    #1,FormatMode(a5)   ; is format mode active?
  843.    beq.s     WordWrap            ; yup - go do word wrap
  844. 1$
  845.    cmp.b     #9,d0               ; is it a TAB char?
  846.    beq       HandleTab           ; if so, pop spaces in buffer
  847.    move.b    d0,(a4)+
  848. CheckEOF
  849.    cmp.l     a2,a3               ; compare current posn (a2) w/ buffer end (a3)
  850.    bgt       _BuildLine          ; back to get next character
  851.    bra       GetOut              ; or leave if EOF
  852. CRatEOL
  853.    move.b    (a2)+,d0            ; check next character in string
  854.    cmpi.b    #10,d0              ; for an LF char (maybe from PC?)
  855.    beq.s     EOLine              ; yup - then just add LF to buffer
  856.    subq      #1,a2               ; nope-  back up so char not missed
  857. EOLine
  858.    move.b    #10,(a4)
  859.    rts
  860.  
  861. WordWrap
  862.    cmpi.b    #32,d0              ; we on a space char?
  863.    beq.s     WrapHere            ; 
  864.    cmpi.b    #9,d0               ; was TAB char
  865.    beq.s     EOLine              ; no need to expand it!
  866.    subq      #1,a2               ; return a2 to char we have
  867.    move.l    a2,EndLine(a5)      ; store this posn if needed
  868.    move.l    d6,CharCounter(a5)  ; and the char counter
  869.    move.l    a4,d1               ; and the buffer posn
  870. WrapLoop
  871.    subq      #1,d6               ; back up char counter
  872.    cmpi.b    #1,d6               ; at beginning of line?
  873.    beq.s     SkipWrap            ; yup...
  874.    move.b    -(a2),d0            ; back up a char
  875.    cmpi.b    #32,d0              ; got a space yet?
  876.    beq.s     DoWrap              ; use as new EOLine
  877.    cmpi.b    #9,d0               ; was it a tab char?
  878.    beq.s     DoWrap              ; will do as a place to wrap
  879.    subq      #1,a4               ; back up ptr into buffer
  880.    bra.s     WrapLoop            ; try next char back
  881. SkipWrap
  882.    move.l    EndLine(a5),a2      ; put a2 back at end of line
  883.    move.l    CharCounter(a5),d6  ; return d6 to num of chars
  884.    move.l    d1,a4               ; and posn in buffer
  885.    subq      #1,d6
  886.    bra       EOLine              ; pop it out
  887. DoWrap
  888.    subq      #1,a4               ; back up buff ptr
  889.    move.b    #10,(a4)            ; pop in EOL char
  890.    addq      #1,a2               ; return a2 to char after break
  891.    rts                           ; back to display line
  892. ReplaceTab
  893.    move.b    #10,-(a4)           ; put LF in buffer
  894.    rts
  895. WrapHere
  896.    move.b    (a2)+,d0            ; check next char
  897.    cmpi.b    #10,d0              ; is it a LF?
  898.    beq       EOLine              ; done here
  899.    cmpi.b    #13,d0              ; is it a CR?
  900.    beq       CRatEOL             ; do the check
  901.    cmpi.b    #32,d0              ; is another space?
  902.    beq.s     WrapHere            ; try again
  903.    subq      #1,a2               ; or back up so char not missed
  904.    bra       EOLine              ; and stuff EOL in buffer
  905.  
  906. HandleTab
  907.    PushReg   d3-d4               ; save working regs
  908.    Zero      d3                  ; and clean 'em out
  909.    Zero      d4                  ;
  910.    move.b    TabSize(a5),d4      ; set up tab size for later
  911.    beq.s     2$                  ; bypass divide by zero possibility!
  912.    move.l    d6,d3               ; current "char pos'n used" counter
  913.    subq      #1,d3               ; was "pre-incremented" in build loop
  914.    add       d4,d3               ; add "max effect" of tab
  915.    divu      d4,d3               ; divide by tabsize
  916.    clr.w     d3                  ; to get the remainder
  917.    swap      d3                  ;
  918.    sub       d3,d4               ; subtract remainder from "max effect"
  919.    subq      #1,d4               ; one off for dbra
  920.    add       d4,d6               ; and add "actual effect" to chars used
  921.    cmp.b     #1,FormatMode(a5)   ; is format mode in use?
  922.    bne.s     1$
  923.    cmp.l     d6,d2               ; are we out of chars?
  924.    bge.s     1$                  ; nope
  925.    move.b    #10,(a4)+           ; yup - put EOL in buffer
  926.    sub       d4,d6               ; and remove tab effect on chars to display
  927.    bra.s     2$
  928. 1$
  929.    move.b    #' ',(a4)+
  930.    dbra      d4,1$
  931. 2$
  932.    PullReg   d3-d4               ; restore working registers
  933.    bra       CheckEOF
  934.  
  935. GetOut
  936.    cmpi.b    #1,d6
  937.    bne.s     1$
  938.    Zero      d6
  939.    rts
  940. 1$
  941.    move.b    #10,(a4)+
  942.    rts
  943.  
  944. _OutputLine
  945.    tst.l     d7                  ; any scroll Offset?
  946.    beq.s     3$                  ; nope - ignore
  947.    sub.l     d7,d6               ; yes, that many fewer to display
  948.    bgt.s     2$                  ; does that make it 0 or less
  949. 1$
  950.    moveq     #10,d0
  951.    bsr       _WrChar             ; just write a LF
  952.    bra.s     5$                  ; and skip other output
  953. 2$
  954.    add.l     d7,LinePtr(a5)      ; add offset into buffer start addr
  955. 3$
  956.    cmp.l     d2,d6               ; compare allowable chars with # to output
  957.    ble.s     4$                  ; allowable number
  958.    move.l    d2,d6               ; or MAKE it allowable number
  959.    DosPrint  RawHnd(a5),LinePtr(a5),d6
  960.    moveq     #10,d0
  961.    bsr       _WrChar
  962.    bra.s     5$
  963. 4$
  964.    DosPrint  RawHnd(a5),LinePtr(a5),d6
  965.  
  966. 5$
  967.    lea       LineBuff(a5),a4
  968.    move.l    a4,LinePtr(a5)
  969.    rts
  970.  
  971. *** Get user requests  ***
  972.  
  973. _KeyHit
  974.    move.l    #1000000,d2         ; wait 1 sec for reader to hit a key
  975.    move.l    RawHnd(a5),d1       ; in our window
  976.    DosCall   WaitForChar         ; we don't BUSY LOOP looking, but
  977.    tst.l     d0
  978.    beq       _KeyHit             ; we are determined to get one!
  979.    DosRd     RawHnd(a5),Control(a5),#36  ; check it out for user's requests
  980.    move.b    Control(a5),d0
  981.    cmpi.b    #$9b,d0             ; is it CSI char?
  982.    beq       ExtendKey           ; if so, check it out
  983.  
  984.    cmpi.b    #' ',d0             ; <SPACE> char
  985.    beq       ForPage
  986.    cmpi.b    #'3',d0             ; <PG DN> char on Numeric pad
  987.    beq       ForPage
  988.  
  989.    cmpi.b    #8,d0               ; <BACKSPACE> char
  990.    beq       BackPage
  991.    cmpi.b    #'9',d0             ; <PG UP> char on Numeric pad
  992.    beq       BackPage
  993.  
  994.    cmpi.b    #'?',d0             ; just a ? :-)
  995.    beq       Help
  996.  
  997.    cmpi.b    #'q',d0
  998.    beq       WantsNext
  999.    cmpi.b    #'Q',d0
  1000.    beq       WantsNext
  1001.    cmpi.b    #27,d0              ; <ESC> char
  1002.    beq       WantsNext
  1003.  
  1004.    cmpi.b    #3,d0               ; <CTRL-C> char
  1005.    beq       WantsOut
  1006.  
  1007.    cmpi.b    #'r',d0
  1008.    beq       ScR
  1009.    cmpi.b    #'R',d0
  1010.    beq       ScR
  1011.    cmpi.b    #'6',d0             ; <RIGHT ARROW> key on Numeric pad
  1012.    beq       ScR
  1013.  
  1014.    cmpi.b    #'l',d0
  1015.    beq       ScL
  1016.    cmpi.b    #'L',d0
  1017.    beq       ScL
  1018.    cmpi.b    #'4',d0             ; <LEFT ARROW> key on Numeric pad
  1019.    beq       ScL
  1020.  
  1021.    cmpi.b    #13,d0              ; <RETURN> char
  1022.    beq       ForLine
  1023.    cmpi.b    #'2',d0             ; <DOWN ARROW> char on Numeric Pad
  1024.    beq       ForLine
  1025.  
  1026.    cmpi.b    #127,d0             ; <DELETE> char
  1027.    beq       BackLine
  1028.    cmpi.b    #'8',d0             ; <UP ARROW> char on Numeric pad
  1029.    beq       BackLine
  1030.  
  1031.    cmpi.b    #'t',d0
  1032.    beq       TOF
  1033.    cmpi.b    #'T',d0
  1034.    beq       TOF
  1035.    cmpi.b    #'<',d0
  1036.    beq       TOF
  1037.    cmpi.b    #'7',d0             ; <HOME> char on Numeric pad
  1038.    beq       TOF
  1039.  
  1040.    cmpi.b    #'b',d0
  1041.    beq       BOF
  1042.    cmpi.b    #'B',d0
  1043.    beq       BOF
  1044.    cmpi.b    #'>',d0
  1045.    beq       BOF
  1046.    cmpi.b    #'1',d0             ; <END> char on Numeric pad
  1047.    beq       BOF
  1048.  
  1049.    cmpi.b    #'e',d0
  1050.    beq       EDIT
  1051.    cmpi.b    #'E',d0
  1052.    beq       EDIT
  1053.  
  1054.    cmpi.b    #9,d0
  1055.    beq       Tab
  1056.  
  1057.    cmpi.b    #'/',d0             ; Case Sensitive search
  1058.    beq       SRCH
  1059.    cmpi.b    #'.',d0             ; Case INsensitive search
  1060.    beq       SRCHI
  1061.  
  1062.    cmpi.b    #'n',d0             ; repeat last search
  1063.    beq       ReSearch
  1064.    cmpi.b    #'N',d0
  1065.    beq       ReSearch
  1066.  
  1067.    cmpi.b    #'p',d0
  1068.    beq       PRT
  1069.    cmpi.b    #'P',d0             ; Print to ...
  1070.    beq       PRT
  1071.  
  1072.    cmpi.b    #'*',d0
  1073.    beq       PRTSc               ; PrintScreen
  1074.  
  1075.    cmpi.b    #'%',d0             ; Goto % in file
  1076.    beq       GOTO
  1077.  
  1078.    cmpi.b    #'f',d0
  1079.    beq       FMT   
  1080.    cmpi.b    #'F',d0             ; toggle format mode
  1081.    beq       FMT
  1082.  
  1083.    bra       _KeyHit             ; anything else we'll ignore!
  1084.  
  1085. ExtendKey
  1086.    move.b    Control+1(a5),d0    ; get next character
  1087.    cmpi.b    #'2',d0             ; MOUSE EVENT?
  1088.    beq       Mouse
  1089.    cmpi.b    #'1',d0             ; RESIZE EVENT?
  1090.    beq.s     RSize
  1091.    cmpi.b    #'?',d0             ; HELP Key?
  1092.    beq       Help                
  1093.    cmpi.b    #'0',d0             ; F1 Key?
  1094.    beq       Help                
  1095.    cmpi.b    #'6',d0             ; F7 Key?
  1096.    beq       PRTSc               
  1097.    cmpi.b    #'9',d0             ; F10 Key?
  1098.    beq       WantsOut               
  1099.    cmpi.b    #'A',d0             ; UP ARROW?
  1100.    beq       BackLine
  1101.    cmpi.b    #'T',d0             ; UP ARROW (shifted) ?
  1102.    beq       BackPage
  1103.    cmpi.b    #'B',d0             ; DOWN ARROW?
  1104.    beq       ForLine
  1105.    cmpi.b    #'S',d0             ; DOWN ARROW (shifted) ?
  1106.    beq       ForPage
  1107.    cmpi.b    #'C',d0             ; RIGHT ARROW?
  1108.    beq       ScR
  1109.    cmpi.b    #'D',d0             ; LEFT ARROW?
  1110.    beq       ScL
  1111.    cmpi.b    #' ',d0             ; LEFT or RIGHT ARROW (shifted) ?
  1112.    beq.s     ArrowChk
  1113.    bra       _KeyHit             ; don't WANT to know what else user hit!
  1114. ArrowChk
  1115.    move.b    Control+2(a5),d0
  1116.    cmpi.b    #'@',d0             ; RIGHT ARROW? (shifted of course)
  1117.    beq       BOF
  1118.    cmpi.b    #'A',d0             ; LEFT ARROW? (shifted)
  1119.    beq       TOF
  1120.    bra       _KeyHit             ; Ignoring all other keystrokes we got
  1121.                                  ; because an impatient user could have
  1122.                                  ; loaded us up with more requests than
  1123.                                  ; was intended!  Next call will write over
  1124.                                  ; whatever was in there...
  1125. RSize
  1126.    move.b    Control+2(a5),d0
  1127.    cmpi.b    #'2',d0
  1128.    beq       ReSize
  1129.    cmpi.b    #'6',d0             ; was it shifted F7?
  1130.    beq       PRT
  1131.    bra       _KeyHit
  1132. Mouse
  1133.    move.b    Control+5(a5),d0
  1134.    cmpi.b    #'1',d0             ; was it a button?
  1135.    bne.s     _NoGo               ; no - ignore it
  1136.    move.b    Control+6(a5),d0
  1137.    cmpi.b    #'0',d0             ; was it a button?
  1138.    bne.s     _NoGo               ; no - ignore it
  1139.    move.b    Control+7(a5),d0
  1140.    cmpi.b    #'4',d0
  1141.    bne.s     _NoGo               ; not it
  1142. LMB
  1143.    bra       ForPage             ; for the moment - advance a page!
  1144. _NoGo
  1145.    bra       _KeyHit
  1146.  
  1147. FMT
  1148.    cmp.b     #1,MUSTFormat(a5)   ; Is it LOCKED into format?
  1149.    beq.s     CantChange
  1150.    cmp.b     #1,FormatMode(a5)   ; is already IN format mode?
  1151.    beq.s     1$
  1152.    move.b    #1,FormatMode(a5)   ; nope - set it there
  1153.    lea       ModeMarker(a5),a0   ; change the marker in the prompt
  1154.    move.b    #'F',(a0)
  1155.    Zero      d7                  ; cancel any OFFSET value
  1156.    bra.s     2$
  1157. 1$
  1158.    move.b    #0,FormatMode(a5)
  1159.    lea       ModeMarker(a5),a0   ; change marker in the prompt
  1160.    move.b    #'N',(a0)
  1161. 2$
  1162.    moveq     #Again,d0           ; redisplay the page with new params
  1163.    rts
  1164. CantChange
  1165.    TxtReq    CantChangeMsg(pc),ResumeTxt(pc)
  1166.    moveq     #Again,d0
  1167.    rts
  1168. CantChangeMsg
  1169.    dc.b      10,' Cannot change mode on this file ',10,0
  1170.    EvenPC
  1171.  
  1172. Help
  1173.    moveq     #Assist,d0          ; pass "action code" in d0 to calling routine
  1174.    rts
  1175.  
  1176. ForPage
  1177.    cmpa.l    a2,a3
  1178.    ble       _KeyHit
  1179.    move.b    #0,TopFlag(a5)
  1180.    moveq     #PageDown,d0
  1181.    rts
  1182. BackPage
  1183.    cmpi.b    #1,TopFlag(a5)      ; are we already at the top?
  1184.    beq       _KeyHit             ; do nothing
  1185.    moveq     #PageUp,d0
  1186.    rts
  1187. TOF
  1188.    move.b    #1,TopFlag(a5)
  1189.    moveq     #Top,d0
  1190.    rts
  1191. BOF
  1192.    move.b    #0,TopFlag(a5)
  1193.    moveq     #Bottom,d0
  1194.    rts
  1195. WantsNext
  1196.    moveq     #Next,d0         
  1197.    rts
  1198. ForLine
  1199.    cmpa.l    a2,a3
  1200.    ble       _KeyHit             ; if EOF, do nothing
  1201.    move.b    #0,TopFlag(a5)      ; not EOF, say NOT TOF :-)
  1202.    moveq     #Down,d0
  1203.    rts
  1204. BackLine
  1205.    cmpi.b    #1,TopFlag(a5)
  1206.    beq       _KeyHit
  1207.    moveq     #Up,d0
  1208.    rts
  1209. ReSize
  1210.    move.l    #SizeIt,d0
  1211.    rts
  1212. ScR      
  1213.    cmp.b     #1,FormatMode(a5)   ; we in word wrap mode?
  1214.    beq       _KeyHit             ; do nothing
  1215.    moveq     #ScrollR,d0
  1216.    rts
  1217. ScL
  1218.    cmp.b     #1,FormatMode(a5)   ; we in word wrap mode?
  1219.    beq       _KeyHit             ; do nothing
  1220.    moveq     #ScrollL,d0
  1221.    rts
  1222. Tab
  1223.    moveq     #ChangeTab,d0
  1224.    rts
  1225. WantsOut
  1226.    moveq     #Quit,d0
  1227.    rts
  1228.  
  1229. ***  Act on User Requests!  ***
  1230.  
  1231. _Help
  1232.    TxtReq    HelpMsg(pc),NoTxt(pc),YesTxt(pc)
  1233.    tst.l     d0
  1234.    beq.s     1$
  1235.    TxtReq    HelpMsg2(pc),NoTxt(pc),YesTxt(pc)
  1236.    tst.l     d0
  1237.    beq.s     1$
  1238.    bra.s     _Help
  1239. 1$
  1240.    rts
  1241.  
  1242. _BackOnePage
  1243.    move.l    NumLines(a5),d3     ; Numlines as loop counter
  1244.    move.l    ColTotal(a5),d2     ; number of columns per page
  1245.    subq      #1,a2               ; back up so ON EOL
  1246.    addq      #1,d3               ; no dbra here :-)
  1247. ScanBack
  1248.    Zero      d4                  ; another counter (!)
  1249.    move.l    a2,EOL(a5)          ; store current EOL
  1250.    bsr.s     _BackScan           ; find previous EOL
  1251.    cmpi.b    #1,TopFlag(a5)      ; we at the top already?
  1252.    beq.s     GoTOF               ; yup - done this excercise!
  1253.    addq      #1,a2               ; step a2 past EOL char found
  1254.    Zero      d6                  ; zero the count of chars to display
  1255.    lea       LineBuff(a5),a4     ; point to start of buffer
  1256.    bsr       _BuildLine          ; build a display line
  1257.    addq      #1,d4               ; count times _BuildLine called
  1258.    cmp.l     EOL(a5),a2          ; are we back here?
  1259.    bgt.s     2$                  ; yup
  1260. 1$
  1261.    Zero      d6                  ; zero the count of chars to display
  1262.    lea       LineBuff(a5),a4     ; point to start of buffer
  1263.    bsr       _BuildLine          ; build another..
  1264.    addq      #1,d4               ; keeping count
  1265.    cmp.l     EOL(a5),a2          ; back where we started yet?
  1266.    ble.s     1$                  ; nope - try again
  1267. 2$
  1268.    subq      #1,a2               ; onto EOL char itself again
  1269.    cmp.l     d4,d3               ; compare lines taken with # to go
  1270.    beq.s     JustRight           ; done!!
  1271.    bgt.s     NotEnough           ; go for more
  1272. TooFar   
  1273.    sub.l     d3,d4               ; get diff OTHER way round
  1274.    subq      #1,d4               ; less 1 for dbra
  1275.    bsr.s     _BackScan           ; move on up
  1276.    addq      #1,a2               ; step past EOL char
  1277. 1$
  1278.    Zero      d6                  ; zero the count of chars to display
  1279.    lea       LineBuff(a5),a4     ; point to start of buffer
  1280.    bsr       _BuildLine          ; step forward
  1281.    dbra      d4,1$               ; number of diff times
  1282.    rts
  1283. NotEnough
  1284.    sub.l     d4,d3               ; reduce # lines to go    
  1285.    bsr.s     _BackScan           ; set a2 back where it worked
  1286.    bra       ScanBack            ; and around again ..
  1287. JustRight
  1288.    bsr.s     _BackScan           ; put a2 back where it worked
  1289.    addq      #1,a2               ; 1 char after EOL
  1290. GoTOF
  1291.    rts
  1292.    
  1293.  
  1294. _BackScan
  1295.    cmpi.b    #10,-(a2)           ; is char a LF?
  1296.    bne.s     1$                  ; yup - return OK
  1297.    rts
  1298. 1$
  1299.    cmpi.b    #13,(a2)            ; is it a CR?
  1300.    bne.s     3$                  ; nope - what else?
  1301.    addq      #1,a2               ; is next character
  1302.    cmpi.b    #10,(a2)            ; a LF?
  1303.    beq.s     2$
  1304.    subq      #1,a2               ; nope - return a2
  1305.    rts
  1306. 2$
  1307.    subq      #1,a2               ; yup - return a2
  1308.    bra.s     _BackScan           ; and act as if didn't exist
  1309. 3$
  1310.    cmpa.l    FileMemBuf(a5),a2   ; are we past start of file?
  1311.    bgt.s     _BackScan           ; nope - get next char
  1312.    move.l    FileMemBuf(a5),a2   ; yup - fix it
  1313.    move.b    #1,TopFlag(a5)
  1314.    rts
  1315.  
  1316. _BackPage
  1317.    move.l    PageTop(a5),a2      ; back up ptr to start of this page
  1318.    bsr       _BackOnePage        ; then up again, to show previous page
  1319.    rts
  1320.  
  1321. _TOF
  1322.    move.l    FileMemBuf(a5),a2   ; back up a2 to start of whole thing
  1323.    rts
  1324.  
  1325. _BOF
  1326.    movea.l   a3,a2               ; set a2 to end of buffer
  1327.    bsr       _BackOnePage        ; then back up a display page
  1328.    rts                           ; final page
  1329.  
  1330. _BackLine
  1331.    move.l    ColTotal(a5),d2     ; number of columns per page
  1332.    subq      #1,a2               ; put a2 ON EOL   
  1333.    moveq     #1,d3               ; set counter for one, and borrow the
  1334.    bsr       ScanBack            ; loop for here too :-)
  1335.    move.l    a2,PageBot(a5)      ; store new page END
  1336.    bsr       _BackOnePage        ; now set back full page
  1337.    cmpa.l    FileMemBuf(a5),a2   ; did we hit TOF?
  1338.    ble.s     SkipOutput          ; better skip it!
  1339.    DosPrt    RawHnd(a5),ScrDnHome(pc)
  1340.    move.l    a2,PageTop(a5)      ; mark new page top
  1341.    move.l    NumLines(a5),d3     ; number of lines per page
  1342.    move.l    ColTotal(a5),d2     ; number of columns per page
  1343.    lea       LineBuff(a5),a4     ; ptr to buffer
  1344.    move.l    a4,LinePtr(a5)      ; and to start of chars to display
  1345.    Zero      d6                  ; zero count of chars to display
  1346.    bsr       _BuildLine          ; build line in buffer
  1347.    bsr       _OutputLine         ; pump it out
  1348.    move.l    PageBot(a5),a2      ; restore new page END
  1349.    bra       ReadingTime         ; and onward
  1350. SkipOutput
  1351.    moveq     #Top,d0             ; simulate "TOF" keystroke
  1352.    bra       ReEntry             ; and continue
  1353. ScrDnHome
  1354.    dc.b      $9b,$54,$9b,'H',0   ; scroll down, and HOME cursor
  1355.    EvenPC
  1356.  
  1357. _ForLine
  1358.    DosPrt    RawHnd(a5),ClrLn(pc)
  1359.    lea       LineBuff(a5),a4
  1360.    move.l    a4,LinePtr(a5)
  1361.    move.l    NumLines(a5),d3
  1362.    move.l    ColTotal(a5),d2     ; number of columns per page
  1363.    Zero      d6                  ; zero Char counter
  1364.    bsr       _BuildLine          ; build line
  1365.    bsr       _OutputLine         ; display it
  1366.    move.l    a2,PageBot(a5)      ; save where we are
  1367.    bsr       _BackOnePage
  1368.    move.l    a2,PageTop(a5)      ; get new page TOP
  1369.    move.l    PageBot(a5),a2      ; back to bottom
  1370.    bra       ReadingTime
  1371.  
  1372. _PrevLine
  1373.    move.l    a2,HereNow(a5)      ; mark where we are
  1374.    bsr       _BackScan           ; find previous EOL
  1375.    addq      #1,a2               ; step 1 past it
  1376. PrevLoop
  1377.    move.l    a2,StartLine(a5)    ; store start of logical line
  1378.    lea       LineBuff(a5),a4     ; set up for
  1379.    move.l    a4,LinePtr(a5)
  1380.    move.l    NumLines(a5),d3
  1381.    move.l    ColTotal(a5),d2
  1382.    Zero      d6
  1383.    bsr       _BuildLine          ; building logical line
  1384.    cmp.l     HereNow(a5),a2      ; we now past point we found?
  1385.    ble.s     PrevLoop            ; nope - build another
  1386.    move.l    StartLine(a5),a2    ; yep, return with start of line
  1387.    rts
  1388.  
  1389.    
  1390. _ScrollRight
  1391.    cmp.l     #120,d7             ; less than 120 offset?
  1392.    bge.s     1$
  1393.    add       #10,d7              ; OK - add 10 to it
  1394. 1$
  1395.    moveq     #Again,d0           ; and redisplay the page
  1396.    bra       ReEntry
  1397.    
  1398. _ScrollLeft
  1399.    tst.l     d7
  1400.    ble.s     1$                  ; already at original left margin?
  1401.    sub       #10,d7
  1402. 1$
  1403.    moveq     #Again,d0
  1404.    bra       ReEntry             ; back to redisplay page
  1405.  
  1406. _TabSize
  1407.    lea       GetLong(a5),a0      ; get structure
  1408.    lea       TabTitle(pc),a1     ; give req a title
  1409.    move.l    a1,gl_titlebar(a0)
  1410.    move.l    #8,gl_defaultval(a0); 8 is the default tab size
  1411.    move.l    #2,gl_minlimit(a0)  ; and our limits
  1412.    move.l    #10,gl_maxlimit(a0)
  1413.    ReqCall   GetLong
  1414.    tst.l     d0                  ; if cancel, do nothing
  1415.    beq.s     NoChange
  1416.    lea       GetLong(a5),a0
  1417.    move.l    gl_result(a0),d0
  1418.    move.b    d0,TabSize(a5)      ; only .b to our var
  1419. NoChange
  1420.    moveq     #Again,d0           ; redisplay with new settings
  1421.    bra       ReEntry
  1422. TabTitle
  1423.    dc.b      ' TAB Size: ',0
  1424.    EvenPC
  1425.  
  1426. _Resize
  1427.    move.l    PageTop(a5),a2      ; set a2 back to current top of page
  1428.    bsr       CalcCols            ; reset new page size
  1429.    bra       Pages               ; and display new pagefull
  1430.  
  1431. *** Call the Editor ***
  1432.  
  1433. EDIT
  1434.    lea       EditName(pc),a0     ; get PTR to filename
  1435.    move.l    a0,d1               ; set it up for _CheckExists
  1436.    bsr       _CheckExists        ; to see if user HAS an editor preference!
  1437.    tst.l     d0
  1438.    bne.s     GetEditor           ; OK - it exists
  1439.  
  1440. AskEditor
  1441.    lea       LineBuff(a5),a0
  1442.    move.b    #0,(a0)
  1443.    lea       GetString(a5),a0    ; load structure
  1444.    lea       EdReqTitle(pc),a1   ; with values we want
  1445.    move.l    a1,gs_titlebar(a0)
  1446.    lea       LineBuff(a5),a1
  1447.    move.l    a1,gs_stringbuffer(a0)
  1448.    move.w    #30,gs_stringsize(a0)
  1449.    move.w    #28,gs_visiblesize(a0)
  1450.    move.w    #0,gs_versionnumber(a0)
  1451.    ReqCall   NewGetString        ; call requester for string
  1452.    tst.l     d0
  1453.    beq       EdTrouble           ; didn't get a valid response
  1454.    lea       LineBuff(a5),a0     ; OK - so figure how long string is
  1455.    Zero      d0
  1456. GetEdLen
  1457.    addq      #1,d0
  1458.    tst.b     (a0)+
  1459.    bne.s     GetEdLen
  1460.    subq      #1,d0
  1461.    bra.s     CallEditor          ; and go try to Execute() it
  1462. EdReqTitle
  1463.    dc.b      ' Editor Name: ',0
  1464.    EvenPC
  1465.  
  1466. GetEditor
  1467.    move.l    d0,FileLok(a5)      ; Lock in same place (not needed again)
  1468.    lea       EditName(pc),a0
  1469.    move.l    a0,d1
  1470.    move.l    #MODE_OLDFILE,d2    ; open up ENV:Editor and see what's there
  1471.    DosCall   Open     
  1472.    tst.l     d0
  1473.    bne.s     ReadEdName          ; 
  1474.    bra.s     EdTrouble
  1475.  
  1476. ReadEdName
  1477.    move.l    d0,EdPTR(a5)        ; store for closedown later
  1478.    DosRd     EdPTR(a5),LineBuff(a5),#79
  1479.    tst.l     d0                  ; read only as big as our buffer
  1480.    bne.s     CallEditor          ; if doesn't fit, won't find it!
  1481.    bra.s     EdTrouble
  1482.  
  1483. CallEditor
  1484.    lea       LineBuff(a5),a1     ; PTR to buff location
  1485.    add.l     d0,a1
  1486.    move.b    #' ',(a1)+          ; pop in a space
  1487.    move.l    FileNm(a5),a0       ; PTR to filename in a0
  1488.    bsr       CopyString
  1489.    lea       LineBuff(a5),a0     ; now set up whole string for
  1490.    move.l    a0,d1               ; Execute()
  1491.    Zero      d2                  ; no input specified
  1492.    move.l    StdOut(a5),d3       ; StdOut for output
  1493.    DosCall   Execute
  1494.    tst.l     d0
  1495.    bne.s     EndEdit
  1496.    bra.s     EdTrouble
  1497.  
  1498. EndEdit
  1499.    move.l    EdPTR(a5),d1        ; IF is PTR, THEN
  1500.    beq.s     DoneEdit
  1501.    DosCall   Close               ; close file
  1502.    move.l    #0,EdPTR(a5)        ; and clear storage!
  1503.    move.l    FileLok(a5),d1
  1504.    beq.s     DoneEdit            ; IF is lock, THEN
  1505.    DosCall   UnLock              ; unlock it
  1506.    move.l    #0,FileLok(a5)      ; and clear storage
  1507.  
  1508. DoneEdit
  1509.    moveq     #Again,d0           ; Redisplay from where we were
  1510.    rts
  1511.  
  1512. EdTrouble
  1513.    TxtReq    EdTroubleMsg(pc),ResumeTxt(pc)
  1514.    bra       EndEdit             ; and exit thru cleanup...
  1515. EdTroubleMsg
  1516.    dc.b      10,' Could not RUN your Editor ',10,0
  1517.    EvenPC
  1518.  
  1519. *** Printing options ***
  1520.  
  1521. PrtTitle
  1522.    dc.b      ' Choose PRINT Destination: ',0
  1523.    EvenPC
  1524.  
  1525. PRTSc
  1526.    move.b    #1,PrtScFlag(a5)        ; set flag for PrtScreen 
  1527.  
  1528. PRT
  1529.    PushReg   d2-d7
  1530.    lea       DirBuff(a5),a0
  1531.    move.b    #0,(a0)
  1532.    lea       FileBuff(a5),a1
  1533.    lea       PRTName(pc),a0
  1534.    bsr       CopyString
  1535.    move.l    FileReq(a5),a0      ; put it in a0
  1536.    move.l    #0,frq_Flags(a0)    ; clear flags
  1537.    lea       PrtTitle(pc),a1     ; give it a title
  1538.    move.l    a1,frq_Title(a0)    
  1539.    lea       DirBuff(a5),a1
  1540.    move.l    a1,frq_Dir(a0)      ; ptr to buff for directory
  1541.    lea       FileBuff(a5),a1
  1542.    move.l    a1,frq_File(a0)     ; ptr to buff for filename
  1543.    lea       PathName(a5),a1
  1544.    move.l    a1,frq_PathName(a0) ; ptr to buff for complete pathname
  1545.    or.l      #FRQEXTSELECTM!FRQCACHINGM!FRQSAVINGM,frq_Flags(a0)
  1546.    ReqCall   FileRequester       ; and call it up
  1547.    tst.l     d0
  1548.    beq       CancelPRT           ; was cancelled
  1549.    bsr       ChkDev              ; see if matches device name
  1550.    tst.l     d0                  ; if zero'd was no match
  1551.    bne       OverWrite           ; was match, treat as overwrite mode
  1552.    lea       PathName(a5),a0     ; diff num of chars, or no match, so
  1553.    move.l    a0,d1               ; PTR to name in d1
  1554.    bsr       _CheckExists        ; try for Lock on file
  1555.    tst.l     d0
  1556.    beq       OverWrite           ; Is new file, no problem
  1557.    move.l    d0,d1               ; old file, we'll unlock it now
  1558.    DosCall   UnLock              ; then check on user's wishes...
  1559.  
  1560. FExists
  1561.    TxtReq    FExistsMsg(pc),CancelTxt(pc),AppendTxt(pc),OverWriteTxt(pc)
  1562.    tst.l     d0
  1563.    beq       CancelPRT
  1564.    cmpi      #1,d0
  1565.    beq.s     Append
  1566.    bra.s     OverWrite
  1567. FExistsMsg
  1568.    dc.b      10,' Chosen file already exists ',10,10,' What should I do now? ',10,0
  1569.    EvenPC
  1570.  
  1571. Append
  1572.    lea       PathName(a5),a0
  1573.    move.l    a0,d1
  1574.    move.l    #MODE_READWRITE,d2  ; to allow append mode
  1575.    DosCall   Open
  1576.    tst.l     d0                  ; see if a handle was returned (success)
  1577.    beq       PRTError            ; No? Skip the rest
  1578.    move.l    d0,PRTFile(a5)      ; or store handle if successful
  1579.    move.l    d0,d1               ; and put in d1 with
  1580.    Zero      d2                  ; no offset in d2
  1581.    moveq     #1,d3               ; and OFFSET_END in d3 for a call to
  1582.    DosCall   Seek                ; Seek to end of file (where we add on!)
  1583.    bra.s     PrintIt             ; ready to print...
  1584.  
  1585. OverWrite
  1586.    lea       PathName(a5),a0     ; get PTR to user input
  1587.    move.l    a0,d1               ; into d1 as PTR to name
  1588.    move.l    #MODE_NEWFILE,d2    ; overwrite mode
  1589.    DosCall   Open                ; and open it up
  1590.    tst.l     d0                  ; check for returned handle
  1591.    beq       PRTError            ; no - get out
  1592.    move.l    d0,PRTFile(a5)      ; store it for close down
  1593.  
  1594. PrintIt
  1595.    move.l    a2,PageBot(a5)      ; just hiding it
  1596.    cmpi.b    #1,PrtScFlag(a5)    ; was it a PrtSc only?
  1597.    beq.s     PrtScIt             ; handle it differently
  1598.    DosPrt    PRTFile(a5),FileMemBuf(a5),FileSize(a5)
  1599.    cmpi.l    #-1,d0              ; oops! not all chars written..
  1600.    beq.s     PRTError
  1601.    bra.s     PRTCleanUp
  1602.  
  1603. PrtScIt
  1604.    move.l    PageTop(a5),d2      ; top of page, & ptr to file
  1605.    move.l    a2,d3               ; page bottom into d3
  1606.    sub.l     d2,d3               ; difference is chars to write
  1607.    move.l    PRTFile(a5),d1      ; "file" ptr into d1
  1608.    DosCall   Write               ; pump it out
  1609.    cmpi.l    #-1,d0              ; not all written?
  1610.    beq.s     PRTError            ; oops!
  1611.    move.b    #0,PrtScFlag(a5)    ; done with PrtScrn
  1612.  
  1613. PRTCleanUp
  1614.    move.l    PRTFile(a5),d1      ; IF is PTR, THEN
  1615.    beq.s     DonePRT
  1616.    DosCall   Close               ; close file
  1617.    move.l    #0,PRTFile(a5)      ; and clear storage!
  1618. DonePRT
  1619.    moveq     #Again,d0           ; Redisplay from where we were
  1620.    PullReg   d2-d7
  1621.    rts
  1622.  
  1623. CancelPRT
  1624.    cmpi.b    #1,PrtScFlag(a5)    ; if was PrtScreen operation
  1625.    bne.s     1$
  1626.    move.b    #0,PrtScFlag(a5)    ; cancel THAT too! :-)
  1627. 1$
  1628.    bra       PRTCleanUp
  1629.  
  1630. PRTError
  1631.    TxtReq    PRTErrorMsg(pc),ResumeTxt(pc)
  1632.    bra       CancelPRT   
  1633. PRTErrorMsg
  1634.    dc.b      10,' ERROR occurred! ',10,0
  1635.    EvenPC
  1636.  
  1637. ChkDev
  1638.    lea       PathName(a5),a0     ; load PTR to user input
  1639.    lea       PRTName(pc),a1      ; and possible value
  1640.    bsr.s     _CompChar           ; and compare
  1641.    tst.l     d0                  ; if match, d0 = last char
  1642.    bne.s     MatchFound          ; if zero, then keep checking
  1643.    lea       PathName(a5),a0
  1644.    lea       PARName(pc),a1      ; next poss to check
  1645.    bsr.s     _CompChar
  1646.    tst.l     d0
  1647.    bne.s     MatchFound          ; keep checking if zero
  1648.    lea       PathName(a5),a0
  1649.    lea       SERName(pc),a1
  1650.    bsr.s     _CompChar
  1651. MatchFound
  1652.    rts                           ; either way - d0 = success in matching :-)
  1653.  
  1654. _CompChar
  1655.    move.l    #3,d4               ; countdown of chars for DBRA
  1656.    Zero      d0                  ; clear out d0
  1657. CompLoop
  1658.    move.b    (a0)+,d0            ; move char into d0
  1659.    bsr       _ConvChar           ; and get char converted (if needed)
  1660.    move.b    (a1)+,d5            ; compare w/char at current posn in name
  1661.    cmp.b     d5,d0               ; does it match char in d0?
  1662.    beq.s     CompMore            ; if match, continue check
  1663.    cmp.b     d5,d1               ; does it match char in d1?
  1664.    beq.s     CompMore            ; if match continue check
  1665.    bra.s     CompNot             ; otherwise get out
  1666. CompMore
  1667.    dbra      d4,CompLoop         ; was match: chars left?
  1668.    rts
  1669. CompNot
  1670.    Zero      d0
  1671.    rts
  1672.  
  1673. ***   Search Operations  ***
  1674. * we give up speed for space here and use the same search 
  1675. * whether or not case sensitive.  2 compares for every 
  1676. * character, but a 680x0 is pretty quick, right?
  1677.  
  1678. SRCH
  1679.    PushReg   d3-d7               ; save 'em for later!
  1680.    move.b    #0,SrchType(a5)     ; we are case sensitive!
  1681.    lea       SrchSensTitle(pc),a1
  1682.    bra.s     Search
  1683. SrchSensTitle
  1684.    dc.b      ' Case Sensitive Search ',0
  1685.    EvenPC
  1686.  
  1687. SRCHI
  1688.    PushReg   d3-d7               ; save 'em for later
  1689.    move.b    #1,SrchType(a5)     ; we are NOT case sensitive!
  1690.    lea       SrchInsensTitle(pc),a1
  1691.    bra.s     Search
  1692. SrchInsensTitle
  1693.    dc.b      ' Case insensitive Search ',0
  1694.    EvenPC
  1695.  
  1696. Search
  1697.    lea       KeyBuff(a5),a0      ; load buffer
  1698.    move.b    #0,(a0)
  1699.    lea       GetString(a5),a0    ; load structure
  1700.    move.l    a1,gs_titlebar(a0)
  1701.    lea       KeyBuff(a5),a1
  1702.    move.l    a1,gs_stringbuffer(a0)
  1703.    move.w    #80,gs_stringsize(a0)
  1704.    move.w    #40,gs_visiblesize(a0)
  1705.    ReqCall   NewGetString        ; call requester for string
  1706.    tst.l     d0
  1707.    beq       NoMatch
  1708.    lea       KeyBuff(a5),a0
  1709.    Zero      d0
  1710. LenGetLoop
  1711.    addq      #1,d0
  1712.    tst.b     (a0)+
  1713.    bne.s     LenGetLoop   
  1714.    move.l    d0,d3               ; store length of string in d3
  1715.    subq.l    #1,d3               ; less one (for dbra)
  1716.    move.l    d3,d4               ; and in d4 for testing
  1717.    move.l    a2,CurPosn(a5)      ; in case we need to know!
  1718.    PushReg   d3                  ; because BackOnePage needs it
  1719.    bsr       _BackOnePage        ; to start of displayable page
  1720.    PullReg   d3                  ; and back to our value
  1721.    bra.s     StartSrch           ; and start search
  1722.  
  1723. ReSearch 
  1724.    PushReg   d3-d7               ; save 'em for later
  1725.    move.l    SrchOK(a5),d3       ; check if previous valid search
  1726.    beq.s     NoMatch             ; no? skip outta here!
  1727.    move.l    d3,d4               ; Yes, copy string length(-1) to d4
  1728.    move.l    a2,CurPosn(a5)      ; in case we need to know!
  1729.    move.l    LastPosn(a5),a2     ; "stored" from last search
  1730.  
  1731. StartSrch 
  1732. FirstChar 
  1733.    Zero      d0                  ; clear out d0
  1734.    lea       KeyBuff(a5),a0      ; PTR to string in a0
  1735.    move.b    (a0)+,d0            ; move first char into d0
  1736.    bsr       _ConvChar           ; and get char converted (if needed)
  1737. SrchLoop 
  1738.    move.b    (a2)+,d5            ; compare w/char at current posn in file
  1739.    cmp.b     d5,d0               ; does it match char in d0?
  1740.    beq.s     Match1              ; if match, continue check
  1741.    cmp.b     d5,d1               ; does it match char in d1?
  1742.    beq.s     Match1              ; if match continue check
  1743.    cmpa.l    a2,a3               ; see if past EOF
  1744.    ble.s     NoMatch             ; if we are, then no match, natch
  1745.    bra       SrchLoop            ; no match yet, so keep searching
  1746.  
  1747. Match1 
  1748.    move.l    a2,d7               ; store new position in file
  1749. MatchLoop
  1750.    subq.l    #1,d4               ; lower string count by 1
  1751.    beq.s     Matched             ; if none left, match is good
  1752.    move.b    (a0)+,d0            ; get next char of string
  1753.    bsr       _ConvChar           ; and set it up for checking
  1754.    cmpa.l    a2,a3               ; check against EOF count
  1755.    ble.s     NoMatch             ; at EOF - stop already!
  1756.    move.b    (a2)+,d5            ; compare w/char at current posn in file
  1757.    cmp.b     d5,d0               ; does it match char in d0?
  1758.    beq       MatchLoop           ; if match, continue check
  1759.    cmp.b     d5,d1               ; does it match char in d1?
  1760.    beq       MatchLoop           ; if match continue check
  1761.    move.l    d3,d4               ; otherwise reset string length check
  1762.    move.l    d7,a2               ; set a2 back to last unchecked position
  1763.    bra       FirstChar           ; and start search for first char again
  1764. Matched
  1765.    move.b    #0,TopFlag(a5)
  1766.    move.l    d7,LastPosn(a5)     ; "store" location to display from
  1767.    move.l    LastPosn(a5),CurPosn(a5)  ; for reasonable value if "re-search" fails
  1768.    PushReg   d2-d4
  1769.    bsr       _PrevLine           ; set a2 to start of line found
  1770.    PullReg   d2-d4
  1771.    moveq     #PageDown,d0        ; tell display routine to go from here
  1772.    move.l    d3,SrchOK(a5)       ; Set flag (w num of chars in string
  1773.    PullReg   d3-d7               ; and reset d3-d7 as before
  1774.    rts
  1775.  
  1776. NoMatch
  1777.    move.l    CurPosn(a5),a2      ; and current posn in file!
  1778.    move.l    #0,SrchOK(a5)       ; Set flag that search DIDN'T work
  1779.    TxtReqCt  NotFoundMsg(pc),ResumeTxt(pc),KeyBuff(a5)
  1780.    PullReg   d3-d7               ; return d3/d7 to previous contents
  1781.    moveq     #Again,d0           ; redisplay from where we were
  1782.    rts
  1783. NotFoundMsg
  1784.    dc.b      10,' <%s> ',10,10,'  Not Found  ',10,0
  1785.    EvenPC
  1786.  
  1787. _ConvChar
  1788.    move.l    d0,d1               ; copy it into d1
  1789.    cmpi.b    #0,SrchType(a5)     ; is case sensitive search?
  1790.    beq.s     NotAlpha            ; do nothing else :-)
  1791.    cmpi.b    #'A',d0             ; is char upper case?
  1792.    blt.s     NotAlpha            ; lower, not alphabetic
  1793.    cmpi.b    #'Z',d0             ;
  1794.    ble.s     UpperCase           ; lower or eq, is UpperCase Alpha
  1795.    cmpi.b    #'a',d0             ;
  1796.    blt.s     NotAlpha            ; lower, not alphabetic
  1797.    cmpi.b    #'z',d0             ;
  1798.    ble.s     LowerCase           ; lower or eq, is LowerCase Alpha
  1799.    bra.s     NotAlpha            ; higher, not alphabetic
  1800. UpperCase
  1801.    add.l     #32,d1              ; make d1 a lower case copy
  1802.    bra.s     NotAlpha            ; and get on with it
  1803. LowerCase
  1804.    sub.l     #32,d1              ; make d1 an upper case copy
  1805. NotAlpha
  1806.    rts
  1807.  
  1808. ***  GOTO Percent of File  ***
  1809.  
  1810. GOTO
  1811.    lea       GetLong(a5),a0
  1812.    lea       GotoTitle(pc),a1
  1813.    move.l    a1,gl_titlebar(a0)
  1814.    move.l    #0,gl_defaultval(a0)
  1815.    move.l    #0,gl_minlimit(a0)
  1816.    move.l    #100,gl_maxlimit(a0)
  1817.    or.l      #GLNODEFAULTM,gl_flags(a0)  ; don't GIVE a default value
  1818.    ReqCall   GetLong
  1819.    tst.l     d0
  1820.    beq.s     GotoExit
  1821.    lea       GetLong(a5),a0
  1822.    move.l    gl_result(a0),d0
  1823.    tst.b     d0                  ; and got what back?
  1824.    beq.s     MeansTop            ; zero? hope user MEANT top :-)
  1825.    cmpi.b    #100,d0             ; was it 100?
  1826.    beq.s     MeansBottom         ; must mean go to bottom
  1827.    addq      #1,d0               ; kludge for rounding errors
  1828.    mulu      HunFileSize(a5),d0  ; multiply by 1/100 of the file's size
  1829.    move.l    FileMemBuf(a5),d1   ; start of file in d0
  1830.    add.l     d0,d1               ; add it to result of calc
  1831.    move.l    d1,a2               ; now we have PTR to display from
  1832.    move.b    #0,TopFlag(a5)      ; and we're NOT at top of file
  1833.    bsr       _PrevLine           ; back up to beginning of line
  1834.    move.l    a2,PageTop(a5)      ; mark this as top of page
  1835. GotoExit
  1836.    moveq     #PageUp,d0          ; tell main loop to show TO here
  1837.    rts
  1838. MeansBottom
  1839.    moveq     #Bottom,d0
  1840.    rts
  1841. MeansTop
  1842.    moveq     #Top,d0
  1843.    rts
  1844. GotoTitle
  1845.    dc.b      ' GO TO % ? ',0
  1846.    EvenPC
  1847.  
  1848. ***  Useful General Subroutines  ***
  1849.  
  1850. _WrChar                          ; Enter with char to print in d0
  1851.    PushAll                       ; Save regs
  1852.    lea       CBuff(a5),a1        ; PTR to buffer in a1
  1853.    move.b    d0,(a1)             ; Put character in buffer
  1854.    DosPrt    RawHnd(a5),CBuff(a5),#1    ; and write it
  1855.    PullAll                       ; Restore regs
  1856.    rts
  1857.    
  1858. _ASCIIConv                       ; Enter with value for conversion in d1
  1859.                                  ; and buffer to store result in a0
  1860.    Zero      d0                  ; this routine only handles 4 decimal chars
  1861.    bsr.s     Do_It               ; because I want it to :-)  (for punching
  1862.    rts                           ; values into strings like RawName)
  1863. Do_It
  1864.    divu      #1000,d1            ; get 1000's digit
  1865.    bsr.s     Eval                ; evaluate and move remainder
  1866.    divu      #100,d1             ; get 100's digit
  1867.    bsr.s     Eval                ; 
  1868.    divu      #10,d1              ; get 10's digit
  1869.    bsr.s     Eval                ; 
  1870.    addq.l    #1,d0               ; if only character, we display the 0
  1871. Eval
  1872.    add       #48,d1              ; convert to ASCII value
  1873.    cmpi.b    #'0',d1             ; is it a leading ASCII Zero char now?
  1874.    bne.s     NotLdZero
  1875.    tst.l     d0                  ; test d0 for a previous no-zero char
  1876.    bne.s     NotLdZero           ; if was one, skip the change to space
  1877.    move.b    #' ',(a0)+          ; there wasn't - so store space instead
  1878.    bra.s     SetForNext          ; and get ready for next digit
  1879. NotLdZero
  1880.    addq.l    #1,d0               ; set flag that nonleadZero char preceded this
  1881.    move.b    d1,(a0)+            ; store digit
  1882. SetForNext
  1883.    clr.w     d1                  ; erase lower word
  1884.    swap      d1                  ; move remainder into lower word
  1885.    rts                           ; return for more (or to caller if done)
  1886.  
  1887. _ASCII2Val                       ; Enter with ASCII string PTR in a0
  1888.                                  ; returns with value in d1   
  1889.    Zero      d1                  ; clear it out
  1890.    bsr.s     DecLoop
  1891.    rts
  1892. DecLoop
  1893.    bsr.s     GetDigit            ; get converted digit
  1894.    blt.s     DecDone             ; less than ASCII 0, not digit (done?)
  1895.    cmpi.b    #9,d0               ; test if greater than 9
  1896.    bgt.s     DecDone             ; yes? get out 
  1897.    mulu.w    #10,d1              ; step up previous result by 10
  1898.    add       d0,d1               ; and add in the new digit
  1899.    bra.s     DecLoop             ; and back for more
  1900. DecDone
  1901.    rts
  1902. GetDigit
  1903.    Zero      d0
  1904.    move.b    (a0)+,d0            ; get digit, point to next...
  1905.    sub.b     #48,d0              ; 48 is ASCII value of 0 
  1906.    rts                           ; back to work
  1907.                       
  1908. *** Data Storage areas ***
  1909.  
  1910. RawName1
  1911.    dc.b      'raw:0/0        /'
  1912.    dc.b      'File:                          CTYPE 2.02         <HELP> for help    ',0
  1913. PosPrompt1
  1914.    dc.b      $9b,'  ;1H',$9b,'7m      % of '
  1915.    dc.b      '     KBytes   MODE = N   Click or <SPACE> = more ',$9b,'0m',$9b,'K',0
  1916. SPosPrompt1
  1917.    dc.b      $9b,'  ;1H ',$9b,'7m -MORE- ',$9b,'0m',$9b,'K',0
  1918. PRTName
  1919.    dc.b      'PRT:',0
  1920. PARName
  1921.    dc.b      'PAR:',0
  1922. SERName
  1923.    dc.b      'SER:',0
  1924. EditName
  1925.    dc.b      'ENV:Editor',0
  1926. ReqTitle
  1927.    dc.b      ' CType 2.02     Choose a File:   ',0
  1928. ClrLn
  1929.    dc.b      $9b,'M',$9b,'F',$9b,'E',0
  1930. CursorOn
  1931.    dc.b      $9b,$20,$70,0
  1932. CursorOff
  1933.    dc.b      $9b,$30,$20,$70,$F,0
  1934. GetWinStat
  1935.    dc.b      $9b,$30,$20,$71,0
  1936. SetMouse
  1937.    dc.b      $9b,'2;12{',0
  1938. YesTxt
  1939.    dc.b      ' Yes ',0
  1940. NoTxt
  1941.    dc.b      ' NO ',0
  1942. CancelTxt
  1943.    dc.b      ' Cancel ',0
  1944. AppendTxt
  1945.    dc.b      ' Append ',0
  1946. OverWriteTxt
  1947.    dc.b      ' OverWrite ',0
  1948. ResumeTxt
  1949.    dc.b      ' Resume ',0
  1950. HelpMsg
  1951.    dc.b      10,' Result               Command      Alternates     Num Pad',10,10
  1952.    dc.b      ' Forward a PAGE       SPACE        SHIFT-DOWN     PGDN       3 ',10
  1953.    dc.b      ' Forward a LINE       RETURN       DOWN           DOWN       2 ',10
  1954.    dc.b      ' Backward  PAGE       BACKSPACE    SHIFT-UP       PGUP       9 ',10
  1955.    dc.b      ' Backward  LINE       DELETE       UP             UP         8 ',10
  1956.    dc.b      ' TOP of file          <            LEFT           HOME       7 ',10
  1957.    dc.b      ' BOTTOM of file       >            RIGHT          END        1 ',10
  1958.    dc.b      ' Scroll RIGHT         RIGHT        R              RIGHT      6 ',10
  1959.    dc.b      ' Scroll LEFT          LEFT         L              LEFT       4 ',10
  1960.    dc.b      ' QUIT/Next File       ESC          Q              F10',10,10
  1961.    dc.b      '                      More HELP? ',10,0
  1962. HelpMsg2
  1963.    dc.b      10,' Result               Command      Alternates ',10,10
  1964.    dc.b      ' Change TAB Size      TAB                     (Default is 8)',10
  1965.    dc.b      ' Toggle FORMAT mode   F                       (Word Wrap)',10
  1966.    dc.b      ' Search for String    /                       (Case Sensitive)',10
  1967.    dc.b      ' Search for String    .                       (NOT Case sensitive) ',10
  1968.    dc.b      ' Next Occurrence      N                       (Of previous String)',10
  1969.    dc.b      ' Move N% into file    %N                      (where N = number)',10
  1970.    dc.b      ' Call your Editor     E                       (Def in ENV:Editor)',10
  1971.    dc.b      ' Print complete file  P            SHIFT-F7   (for WP users!)',10
  1972.    dc.b      ' Print screen only    PrtSc        F7         (or ANY * key)',10,10
  1973.    dc.b      ' UNCONDITIONAL EXIT   CTRL-C',10,10
  1974.    dc.b      '                      More HELP? ',10,0
  1975.    EvenPC
  1976.  
  1977.    end                           ; yup - that's IT!
  1978.