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 >
Wrap
Text File
|
1990-05-30
|
75KB
|
1,978 lines
*-----------------------------------------------------*
* CType Version 2.02 *
* *
* Copyright February 1990 - by Bill Nelson *
* Midnight Logic Software *
* *
* This is a FREELY REDISTRIBUTABLE 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 2.02 00:00:01 10/05/90 *
* *
*-----------------------------------------------------*
PUR EQU 1
WBC EQU 1 ; will need console if from WB
REQ EQU 1 ; want pure code, Req startup
VS EQU 1300 ; amount of variable space needed
; alloc'd in ReqPurStart.ASM
bra Start ; Jump into ReqPurStart.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
NewFile EQU 9
SizeIt EQU 10
ScrollR EQU 11
ScrollL EQU 12
ChangeTab EQU 13
Next EQU 14
*** Variables as offsets from a5 ***
LineBuff EQU 0 ; each line as output (400 chars)
KeyBuff EQU 400 ; filename (80 chars)
Control EQU 480 ; user requests etc (36 chars)
CBuff EQU 516 ; 1 char user inputb (4 chars)
FileReq EQU 520 ; PTR to FilReq struct LONG
FilePTR EQU 524 ; PTR to File LONG
FileLok EQU 528 ; PTR to FileLok LONG
fib_PTR EQU 532 ; PTR to fib_struct memory LONG
FileMemBuf EQU 536 ; PTR to filebuff memory LONG
FileChars EQU 540 ; Number of chars read LONG
FileSize EQU 544 ; FileSize LONG
EdNum EQU 548 ; Editor entry size LONG
EdPTR EQU 552 ; Editor entry file PTR LONG
PRTFile EQU 556 ; PRT file handle LONG
CharCount EQU 560 ; PTR to char to read in Buf LONG
LinePtr EQU 564 ; PTR to start of line LONG
RawHnd EQU 568 ; raw window handle LONG
pf_PTR EQU 572 ; PTR to Pref struct LONG
FileNm EQU 576 ; PTR to filename LONG
OldDir EQU 580 ; LOCK on old directory LONG
SrchOK EQU 584 ; "was valid Search" flag LONG
EndLine EQU 588 ; end of current line LONG
CharCounter EQU 592 ; charcounter LONG
ColTotal EQU 696 ; total columns LONG
EOL EQU 600 ; place EOL last found at LONG
NumLines EQU 604 ; display lines avail LONG
NumFiles EQU 608 ; num files specified LONG
CurrentFile EQU 612 ; number of current file LONG
CurPosn EQU 616 ; current position in file LONG
LastPosn EQU 620 ; last position in file LONG
PageBot EQU 624 ; current page bottom LONG
PageTop EQU 628 ; current page TOP LONG
HereNow EQU 632 ; midline posn LONG
StartLine EQU 636 ; start of above line LONG
HunFileSize EQU 640 ; 1/100 of filesize WORD
MUSTFormat EQU 642 ; MUST FORMAT flag BYTE
FormatMode EQU 643 ; State of format mode BYTE
IsMultiArg EQU 644 ; flag "in multi-arg mode" BYTE
RowSizeChg EQU 645 ; num extra rows BYTE
ColSizeChg EQU 646 ; num extra cols BYTE
LaceTogl EQU 647 ; whether interlaced BYTE
EndFlag EQU 648 ; EOF flag BYTE
TopFlag EQU 649 ; TOF flag BYTE
SmallFile EQU 650 ; "is small file" flag BYTE
SrchType EQU 651 ; "type of last search" flag BYTE
PrtScFlag EQU 652 ; "print screen" flag BYTE
TabSize EQU 653 ; user tabsize preference BYTE
SmallWindow EQU 654 ; whether undersize window BYTE
RawName EQU 655 ; OpenWin string (85 chars)
Wide EQU 662 ;
High EQU 666 ;
FName EQU 677 ; place to jam in file's name
PosPrompt EQU 746
PromptPos EQU 747 ; prompt string (78 chars)
CurPos EQU 756
KByteTot EQU 766
ModeMarker EQU 787
SPosPrompt EQU 832 ; SHORT prompt string (24 chars)
SPromptPos EQU 833 ;
DirBuff EQU 856 ; storage for DIR string
FileBuff EQU 988 ; storage for FILE string
PathName EQU 1020 ; storage for concat of above
TextReq EQU 1182 ; TextRequester struct
GetLong EQU 1228 ; GetLongStruct
GetString EQU 1262 ; GetStringStruct
; TOTAL of 1298 bytes
; EQU'd above for
; startup to Alloc correctly
EvenPC
*** The PROGRAM (at last!) ***
_Main
lea TextReq(a5),a0
move.w #$ffff,TR_KeyMask(a0); set requester to hot keys
move.w #3,TR_textcolor(a0)
move.b #8,TabSize(a5) ; initial setting!
move.l EndFromWB(a5),d0 ; was this started from WB
beq.s CLIEntry ; no, do the CLI stuff
move.l WBMsg(a5),a0 ; yes, set WBMsg up for offset access
move.l sm_NumArgs(a0),d3 ; how many args were provided
subq #1,d3 ; decrement down to number of FILES
beq.s NoArgs ; were no files, set CurrentDir & call request
move.l d3,NumFiles(a5) ; save number of files requested
move.l #1,CurrentFile(a5) ; and start on first one...
bra NextWBArg
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(a5) ; CType (and save where we were)
bra.s NoCLIArgs
CLIEntry
move.l CmdLen(a5),d0 ; Check if user entered filename
cmpi.b #1,d0 ; on the command line
beq.s NoCLIArgs ; if not, exit with explanation
move.l Command(a5),a1 ; check if ? is parameter
cmpi.b #'?',(a1) ;
beq.s Usage
move.l Command(a5),a0 ; set File buffer to match
lea FileBuff(a5),a1
bsr CopyString
move.l Command(a5),d1 ; or set it up for CheckExists
move.l d1,FileNm(a5) ; and store pointer for later access
move.l #1,NumFiles(a5) ; number of files to display
move.l #1,CurrentFile(a5) ; and start off on first one
bra.s GoGetIt
Usage
TxtReq UseTxt(pc),ResumeTxt(pc)
NoCLIArgs
bsr GetFileName ; and get filename from user (?)
GoGetIt
bra OpenFile
UseTxt
dc.b 10,' Enter an (optional) filename ',10
dc.b 10,' or just start the program up! ',0
EvenPC
NextWBArg
Zero d2 ; clear out d2
move.l CurrentFile(a5),d0 ; num of current file as counter
OffSetLoop
add.l #wa_SIZEOF,d2 ; add size of WBArg in d2, as offset to arg
subq #1,d0 ; decrement cur file counter
bne.s OffSetLoop ; not on it yet - more offset needed
move.l WBMsg(a5),a0 ; yes, set WBMsg up for offset access
move.l sm_ArgList(a0),a2 ; setup arglist for offset access
move.l 0(a2,d2),d1 ; ptr to directory lock into d1
DosCall CurrentDir ; change to directory of specified file
move.l d0,OldDir(a5) ; and save where we came from
move.l wa_Name(a2,d2),d1 ; put PTR to filename in d1
move.l d1,FileNm(a5) ; and store for opening file after getting lock
move.l d1,a0
lea FileBuff(a5),a1 ; and copy Filename into buffer for title
bsr CopyString
bra OpenFile ; and skip to the Openfile routine
GetFileName
move.l FileReq(a5),d0 ; already HAVE one?
bne.s GetFileAgain ; yup - DON'T start another!
AllocPubMem #frq_SIZEOF ; get memory for filerequester
tst.l d0
beq MemFail
move.l d0,FileReq(a5) ; store PTR to struct
move.l d0,a0
lea DirBuff(a5),a1
move.l a1,frq_Dir(a0) ; ptr to buff for directory
lea FileBuff(a5),a1
move.l a1,frq_File(a0) ; ptr to buff for filename
lea PathName(a5),a1
move.l a1,frq_PathName(a0) ; ptr to buff for complete pathname
GetFileAgain
move.l FileReq(a5),a0 ; put it in a0
move.l #0,frq_Flags(a0) ; clear flags
lea ReqTitle(pc),a1 ; give it a title
move.l a1,frq_Title(a0) ;
move.w #40,frq_numlines(a0)
move.w #3,frq_dirnamescolor(a0)
move.w #2,frq_devicenamescolor(a0)
or.l #FRQEXTSELECTM!FRQCACHINGM!FRQLOADINGM,frq_Flags(a0)
ReqCall FileRequester ; and call it up
tst.l d0 ; was it CANCELled?
beq GoNow ; yes - wants out...
move.l FileReq(a5),a2 ; or find out what
move.l frq_ExtendedSelect(a2),d1
beq.s NoExtend ; no extend select - 1 file only
NumFilesSelect
move.b #1,IsMultiArg(a5) ; we are in Multi-Arg mode
move.l d1,a2 ; First ESSStruct in a2
Zero d2 ; start counter at zero
1$
move.l es_NextFile(a2),a2 ; get next structure
addq #1,d2 ; add 1 to counter
cmpi.l #0,a2 ; is this link ptr zero?
bne.s 1$ ; nope? do it again
move.l d2,NumFiles(a5) ; yup - counter = # of files
move.l #1,CurrentFile(a5) ; and we start on first file
MultiArgs
move.l CurrentFile(a5),d2 ; current file is?
move.l FileReq(a5),a0 ; get FileReq Struct
move.l frq_ExtendedSelect(a0),a2
subq #2,d2 ;
blt.s BuildName ; was first file, HAVE right struct
GetStruct
move.l es_NextFile(a2),a2 ; get next struct
cmpi.l #0,a2 ; check if zero (counter wrong somehow?)
beq.s BuildName
dbra d2,GetStruct ; do again if counter not reached
BuildName
lea DirBuff(a5),a0 ; copy DIRname into Pathname
lea PathName(a5),a1
bsr CopyString
lea PathName(a5),a0
subq #1,a1 ; back up over null
cmp.l a0,a1 ; Dir name was null?
beq.s NoSep
cmp.b #':',-(a1) ; was last char of dir a ':' ?
bne.s 1$
addq #1,a1 ; return a1 to correct posn
bra.s NoSep ; no other sep needed
1$
addq #1,a1 ; return a1 to correct posn
move.b #'/',(a1)+ ; put in dir separator
NoSep
lea es_FileName(a2),a0 ; get file name
bsr CopyString ; into PathName for open
lea es_FileName(a2),a0
lea FileBuff(a5),a1 ; and into FileBuff
bsr CopyString ; so title reflects right file!
bra.s SetName
NoExtend
move.b #0,IsMultiArg(a5) ; no multiargs active
move.l #1,NumFiles(a5) ; number of files we know of
move.l #1,CurrentFile(a5) ; and this file's number
SetName
lea PathName(a5),a0 ; load name
move.l a0,d1 ; into d1 for _CheckExists
move.l d1,FileNm(a5) ; and store for later
rts
*** Open the file ***
OpenFile
tst.l d1
beq NextOrExit
PushReg d1
bsr _ShutDown
PullReg d1
bsr _CheckExists ; try for Lock on file
tst.l d0
beq.s NoFileFound ; no exist - I guess we lost it :-(
move.l d0,FileLok(a5) ; stash it for other uses!
bsr _GetFileSize ; find out the file size - how much MEM?
tst.l d0
beq OpenTrouble ; couldn't get the filesize (mem?)
move.l d0,FileSize(a5) ; store for later - also in d0 to
AllocPubMem d0 ; alloc enough mem for file buffer
tst.l d0 ; See if call made it
beq MemFail ; or leave...
move.l d0,FileMemBuf(a5) ; otherwise, store PTR to memory
; (automatically LONG aligned by EXEC)
move.l FileNm(a5),d1 ; put PTR to filename in d1
move.l #MODE_OLDFILE,d2 ; for reading
DosCall Open
tst.l d0 ; see if a handle was returned (success)
beq.s OpenTrouble ; No? Skip the rest
move.l d0,FilePTR(a5) ; or store handle if successful
bsr _SetUpStrings ; copy our modifiable strings to work area
bra CalcKBytes ; and get on with it
NoFileFound
TxtReqCt NoFileMsg(pc),ResumeTxt(pc),FileBuff(a5)
bra NextOrExit
NoFileMsg
dc.b 10,' Could not locate file ',10,10,' <%s> ',0
EvenPC
OpenTrouble
TxtReq OpenTroubleMsg(pc),ResumeTxt(pc)
bra.s FixFileLok
OpenTroubleMsg
dc.b 10,' Could not open file ',10,0
EvenPC
MemFail
TxtReq MemFailMsg(pc),ResumeTxt(pc)
bra.s FixFileLok
MemFailMsg
dc.b 10,' Not enough memory! ',10,0
EvenPC
FixFileLok
move.l FileLok(a5),d1 ; get the lock
beq.s 1$ ; wasn't one, skip it!
DosCall UnLock ; free it up
1$
move.l #0,FileLok(a5) ; and zero the space
bra NextOrExit
*** Various Calculations for later ***
CalcKBytes
Zero d0 ; clear out the regs I use here
Zero d1 ;
move.l FileSize(a5),d0 ; total filesize into d0
cmpi.l #9999,d0 ;
ble.s 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.s 1$ ; if less, skip this next
addq #1,d1 ; round up if greater than 1/2K
1$
lea KByteTot(a5),a0 ; stuff it into string for end of page
bsr _ASCIIConv ; in ASCII :-)
bra.s CalcForPercent
SmallerFile
move.l d0,d1 ; put filesize in d1
lea KByteTot(a5),a0 ; stuff it into string for end of page
bsr _ASCIIConv ; in ASCII
addq #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(a5),d0 ; get filesize/100
divu #100,d0 ; to make % calculation fit in WORD
move.w d0,d1 ; thus allowing DIVU to work!
beq.s 1$ ; unless is ZERO result! (no GURU 5 please!)
move.w d1,HunFileSize(a5) ; store it for calculation done at end of page
bra.s GetThePrefs
1$
move.w #1,HunFileSize(a5) ; never less than 1 for divisor!
move.b #1,SmallFile(a5) ; 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(a5),d1 ; change in width (pixels)
addi #640,d1 ; add in 640
lea Wide(a5),a0 ; and get the ASCII equivalent
bsr _ASCIIConv ; and write it into the string we later
lea Wide(a5),a0 ; pass to the OPEN call for a window
move.b #'/',(a0) ; add in the '/' in the right place!
Zero d1
move.b RowSizeChg(a5),d1 ; same thing for height (pixels)
addi.l #200,d1 ; add the standard height
move.b LaceTogl(a5),d0 ; interlace on?
beq.s 1$ ; no, we have the value
add.l d1,d1 ; yes. multiply by 2
1$
lea High(a5),a0 ; and stuff it in the string as well
bsr _ASCIIConv ; with the same "brute force" technique
lea High(a5),a0
move.b #'/',(a0) ; with the / separator
SetUpTitle
lea FileBuff(a5),a0 ; PTR to filename in a0
move.l a0,a2 ; and in a2 for difference
lea FName(a5),a1 ; and destination for string in a1
Zero d1 ; initialize counter
LengthChk
addq #1,d1 ; increment counter
tst.b (a2)+ ; look for end of string
bne.s LengthChk
cmp #24,d1 ; was it more than 24 chars
ble.s MoveName ; nope - just copy it up
MvLeft
subq.l #6,a1 ; back up over "File: " entry
MoveName
bsr CopyString ; copy the string up
move.b #' ',-(a1) ; put space over the zero byte
*** Open a window for I/O (of size we now know) ***
OpenWin
lea RawName(a5),a0
move.l a0,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(a5) ; got it, store it for output later
DosPrt RawHnd(a5),SetMouse(pc)
bsr.s CalcCols
bra ReadFile
CalcCols
PushReg a2-a3
GetResponse
DosPrt RawHnd(a5),GetWinStat(pc)
move.l #1000000,d2 ; wait 1 sec for incoming
move.l RawHnd(a5),d1 ; in our window
DosCall WaitForChar ; we don't BUSY LOOP looking, but
DosRd RawHnd(a5),KeyBuff(a5),#20 ; we want all that's useful
lea KeyBuff(a5),a0
move.b (a0)+,d0 ; get first char
cmpi.b #$9b,d0 ; is it CSI?
bne GetResponse
move.b (a0)+,d0 ; get a char
cmpi.b #'1',d0 ; is it a 1?
bne GetResponse
move.b (a0)+,d0 ; get a char
cmpi.b #';',d0 ; is it a separator
bne GetResponse
move.b (a0)+,d0 ; get a char
cmpi.b #'1',d0
bne GetResponse
move.b (a0)+,d0 ; get a char
cmpi.b #';',d0
bne GetResponse
move.l a0,a2 ; made it this far, must be Status report!
lea PromptPos(a5),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.s MarkIt ; first parameter complete
cmpi.b #' ',d0 ; space after end of 2nd parameter
beq.s 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!)
addq #1,a3 ; so we can convert them to values
move.b #0,(a0) ; put a null after 1st parameter
lea KeyBuff(a5),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 convert it to value
subq #2,d1 ; less 1 for Prompt, and 1 for DBRA!
ble GetResponse ; if 0 or less, wait for another event :-)
move.l d1,NumLines(a5) ; 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(a5) ; we have number of useable columns
cmp.l #61,d1 ; smaller than normal prompt string?
bge.s 1$
move.b #1,SmallWindow(a5) ; mark for SMALL prompt only!
bra.s 2$
1$
move.b #0,SmallWindow(a5) ; mark as big enough window
2$
lea PromptPos(a5),a0 ; copy positioning to other
lea SPromptPos(a5),a1 ; prompt string
move.b (a0)+,(a1)+
move.b (a0)+,(a1)+
PullReg a2-a3 ; restore our regs
rts
*** Read the file in ***
ReadFile
DosRead FilePTR(a5),FileMemBuf(a5),FileSize(a5)
tst.l d0
bgt.s KeepGoing ; greater than 0, is length of useful file
move.l FilePTR(a5),d1 ; or shut it down.
DosCall Close
move.l FileLok(a5),d1 ; better not forget to UNLOCK the file!
DosCall UnLock ; so we do it now...
move.l #0,FileLok(a5) ; and clear the storage area
TxtReq NoReadFileMsg(pc),ResumeTxt(pc)
bra NextOrExit
NoReadFileMsg
dc.b 10,' File unreadable or empty ',10,0
EvenPC
KeepGoing
move.l d0,FileChars(a5) ; tells us how many were read
move.l FilePTR(a5),d1 ; STILL no trust :-)
DosCall Close ; won't need it again
move.l FileLok(a5),d1 ; better not forget to UNLOCK the file!
DosCall UnLock ; so we do it now...
move.l #0,FileLok(a5) ; and clear the storage (for later use!)
*** Check file format ***
FormatCheck
move.l FileMemBuf(a5),a2 ; Start of buffer
move.l FileChars(a5),a3 ; Number of chars it contains
adda.l a2,a3 ; End of buffer now in a3
Zero d6 ; track char/line
InitScan
move.b (a2)+,d0 ; move byte to d0, and increment a2
cmpi.b #10,d0 ; is LF character?
beq.s 1$
cmpi.b #13,d0 ; is CR character?
bne.s 2$
1$
Zero d6
bra.s InitScan
2$
cmpi.b #$E,d0 ; is SHIFT OUT char?
beq.s IsBinary ; likely binary file
cmpi.b #127,d0 ; is highbit set?
bgt.s IsBinary ; likely not readable
addq #1,d6 ; up count of chars this line
cmpi #512,d6 ; more than 512 chars?
bgt.s LineTooLong ; FORCE format mode!
cmpa.l a2,a3
bgt InitScan
move.b #0,MUSTFormat(a5) ; made it this far - mark as OK
bra DisplayFile
LineTooLong
move.b #1,MUSTFormat(a5) ; set both flags
move.b #1,FormatMode(a5)
Zero d7 ; clear any format offset!
lea ModeMarker(a5),a0
move.b #'F',(a0)
bra.s DisplayFile
IsBinary
TxtReq NonASCIIMsg(pc),NoTxt(pc),YesTxt(pc)
tst.l d0
bne InitScan ; keep testing (for long lines!)
bra NextOrExit
NonASCIIMsg
dc.b 10,' Non ASCII characters found ',10,10,' Attempt to display anyway? ',10,0
EvenPC
*** Display the file ***
DisplayFile
move.b #1,TopFlag(a5) ; mark us at TOF
Zero d7
move.l FileMemBuf(a5),a2 ; set a2 to start of buffer
move.l a2,PageTop(a5)
Pages
bsr.s _PageSetup
bsr.s _PageLoop
bra.s ReadingTime
_PageSetup
lea LineBuff(a5),a4 ; start of Buffer in a4
move.l a4,LinePtr(a5) ; and in LinePtr variable
move.l NumLines(a5),d3 ; number of lines per page
move.l ColTotal(a5),d2 ; number of columns per page
moveq #12,d0
bsr _WrChar ; Clear the screen
move.l a2,PageTop(a5)
rts
_PageLoop
Zero d6 ; set chars to display at zero
bsr _BuildLine ; build normal text line
bsr _OutputLine ; dump it to screen
dbra d3,_PageLoop ; loop till NumLines on the screen
rts
ReadingTime
cmp.b #1,SmallWindow(a5) ; is this an underwidth window?
bne.s 1$ ; nope - do the prompt stuff
DosPrt RawHnd(a5),CursorOff(pc)
DosPrt RawHnd(a5),SPosPrompt(a5)
bra.s GetAKey
1$
cmp.b #1,SmallFile(a5) ; was this a small file?
beq.s ForceIt ; yes, skip the calcs!
move.l a2,d1 ; put current "position" in d1 for calcs
sub.l FileMemBuf(a5),d1 ; subtract start of buffer from d1
divu HunFileSize(a5),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.s Prompt ; file is under 1000 bytes)
ForceIt
moveq #100,d1 ; if it is, make it 100
Prompt
lea CurPos(a5),a0 ; force feed it to string PosPrompt
bsr _ASCIIConv
DosPrt RawHnd(a5),CursorOff(pc)
DosPrt RawHnd(a5),PosPrompt(a5)
GetAKey
bsr _KeyHit ; wait for a keystroke (sub returns action codes)
tst.l d0 ; see if user wants out
beq GoNow ; and exit if so
ReEntry ; entry point if from PrtScreen
cmpi.b #Up,d0 ; now we check all supported keystrokes
bne.s 2$
cmpa.l a2,a3 ; at bottom?
bgt.s 1$
bsr _BOF ; redisplay as BOF
bsr _PageSetup
bsr _PageLoop
1$
bra _BackLine ; now back up a line
2$
cmpi.b #Down,d0
bne.s 3$
bra _ForLine ; go ahead a line
3$
cmpi.b #Top,d0
bne.s 4$
bsr _TOF ; jump to top
bra Pages
4$
cmpi.b #Bottom,d0
bne.s 5$
bsr _BOF ; jump to bottom
bra Pages
5$
cmpi.b #Again,d0
bne.s 6$
move.l PageTop(a5),a2 ; just redisplay with current params
bra Pages
6$
cmpi.b #Assist,d0
bne.s 7$
bsr _Help ; call HELP requester
bra GetAKey
7$
cmpi.b #PageUp,d0
bne.s 8$
bsr _BackPage ; back it up 1 page if possible
bra Pages
8$
cmpi.b #PageDown,d0
bne.s 9$ ; forward a page
bra Pages
9$
cmpi.b #SizeIt,d0 ; user requested size change?
bne.s 10$
beq _Resize ; do it
10$
cmpi.b #ScrollR,d0 ; Scroll it Right
bne.s 11$
beq _ScrollRight
11$
cmpi.b #ScrollL,d0 ; Scroll it Left
bne.s 12$
beq _ScrollLeft
12$
cmpi.b #ChangeTab,d0 ; user requested tab size change?
bne.s 13$
beq _TabSize ; do it
13$
cmpi.b #Next,d0 ; hit ESC - wants another file?
bne Pages
*** Ways Out of program ***
NextOrExit
move.l NumFiles(a5),d0 ; load it with numfiles
move.l CurrentFile(a5),d1 ; and our current file
sub.l d1,d0 ;
bgt.s GetAnother ; more to go...
AskAnother
move.b #0,IsMultiArg(a5) ; we know we aren't in middle of multi
TxtReq AnotherMsg(pc),NoTxt(pc),YesTxt(pc)
tst.l d0
beq.s GoNow
bra.s GetNewName
AnotherMsg
dc.b 10,' Display another file? ',10,0
EvenPC
GetNewName
bsr GetFileName ; and get another name
bra OpenFile
GetAnother
add.l #1,CurrentFile(a5) ; increment number we're displaying
move.b IsMultiArg(a5),d1 ; we in multiargs?
beq NextWBArg ; nope. get next WB arg
bsr MultiArgs ; yup - get the name
bra OpenFile ; and on we go
GoNow
move.l EndFromWB(a5),d1 ; see if we started from WB
beq.s GoneNow ; no, normal shutdown
move.l OldDir(a5),d1 ; yes, return our CurrentDir as was
DosCall CurrentDir ; before we go and then
GoneNow
bsr.s _ShutDown ; clean up everything that Startup doesn't
bsr.s _ShutDown2 ; yes, EVERYTHING
Zero d0
rts ; GONE
Error
bsr.s _ShutDown
bsr.s _ShutDown2
moveq #20,d0 ; Set Error returncode
rts
*** Subroutines ***
_ShutDown
ReturnMem
move.l FileMemBuf(a5),d0 ; ptr to buffer
beq.s CloseRaw ; if not ptr... (!)
move.l d0,a1
move.l FileSize(a5),d0
SysCall FreeMem
move.l #0,FileMemBuf(a5) ; and CLEAR it!
CloseRaw
move.l RawHnd(a5),d1 ; load Window handle into d1
tst.l d1 ; if its NULL, we didn't get it open
beq.s Shut ; so don't TRY to close it!
DosCall Close
move.l #0,RawHnd(a5) ; clear ptr too!
Shut
rts
_ShutDown2
move.l FileReq(a5),d0 ; ptr to FileReq struct
beq.s Shut2
move.l d0,a0
ReqCall PurgeFiles ; release all assoc mem
move.l FileReq(a5),a1
move.l #frq_SIZEOF,d0 ; and the FileReq mem itself
SysCall FreeMem
move.l #0,FileReq(a5) ; no ptr now!
Shut2
rts
_SetUpStrings
lea RawName1(pc),a0 ; PTR to string in a0
lea RawName(a5),a1 ; PTR to where it goes
bsr.s CopyString ; copy it up
lea PosPrompt1(pc),a0 ; same again
lea PosPrompt(a5),a1
bsr.s CopyString
lea SPosPrompt1(pc),a0 ; same again
lea SPosPrompt(a5),a1 ; and fall through to go on back
CopyString
move.b (a0)+,(a1)+ ; null-terminated strings are easy
bne CopyString ; to move around in 680x0 asm!
rts
_CheckExists ; enter with filePTR in d1
moveq #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.s GotFileSize ; no memory, exit with 0 in d0
move.l d0,fib_PTR(a5) ; got mem, store PTR for later
move.l d0,d2 ; and set it as 1st parameter with
move.l FileLok(a5),d1 ; other parameter for Examine()
DosCall Examine
tst.l d0 ; Boolean return
beq.s CloseFibMem ; can't imagine WHY, but give back mem!
move.l fib_PTR(a5),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(a5),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.s GotPrefs ; we didn't get it, d0 has "fail" return code
move.l d0,pf_PTR(a5) ; 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.s ClosePFMem ; can't imagine WHY this would happen, but...
move.l pf_PTR(a5),a1 ; set up offset access for what we wanted!
move.b pf_RowSizeChange(a1),RowSizeChg(a5)
move.b pf_ColumnSizeChange(a1),ColSizeChg(a5)
move.b pf_LaceWB(a1),LaceTogl(a5)
moveq #1,d0 ; we got what we wanted, so return "success"
ClosePFMem
PushReg d0 ; store return code for now
move.l pf_PTR(a5),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
_BuildLine
addq #1,d6 ; up count of chars this line
move.b (a2)+,d0 ; get next character
cmp.b #12,d0
beq.s EOLine ; was CLS, treat as LF
cmpi.b #$E,d0
beq.s EOLine ; was SHIFT-OUT - pretend was EOL
cmpi.b #10,d0 ; (don't want ALT charset)
beq.s EOLine
cmpi.b #13,d0
beq.s CRatEOL
cmp d6,d2 ; end of displayable yet?
bne.s 1$ ; nope - skip checks
cmpi.b #1,FormatMode(a5) ; is format mode active?
beq.s WordWrap ; yup - go do word wrap
1$
cmp.b #9,d0 ; is it a TAB char?
beq HandleTab ; if so, pop spaces in buffer
move.b d0,(a4)+
CheckEOF
cmp.l a2,a3 ; compare current posn (a2) w/ buffer end (a3)
bgt _BuildLine ; back to get next character
bra GetOut ; or leave if EOF
CRatEOL
move.b (a2)+,d0 ; check next character in string
cmpi.b #10,d0 ; for an LF char (maybe from PC?)
beq.s EOLine ; yup - then just add LF to buffer
subq #1,a2 ; nope- back up so char not missed
EOLine
move.b #10,(a4)
rts
WordWrap
cmpi.b #32,d0 ; we on a space char?
beq.s WrapHere ;
cmpi.b #9,d0 ; was TAB char
beq.s EOLine ; no need to expand it!
subq #1,a2 ; return a2 to char we have
move.l a2,EndLine(a5) ; store this posn if needed
move.l d6,CharCounter(a5) ; and the char counter
move.l a4,d1 ; and the buffer posn
WrapLoop
subq #1,d6 ; back up char counter
cmpi.b #1,d6 ; at beginning of line?
beq.s SkipWrap ; yup...
move.b -(a2),d0 ; back up a char
cmpi.b #32,d0 ; got a space yet?
beq.s DoWrap ; use as new EOLine
cmpi.b #9,d0 ; was it a tab char?
beq.s DoWrap ; will do as a place to wrap
subq #1,a4 ; back up ptr into buffer
bra.s WrapLoop ; try next char back
SkipWrap
move.l EndLine(a5),a2 ; put a2 back at end of line
move.l CharCounter(a5),d6 ; return d6 to num of chars
move.l d1,a4 ; and posn in buffer
subq #1,d6
bra EOLine ; pop it out
DoWrap
subq #1,a4 ; back up buff ptr
move.b #10,(a4) ; pop in EOL char
addq #1,a2 ; return a2 to char after break
rts ; back to display line
ReplaceTab
move.b #10,-(a4) ; put LF in buffer
rts
WrapHere
move.b (a2)+,d0 ; check next char
cmpi.b #10,d0 ; is it a LF?
beq EOLine ; done here
cmpi.b #13,d0 ; is it a CR?
beq CRatEOL ; do the check
cmpi.b #32,d0 ; is another space?
beq.s WrapHere ; try again
subq #1,a2 ; or back up so char not missed
bra EOLine ; and stuff EOL in buffer
HandleTab
PushReg d3-d4 ; save working regs
Zero d3 ; and clean 'em out
Zero d4 ;
move.b TabSize(a5),d4 ; set up tab size for later
beq.s 2$ ; bypass divide by zero possibility!
move.l d6,d3 ; current "char pos'n used" counter
subq #1,d3 ; was "pre-incremented" in build loop
add d4,d3 ; add "max effect" of tab
divu d4,d3 ; divide by tabsize
clr.w d3 ; to get the remainder
swap d3 ;
sub d3,d4 ; subtract remainder from "max effect"
subq #1,d4 ; one off for dbra
add d4,d6 ; and add "actual effect" to chars used
cmp.b #1,FormatMode(a5) ; is format mode in use?
bne.s 1$
cmp.l d6,d2 ; are we out of chars?
bge.s 1$ ; nope
move.b #10,(a4)+ ; yup - put EOL in buffer
sub d4,d6 ; and remove tab effect on chars to display
bra.s 2$
1$
move.b #' ',(a4)+
dbra d4,1$
2$
PullReg d3-d4 ; restore working registers
bra CheckEOF
GetOut
cmpi.b #1,d6
bne.s 1$
Zero d6
rts
1$
move.b #10,(a4)+
rts
_OutputLine
tst.l d7 ; any scroll Offset?
beq.s 3$ ; nope - ignore
sub.l d7,d6 ; yes, that many fewer to display
bgt.s 2$ ; does that make it 0 or less
1$
moveq #10,d0
bsr _WrChar ; just write a LF
bra.s 5$ ; and skip other output
2$
add.l d7,LinePtr(a5) ; add offset into buffer start addr
3$
cmp.l d2,d6 ; compare allowable chars with # to output
ble.s 4$ ; allowable number
move.l d2,d6 ; or MAKE it allowable number
DosPrint RawHnd(a5),LinePtr(a5),d6
moveq #10,d0
bsr _WrChar
bra.s 5$
4$
DosPrint RawHnd(a5),LinePtr(a5),d6
5$
lea LineBuff(a5),a4
move.l a4,LinePtr(a5)
rts
*** Get user requests ***
_KeyHit
move.l #1000000,d2 ; wait 1 sec for reader to hit a key
move.l RawHnd(a5),d1 ; in our window
DosCall WaitForChar ; we don't BUSY LOOP looking, but
tst.l d0
beq _KeyHit ; we are determined to get one!
DosRd RawHnd(a5),Control(a5),#36 ; check it out for user's requests
move.b Control(a5),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 #'?',d0 ; just a ? :-)
beq Help
cmpi.b #'q',d0
beq WantsNext
cmpi.b #'Q',d0
beq WantsNext
cmpi.b #27,d0 ; <ESC> char
beq WantsNext
cmpi.b #3,d0 ; <CTRL-C> char
beq WantsOut
cmpi.b #'r',d0
beq ScR
cmpi.b #'R',d0
beq ScR
cmpi.b #'6',d0 ; <RIGHT ARROW> key on Numeric pad
beq ScR
cmpi.b #'l',d0
beq ScL
cmpi.b #'L',d0
beq ScL
cmpi.b #'4',d0 ; <LEFT ARROW> key on Numeric pad
beq ScL
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 #9,d0
beq Tab
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
cmpi.b #'f',d0
beq FMT
cmpi.b #'F',d0 ; toggle format mode
beq FMT
bra _KeyHit ; anything else we'll ignore!
ExtendKey
move.b Control+1(a5),d0 ; get next character
cmpi.b #'2',d0 ; MOUSE EVENT?
beq Mouse
cmpi.b #'1',d0 ; RESIZE EVENT?
beq.s RSize
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 #'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 ScR
cmpi.b #'D',d0 ; LEFT ARROW?
beq ScL
cmpi.b #' ',d0 ; LEFT or RIGHT ARROW (shifted) ?
beq.s ArrowChk
bra _KeyHit ; don't WANT to know what else user hit!
ArrowChk
move.b Control+2(a5),d0
cmpi.b #'@',d0 ; RIGHT ARROW? (shifted of course)
beq BOF
cmpi.b #'A',d0 ; LEFT ARROW? (shifted)
beq TOF
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...
RSize
move.b Control+2(a5),d0
cmpi.b #'2',d0
beq ReSize
cmpi.b #'6',d0 ; was it shifted F7?
beq PRT
bra _KeyHit
Mouse
move.b Control+5(a5),d0
cmpi.b #'1',d0 ; was it a button?
bne.s _NoGo ; no - ignore it
move.b Control+6(a5),d0
cmpi.b #'0',d0 ; was it a button?
bne.s _NoGo ; no - ignore it
move.b Control+7(a5),d0
cmpi.b #'4',d0
bne.s _NoGo ; not it
LMB
bra ForPage ; for the moment - advance a page!
_NoGo
bra _KeyHit
FMT
cmp.b #1,MUSTFormat(a5) ; Is it LOCKED into format?
beq.s CantChange
cmp.b #1,FormatMode(a5) ; is already IN format mode?
beq.s 1$
move.b #1,FormatMode(a5) ; nope - set it there
lea ModeMarker(a5),a0 ; change the marker in the prompt
move.b #'F',(a0)
Zero d7 ; cancel any OFFSET value
bra.s 2$
1$
move.b #0,FormatMode(a5)
lea ModeMarker(a5),a0 ; change marker in the prompt
move.b #'N',(a0)
2$
moveq #Again,d0 ; redisplay the page with new params
rts
CantChange
TxtReq CantChangeMsg(pc),ResumeTxt(pc)
moveq #Again,d0
rts
CantChangeMsg
dc.b 10,' Cannot change mode on this file ',10,0
EvenPC
Help
moveq #Assist,d0 ; pass "action code" in d0 to calling routine
rts
ForPage
cmpa.l a2,a3
ble _KeyHit
move.b #0,TopFlag(a5)
moveq #PageDown,d0
rts
BackPage
cmpi.b #1,TopFlag(a5) ; are we already at the top?
beq _KeyHit ; do nothing
moveq #PageUp,d0
rts
TOF
move.b #1,TopFlag(a5)
moveq #Top,d0
rts
BOF
move.b #0,TopFlag(a5)
moveq #Bottom,d0
rts
WantsNext
moveq #Next,d0
rts
ForLine
cmpa.l a2,a3
ble _KeyHit ; if EOF, do nothing
move.b #0,TopFlag(a5) ; not EOF, say NOT TOF :-)
moveq #Down,d0
rts
BackLine
cmpi.b #1,TopFlag(a5)
beq _KeyHit
moveq #Up,d0
rts
ReSize
move.l #SizeIt,d0
rts
ScR
cmp.b #1,FormatMode(a5) ; we in word wrap mode?
beq _KeyHit ; do nothing
moveq #ScrollR,d0
rts
ScL
cmp.b #1,FormatMode(a5) ; we in word wrap mode?
beq _KeyHit ; do nothing
moveq #ScrollL,d0
rts
Tab
moveq #ChangeTab,d0
rts
WantsOut
moveq #Quit,d0
rts
*** Act on User Requests! ***
_Help
TxtReq HelpMsg(pc),NoTxt(pc),YesTxt(pc)
tst.l d0
beq.s 1$
TxtReq HelpMsg2(pc),NoTxt(pc),YesTxt(pc)
tst.l d0
beq.s 1$
bra.s _Help
1$
rts
_BackOnePage
move.l NumLines(a5),d3 ; Numlines as loop counter
move.l ColTotal(a5),d2 ; number of columns per page
subq #1,a2 ; back up so ON EOL
addq #1,d3 ; no dbra here :-)
ScanBack
Zero d4 ; another counter (!)
move.l a2,EOL(a5) ; store current EOL
bsr.s _BackScan ; find previous EOL
cmpi.b #1,TopFlag(a5) ; we at the top already?
beq.s GoTOF ; yup - done this excercise!
addq #1,a2 ; step a2 past EOL char found
Zero d6 ; zero the count of chars to display
lea LineBuff(a5),a4 ; point to start of buffer
bsr _BuildLine ; build a display line
addq #1,d4 ; count times _BuildLine called
cmp.l EOL(a5),a2 ; are we back here?
bgt.s 2$ ; yup
1$
Zero d6 ; zero the count of chars to display
lea LineBuff(a5),a4 ; point to start of buffer
bsr _BuildLine ; build another..
addq #1,d4 ; keeping count
cmp.l EOL(a5),a2 ; back where we started yet?
ble.s 1$ ; nope - try again
2$
subq #1,a2 ; onto EOL char itself again
cmp.l d4,d3 ; compare lines taken with # to go
beq.s JustRight ; done!!
bgt.s NotEnough ; go for more
TooFar
sub.l d3,d4 ; get diff OTHER way round
subq #1,d4 ; less 1 for dbra
bsr.s _BackScan ; move on up
addq #1,a2 ; step past EOL char
1$
Zero d6 ; zero the count of chars to display
lea LineBuff(a5),a4 ; point to start of buffer
bsr _BuildLine ; step forward
dbra d4,1$ ; number of diff times
rts
NotEnough
sub.l d4,d3 ; reduce # lines to go
bsr.s _BackScan ; set a2 back where it worked
bra ScanBack ; and around again ..
JustRight
bsr.s _BackScan ; put a2 back where it worked
addq #1,a2 ; 1 char after EOL
GoTOF
rts
_BackScan
cmpi.b #10,-(a2) ; is char a LF?
bne.s 1$ ; yup - return OK
rts
1$
cmpi.b #13,(a2) ; is it a CR?
bne.s 3$ ; nope - what else?
addq #1,a2 ; is next character
cmpi.b #10,(a2) ; a LF?
beq.s 2$
subq #1,a2 ; nope - return a2
rts
2$
subq #1,a2 ; yup - return a2
bra.s _BackScan ; and act as if didn't exist
3$
cmpa.l FileMemBuf(a5),a2 ; are we past start of file?
bgt.s _BackScan ; nope - get next char
move.l FileMemBuf(a5),a2 ; yup - fix it
move.b #1,TopFlag(a5)
rts
_BackPage
move.l PageTop(a5),a2 ; back up ptr to start of this page
bsr _BackOnePage ; then up again, to show previous page
rts
_TOF
move.l FileMemBuf(a5),a2 ; back up a2 to start of whole thing
rts
_BOF
movea.l a3,a2 ; set a2 to end of buffer
bsr _BackOnePage ; then back up a display page
rts ; final page
_BackLine
move.l ColTotal(a5),d2 ; number of columns per page
subq #1,a2 ; put a2 ON EOL
moveq #1,d3 ; set counter for one, and borrow the
bsr ScanBack ; loop for here too :-)
move.l a2,PageBot(a5) ; store new page END
bsr _BackOnePage ; now set back full page
cmpa.l FileMemBuf(a5),a2 ; did we hit TOF?
ble.s SkipOutput ; better skip it!
DosPrt RawHnd(a5),ScrDnHome(pc)
move.l a2,PageTop(a5) ; mark new page top
move.l NumLines(a5),d3 ; number of lines per page
move.l ColTotal(a5),d2 ; number of columns per page
lea LineBuff(a5),a4 ; ptr to buffer
move.l a4,LinePtr(a5) ; and to start of chars to display
Zero d6 ; zero count of chars to display
bsr _BuildLine ; build line in buffer
bsr _OutputLine ; pump it out
move.l PageBot(a5),a2 ; restore new page END
bra ReadingTime ; and onward
SkipOutput
moveq #Top,d0 ; simulate "TOF" keystroke
bra ReEntry ; and continue
ScrDnHome
dc.b $9b,$54,$9b,'H',0 ; scroll down, and HOME cursor
EvenPC
_ForLine
DosPrt RawHnd(a5),ClrLn(pc)
lea LineBuff(a5),a4
move.l a4,LinePtr(a5)
move.l NumLines(a5),d3
move.l ColTotal(a5),d2 ; number of columns per page
Zero d6 ; zero Char counter
bsr _BuildLine ; build line
bsr _OutputLine ; display it
move.l a2,PageBot(a5) ; save where we are
bsr _BackOnePage
move.l a2,PageTop(a5) ; get new page TOP
move.l PageBot(a5),a2 ; back to bottom
bra ReadingTime
_PrevLine
move.l a2,HereNow(a5) ; mark where we are
bsr _BackScan ; find previous EOL
addq #1,a2 ; step 1 past it
PrevLoop
move.l a2,StartLine(a5) ; store start of logical line
lea LineBuff(a5),a4 ; set up for
move.l a4,LinePtr(a5)
move.l NumLines(a5),d3
move.l ColTotal(a5),d2
Zero d6
bsr _BuildLine ; building logical line
cmp.l HereNow(a5),a2 ; we now past point we found?
ble.s PrevLoop ; nope - build another
move.l StartLine(a5),a2 ; yep, return with start of line
rts
_ScrollRight
cmp.l #120,d7 ; less than 120 offset?
bge.s 1$
add #10,d7 ; OK - add 10 to it
1$
moveq #Again,d0 ; and redisplay the page
bra ReEntry
_ScrollLeft
tst.l d7
ble.s 1$ ; already at original left margin?
sub #10,d7
1$
moveq #Again,d0
bra ReEntry ; back to redisplay page
_TabSize
lea GetLong(a5),a0 ; get structure
lea TabTitle(pc),a1 ; give req a title
move.l a1,gl_titlebar(a0)
move.l #8,gl_defaultval(a0); 8 is the default tab size
move.l #2,gl_minlimit(a0) ; and our limits
move.l #10,gl_maxlimit(a0)
ReqCall GetLong
tst.l d0 ; if cancel, do nothing
beq.s NoChange
lea GetLong(a5),a0
move.l gl_result(a0),d0
move.b d0,TabSize(a5) ; only .b to our var
NoChange
moveq #Again,d0 ; redisplay with new settings
bra ReEntry
TabTitle
dc.b ' TAB Size: ',0
EvenPC
_Resize
move.l PageTop(a5),a2 ; set a2 back to current top of page
bsr CalcCols ; reset new page size
bra Pages ; and display new pagefull
*** Call the Editor ***
EDIT
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.s GetEditor ; OK - it exists
AskEditor
lea LineBuff(a5),a0
move.b #0,(a0)
lea GetString(a5),a0 ; load structure
lea EdReqTitle(pc),a1 ; with values we want
move.l a1,gs_titlebar(a0)
lea LineBuff(a5),a1
move.l a1,gs_stringbuffer(a0)
move.w #30,gs_stringsize(a0)
move.w #28,gs_visiblesize(a0)
move.w #0,gs_versionnumber(a0)
ReqCall NewGetString ; call requester for string
tst.l d0
beq EdTrouble ; didn't get a valid response
lea LineBuff(a5),a0 ; OK - so figure how long string is
Zero d0
GetEdLen
addq #1,d0
tst.b (a0)+
bne.s GetEdLen
subq #1,d0
bra.s CallEditor ; and go try to Execute() it
EdReqTitle
dc.b ' Editor Name: ',0
EvenPC
GetEditor
move.l d0,FileLok(a5) ; Lock in same place (not needed again)
lea EditName(pc),a0
move.l a0,d1
move.l #MODE_OLDFILE,d2 ; open up ENV:Editor and see what's there
DosCall Open
tst.l d0
bne.s ReadEdName ;
bra.s EdTrouble
ReadEdName
move.l d0,EdPTR(a5) ; store for closedown later
DosRd EdPTR(a5),LineBuff(a5),#79
tst.l d0 ; read only as big as our buffer
bne.s CallEditor ; if doesn't fit, won't find it!
bra.s EdTrouble
CallEditor
lea LineBuff(a5),a1 ; PTR to buff location
add.l d0,a1
move.b #' ',(a1)+ ; pop in a space
move.l FileNm(a5),a0 ; PTR to filename in a0
bsr CopyString
lea LineBuff(a5),a0 ; now set up whole string for
move.l a0,d1 ; Execute()
Zero d2 ; no input specified
move.l StdOut(a5),d3 ; StdOut for output
DosCall Execute
tst.l d0
bne.s EndEdit
bra.s EdTrouble
EndEdit
move.l EdPTR(a5),d1 ; IF is PTR, THEN
beq.s DoneEdit
DosCall Close ; close file
move.l #0,EdPTR(a5) ; and clear storage!
move.l FileLok(a5),d1
beq.s DoneEdit ; IF is lock, THEN
DosCall UnLock ; unlock it
move.l #0,FileLok(a5) ; and clear storage
DoneEdit
moveq #Again,d0 ; Redisplay from where we were
rts
EdTrouble
TxtReq EdTroubleMsg(pc),ResumeTxt(pc)
bra EndEdit ; and exit thru cleanup...
EdTroubleMsg
dc.b 10,' Could not RUN your Editor ',10,0
EvenPC
*** Printing options ***
PrtTitle
dc.b ' Choose PRINT Destination: ',0
EvenPC
PRTSc
move.b #1,PrtScFlag(a5) ; set flag for PrtScreen
PRT
PushReg d2-d7
lea DirBuff(a5),a0
move.b #0,(a0)
lea FileBuff(a5),a1
lea PRTName(pc),a0
bsr CopyString
move.l FileReq(a5),a0 ; put it in a0
move.l #0,frq_Flags(a0) ; clear flags
lea PrtTitle(pc),a1 ; give it a title
move.l a1,frq_Title(a0)
lea DirBuff(a5),a1
move.l a1,frq_Dir(a0) ; ptr to buff for directory
lea FileBuff(a5),a1
move.l a1,frq_File(a0) ; ptr to buff for filename
lea PathName(a5),a1
move.l a1,frq_PathName(a0) ; ptr to buff for complete pathname
or.l #FRQEXTSELECTM!FRQCACHINGM!FRQSAVINGM,frq_Flags(a0)
ReqCall FileRequester ; and call it up
tst.l d0
beq CancelPRT ; was cancelled
bsr ChkDev ; see if matches device name
tst.l d0 ; if zero'd was no match
bne OverWrite ; was match, treat as overwrite mode
lea PathName(a5),a0 ; diff num of chars, or no match, so
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
TxtReq FExistsMsg(pc),CancelTxt(pc),AppendTxt(pc),OverWriteTxt(pc)
tst.l d0
beq CancelPRT
cmpi #1,d0
beq.s Append
bra.s OverWrite
FExistsMsg
dc.b 10,' Chosen file already exists ',10,10,' What should I do now? ',10,0
EvenPC
Append
lea PathName(a5),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(a5) ; 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.s PrintIt ; ready to print...
OverWrite
lea PathName(a5),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(a5) ; store it for close down
PrintIt
move.l a2,PageBot(a5) ; just hiding it
cmpi.b #1,PrtScFlag(a5) ; was it a PrtSc only?
beq.s PrtScIt ; handle it differently
DosPrt PRTFile(a5),FileMemBuf(a5),FileSize(a5)
cmpi.l #-1,d0 ; oops! not all chars written..
beq.s PRTError
bra.s PRTCleanUp
PrtScIt
move.l PageTop(a5),d2 ; top of page, & ptr to file
move.l a2,d3 ; page bottom into d3
sub.l d2,d3 ; difference is chars to write
move.l PRTFile(a5),d1 ; "file" ptr into d1
DosCall Write ; pump it out
cmpi.l #-1,d0 ; not all written?
beq.s PRTError ; oops!
move.b #0,PrtScFlag(a5) ; done with PrtScrn
PRTCleanUp
move.l PRTFile(a5),d1 ; IF is PTR, THEN
beq.s DonePRT
DosCall Close ; close file
move.l #0,PRTFile(a5) ; and clear storage!
DonePRT
moveq #Again,d0 ; Redisplay from where we were
PullReg d2-d7
rts
CancelPRT
cmpi.b #1,PrtScFlag(a5) ; if was PrtScreen operation
bne.s 1$
move.b #0,PrtScFlag(a5) ; cancel THAT too! :-)
1$
bra PRTCleanUp
PRTError
TxtReq PRTErrorMsg(pc),ResumeTxt(pc)
bra CancelPRT
PRTErrorMsg
dc.b 10,' ERROR occurred! ',10,0
EvenPC
ChkDev
lea PathName(a5),a0 ; load PTR to user input
lea PRTName(pc),a1 ; and possible value
bsr.s _CompChar ; and compare
tst.l d0 ; if match, d0 = last char
bne.s MatchFound ; if zero, then keep checking
lea PathName(a5),a0
lea PARName(pc),a1 ; next poss to check
bsr.s _CompChar
tst.l d0
bne.s MatchFound ; keep checking if zero
lea PathName(a5),a0
lea SERName(pc),a1
bsr.s _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.s CompMore ; if match, continue check
cmp.b d5,d1 ; does it match char in d1?
beq.s CompMore ; if match continue check
bra.s CompNot ; otherwise get out
CompMore
dbra d4,CompLoop ; was match: chars left?
rts
CompNot
Zero d0
rts
*** Search Operations ***
* we give up speed for space here and use the same search
* whether or not case sensitive. 2 compares for every
* character, but a 680x0 is pretty quick, right?
SRCH
PushReg d3-d7 ; save 'em for later!
move.b #0,SrchType(a5) ; we are case sensitive!
lea SrchSensTitle(pc),a1
bra.s Search
SrchSensTitle
dc.b ' Case Sensitive Search ',0
EvenPC
SRCHI
PushReg d3-d7 ; save 'em for later
move.b #1,SrchType(a5) ; we are NOT case sensitive!
lea SrchInsensTitle(pc),a1
bra.s Search
SrchInsensTitle
dc.b ' Case insensitive Search ',0
EvenPC
Search
lea KeyBuff(a5),a0 ; load buffer
move.b #0,(a0)
lea GetString(a5),a0 ; load structure
move.l a1,gs_titlebar(a0)
lea KeyBuff(a5),a1
move.l a1,gs_stringbuffer(a0)
move.w #80,gs_stringsize(a0)
move.w #40,gs_visiblesize(a0)
ReqCall NewGetString ; call requester for string
tst.l d0
beq NoMatch
lea KeyBuff(a5),a0
Zero d0
LenGetLoop
addq #1,d0
tst.b (a0)+
bne.s LenGetLoop
move.l d0,d3 ; store length of string in d3
subq.l #1,d3 ; less one (for dbra)
move.l d3,d4 ; and in d4 for testing
move.l a2,CurPosn(a5) ; in case we need to know!
PushReg d3 ; because BackOnePage needs it
bsr _BackOnePage ; to start of displayable page
PullReg d3 ; and back to our value
bra.s StartSrch ; and start search
ReSearch
PushReg d3-d7 ; save 'em for later
move.l SrchOK(a5),d3 ; check if previous valid search
beq.s NoMatch ; no? skip outta here!
move.l d3,d4 ; Yes, copy string length(-1) to d4
move.l a2,CurPosn(a5) ; in case we need to know!
move.l LastPosn(a5),a2 ; "stored" from last search
StartSrch
FirstChar
Zero d0 ; clear out d0
lea KeyBuff(a5),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.s Match1 ; if match, continue check
cmp.b d5,d1 ; does it match char in d1?
beq.s Match1 ; if match continue check
cmpa.l a2,a3 ; see if past EOF
ble.s 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.s 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.s 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
move.b #0,TopFlag(a5)
move.l d7,LastPosn(a5) ; "store" location to display from
move.l LastPosn(a5),CurPosn(a5) ; for reasonable value if "re-search" fails
PushReg d2-d4
bsr _PrevLine ; set a2 to start of line found
PullReg d2-d4
moveq #PageDown,d0 ; tell display routine to go from here
move.l d3,SrchOK(a5) ; Set flag (w num of chars in string
PullReg d3-d7 ; and reset d3-d7 as before
rts
NoMatch
move.l CurPosn(a5),a2 ; and current posn in file!
move.l #0,SrchOK(a5) ; Set flag that search DIDN'T work
TxtReqCt NotFoundMsg(pc),ResumeTxt(pc),KeyBuff(a5)
PullReg d3-d7 ; return d3/d7 to previous contents
moveq #Again,d0 ; redisplay from where we were
rts
NotFoundMsg
dc.b 10,' <%s> ',10,10,' Not Found ',10,0
EvenPC
_ConvChar
move.l d0,d1 ; copy it into d1
cmpi.b #0,SrchType(a5) ; is case sensitive search?
beq.s 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
lea GetLong(a5),a0
lea GotoTitle(pc),a1
move.l a1,gl_titlebar(a0)
move.l #0,gl_defaultval(a0)
move.l #0,gl_minlimit(a0)
move.l #100,gl_maxlimit(a0)
or.l #GLNODEFAULTM,gl_flags(a0) ; don't GIVE a default value
ReqCall GetLong
tst.l d0
beq.s GotoExit
lea GetLong(a5),a0
move.l gl_result(a0),d0
tst.b d0 ; and got what back?
beq.s MeansTop ; zero? hope user MEANT top :-)
cmpi.b #100,d0 ; was it 100?
beq.s MeansBottom ; must mean go to bottom
addq #1,d0 ; kludge for rounding errors
mulu HunFileSize(a5),d0 ; multiply by 1/100 of the file's size
move.l FileMemBuf(a5),d1 ; start of file in d0
add.l d0,d1 ; add it to result of calc
move.l d1,a2 ; now we have PTR to display from
move.b #0,TopFlag(a5) ; and we're NOT at top of file
bsr _PrevLine ; back up to beginning of line
move.l a2,PageTop(a5) ; mark this as top of page
GotoExit
moveq #PageUp,d0 ; tell main loop to show TO here
rts
MeansBottom
moveq #Bottom,d0
rts
MeansTop
moveq #Top,d0
rts
GotoTitle
dc.b ' GO TO % ? ',0
EvenPC
*** Useful General Subroutines ***
_WrChar ; Enter with char to print in d0
PushAll ; Save regs
lea CBuff(a5),a1 ; PTR to buffer in a1
move.b d0,(a1) ; Put character in buffer
DosPrt RawHnd(a5),CBuff(a5),#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.s 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.s Eval ; evaluate and move remainder
divu #100,d1 ; get 100's digit
bsr.s Eval ;
divu #10,d1 ; get 10's digit
bsr.s 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.s NotLdZero
tst.l d0 ; test d0 for a previous no-zero char
bne.s NotLdZero ; if was one, skip the change to space
move.b #' ',(a0)+ ; there wasn't - so store space instead
bra.s 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
*** Data Storage areas ***
RawName1
dc.b 'raw:0/0 /'
dc.b 'File: CTYPE 2.02 <HELP> for help ',0
PosPrompt1
dc.b $9b,' ;1H',$9b,'7m % of '
dc.b ' KBytes MODE = N Click or <SPACE> = more ',$9b,'0m',$9b,'K',0
SPosPrompt1
dc.b $9b,' ;1H ',$9b,'7m -MORE- ',$9b,'0m',$9b,'K',0
PRTName
dc.b 'PRT:',0
PARName
dc.b 'PAR:',0
SERName
dc.b 'SER:',0
EditName
dc.b 'ENV:Editor',0
ReqTitle
dc.b ' CType 2.02 Choose a File: ',0
ClrLn
dc.b $9b,'M',$9b,'F',$9b,'E',0
CursorOn
dc.b $9b,$20,$70,0
CursorOff
dc.b $9b,$30,$20,$70,$F,0
GetWinStat
dc.b $9b,$30,$20,$71,0
SetMouse
dc.b $9b,'2;12{',0
YesTxt
dc.b ' Yes ',0
NoTxt
dc.b ' NO ',0
CancelTxt
dc.b ' Cancel ',0
AppendTxt
dc.b ' Append ',0
OverWriteTxt
dc.b ' OverWrite ',0
ResumeTxt
dc.b ' Resume ',0
HelpMsg
dc.b 10,' Result Command Alternates Num Pad',10,10
dc.b ' Forward a PAGE SPACE SHIFT-DOWN PGDN 3 ',10
dc.b ' Forward a LINE RETURN DOWN DOWN 2 ',10
dc.b ' Backward PAGE BACKSPACE SHIFT-UP PGUP 9 ',10
dc.b ' Backward LINE DELETE UP UP 8 ',10
dc.b ' TOP of file < LEFT HOME 7 ',10
dc.b ' BOTTOM of file > RIGHT END 1 ',10
dc.b ' Scroll RIGHT RIGHT R RIGHT 6 ',10
dc.b ' Scroll LEFT LEFT L LEFT 4 ',10
dc.b ' QUIT/Next File ESC Q F10',10,10
dc.b ' More HELP? ',10,0
HelpMsg2
dc.b 10,' Result Command Alternates ',10,10
dc.b ' Change TAB Size TAB (Default is 8)',10
dc.b ' Toggle FORMAT mode F (Word Wrap)',10
dc.b ' Search for String / (Case Sensitive)',10
dc.b ' Search for String . (NOT Case sensitive) ',10
dc.b ' Next Occurrence N (Of previous String)',10
dc.b ' Move N% into file %N (where N = number)',10
dc.b ' Call your Editor E (Def in ENV:Editor)',10
dc.b ' Print complete file P SHIFT-F7 (for WP users!)',10
dc.b ' Print screen only PrtSc F7 (or ANY * key)',10,10
dc.b ' UNCONDITIONAL EXIT CTRL-C',10,10
dc.b ' More HELP? ',10,0
EvenPC
end ; yup - that's IT!