home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Archive Magazine 1995
/
ARCHIVE95.iso
/
discs
/
shareware
/
share_37
/
zansi
/
more_asm
< prev
next >
Wrap
Text File
|
1990-11-29
|
7KB
|
372 lines
;------ more.asm ----------------------------------------------------------
; Displays files one page at a time.
; Uses raw mode, buffers output, and avoids scrolling; thus repaints screen
; very quickly when used with Nansi.
; Link as follows:
; link more setraw args;
; exe2bin more more.com
; del more.exe
;
; 3/16/86 DRK: added setraw call to fix raw read from con: problem.
extrn _args:near, new:near
extrn argc:word, argv:word
extrn getraw:near, setraw:near
cls_on_page equ 1 ; set to 0 for scroll instead of cls
stdin equ 0
stdout equ 1
stderr equ 2
code segment para public 'CODE'
assume cs:code, ds:code
org 100h
main proc
jmp short domain
db 1bh
db "[2J"
db "More v1.1 March 16, 1986 by John Q. Smallberries."
db 0dh, 0ah, 1ah
m_fbad db "more: can't open."
db 13, 10
l_fbad equ $-m_fbad
m_noram db "more: out of memory."
db 13, 10
l_noram equ $-m_noram
max_y db 18h
max_x db 50h
cur_y db 01h
cur_x db 01h
old_rawness dw ?
stacklen equ 400h
filbufl equ 01000h
filbuf dw ? ; buffer for file reading
fillen dw ? ; number of chars in buffer
linbufl equ 100h
linbuf dw ? ; buffer for line output
linlen dw ? ; number of chars in output line buffer
domain:
call _args
; Check DOS version
MOV AH,30h
INT 21h
XCHG AL,AH
CMP AX,200h
JNB version_ok
MOV DX,OFFSET bad_version
MOV AH,9
INT 21h
mov ah, 0
int 21h
bad_version:
db "MORE: Incorrect DOS version"
db 0dh, 0ah, 24h
version_ok:
; allocate buffer for reading in file
mov cx, filbufl
call new
mov filbuf, bx
; allocate buffer for writing out a line
mov cx, linbufl
call new
mov linbuf, bx
; return remainder of RAM to system;
; bx+stacklen+linbufl is last byte used.
push cs
pop es
add bx, stacklen+linbufl
mov cl, 4
shr bx, cl
inc bx ; memory needed/16
mov ah, 4ah ; setblock
int 21h ; only fails if not enough available.
; error code 8 = not enough memory; bx = available mem.
mov cx, l_noram
mov dx, offset l_noram
jc prterr
; allocate stack (must be last new)
mov cx, stacklen ; big one!
call new
add bx, 3feh ; stack top
mov ax, cs
mov ss, ax
mov sp, bx ; indivisible; don't need to cli.
; determine screen width by calling ROM Bios
MOV BYTE PTR [max_y],19h
MOV AH,0Fh
INT 10h
MOV byte ptr [max_x],AH
; Save old rawness state of stdout
mov bx, stdout
call getraw
mov old_rawness, ax
; Set stdout to raw mode (for speed & immunity from ^C)
mov al, 1
mov bx, stdout
call setraw
mov di, linbuf
mov linlen, 0 ; init output line
cmp argc, 0 ; any arguments?
jz play_hookey
; File arguments. For now, only allow one.
mov dx, argv[2] ; get pointer to first arg
mov ax, 3d00h ; open for read access
int 21h
jnc got_file
mov dx, offset m_fbad
mov cx, l_fbad
prterr: mov bx, stderr
mov ah, 40h ; write
int 21h
jmp quit
got_file: mov bp, ax
jmp short start_output
play_hookey:
; If reading from stdin, play hooky with
; file descriptors.
mov bx, stdin
MOV AH,45h
INT 21h
MOV BP,AX ; bp = copy of stdin
MOV AH,3Eh
INT 21h ; close stdin
MOV BX,stderr
MOV AH,45h
INT 21h ; ax = copy of stderr (probably zero)
start_output:
; At this point, input file descriptor is in BP;
; somehow, fd 0 is directly connected to console...
; Set cooked mode on input file; this avoids problems
; if input file is a device (say, CON:).
mov bx, bp
mov ax, 0
call setraw
; don't clear screen before starting, minor annoyance --CLF
; if cls_on_page
; ; Clear screen before starting...
; mov dx, offset cls_string
; mov ah, 9
; int 21h
; endif
;----- outer loop -------
get_more_input:
CLD
MOV DX,filbuf
MOV CX,filbufl
MOV BX,BP
MOV AH,3Fh
INT 21h
OR AX,AX
jz putquit
mov fillen, ax ; save number of chars in buffer
MOV CX,AX
MOV SI,DX
;---- inner loop ----
get_another_char:
lodsb
cmp AL,1Ah
jz putquit ; eof, so flush buffer & exit
cmp AL,0Dh
jz is_cr
cmp al, 0ah
jz is_lf
cmp al, 8
jz is_bsp
cmp al, 9
jz is_tab
cmp al, 1bh
jz is_escape
cmp al, 7
jz is_bel
not_funny:
; Just a normal char in AL; increment X and put the char.
inc cur_x
MOV AH, cur_x
CMP AH, max_x
JB do_stosb
; Ran over screen edge; do a CRLF after putting the char,
; and flush the buffer.
INC cur_y
MOV cur_x, 1
stosb
mov al, 0dh
stosb
mov al, 0ah
stosb
call putlin
jmp short skip_putc
do_stosb:
stosb
skip_putc:
MOV AH,[cur_y]
CMP AH,[max_y]
loopnz get_another_char
jcxz get_more_input
jmp inquire ; must have come to bottom of screen
putquit: call putlin
quitgate: jmp quit
is_cr: MOV cur_x,1
is_bel: JMP do_stosb
is_lf: stosb
call putlin
INC cur_y
JMP skip_putc
is_bsp: dec cur_x
jnz bsp_ok
inc cur_x
bsp_ok: jmp do_stosb
is_tab: MOV AH, cur_x
ADD AH, 7
AND AH, 0F8h
INC AH
mov cur_x, ah
jmp do_stosb
; escloop avoids screwing up tabs when outputting escape sequences
; It screws up slightly when the input buffer is empty, but who cares.
escloop:
lodsb
cmp al, 'A'
jb do_stosb
is_escape: ; Don't count it as printing, most of time, at least...
stosb
loop escloop
jmp get_more_input
inquire:
try_again_stupid:
MOV DX, offset more_msg ; print "More?"
mov ah, 9
int 21h
; get char; don't echo it, don't check for ctrl-break.
MOV AH, 7
INT 21h
; Clear "more?" message.
push ax
MOV DX,OFFSET clear
mov ah, 9
int 21h
pop ax
; Response in AL; check response, exit if q or Q, line if <CR> ----
cmp al, 'q'
jz quit
cmp al, 'h'
jz helpme
cmp al, '?'
jnz not_help
helpme: mov dx, offset help_msg
mov ah, 9
int 21h
jmp inquire
not_help:
cmp al, 'd'
jnz not_d
; do another half screenful
MOV BYTE PTR [cur_x],01
shr BYTE PTR [cur_y],1
jmp short do_more
not_d: cmp al, 0dh ; <CR>
jnz not_cr
; just do one line more
mov byte ptr [cur_x],1
dec byte ptr [cur_y]
jmp short do_more
not_cr: cmp al, ' '
jnz try_again_stupid
; do another screenful
MOV BYTE PTR [cur_x],01 ; clear x, y
MOV BYTE PTR [cur_y],01
if cls_on_page
mov dx, offset cls_string
mov ah, 9
int 21h
endif
do_more:
jmp get_another_char
quit: mov bx, stdout
mov ax, old_rawness
call setraw
mov ax, 4c00h
int 21h
main endp
;---- putlin ------------
; Puts line at linbuf to stdout, resets DI and linlen.
putlin proc near
push bx
push cx
mov bx, stdout
mov dx, linbuf
mov cx, di
sub cx, dx
mov ah, 40h ; write to file
int 21h
jc quit
mov di, linbuf
pop cx
pop bx
ret
putlin endp
help_msg:
db 0dh, 0ah
db "More understands these keystrokes:", 0dh, 0ah
db "q: quit", 0dh, 0ah
db "h: help (prints this message)", 0dh, 0ah
db "d: down half screen", 0dh, 0ah
db "space: down full screen", 0dh, 0ah
db "ENTER: down one line.", 0dh, 0ah
db "$"
more_msg:
db 0dh
db " More (cr, sp, ?) $"
clear: db 0dh, 18 dup (20h), 0dh, '$'
cls_string:
db 27,"[H",27,"[2J$"
code ends
end main