home *** CD-ROM | disk | FTP | other *** search
- ;------ 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
-