home *** CD-ROM | disk | FTP | other *** search
/ ftp.shrubbery.net / 2015-02-07.ftp.shrubbery.net.tar / ftp.shrubbery.net / pub / pc / unix / unx.arc / MORE.ASM < prev    next >
Assembly Source File  |  1986-03-21  |  7KB  |  372 lines

  1. ;------ more.asm ----------------------------------------------------------
  2. ; Displays files one page at a time.
  3. ; Uses raw mode, buffers output, and avoids scrolling; thus repaints screen
  4. ; very quickly when used with Nansi.
  5. ; Link as follows:
  6. ;  link more setraw args;
  7. ;  exe2bin more more.com
  8. ;  del more.exe
  9. ;
  10. ; 3/16/86 DRK: added setraw call to fix raw read from con: problem.
  11.  
  12.     extrn    _args:near, new:near
  13.     extrn    argc:word, argv:word
  14.     extrn    getraw:near, setraw:near
  15.  
  16. cls_on_page    equ    1        ; set to 0 for scroll instead of cls
  17.  
  18. stdin    equ    0
  19. stdout    equ    1
  20. stderr    equ    2
  21.  
  22. code    segment para public 'CODE'
  23. assume    cs:code, ds:code
  24.  
  25.     org    100h
  26. main    proc
  27.  
  28.     jmp    short domain
  29.     db    1bh
  30.     db    "[2J"
  31.     db    "More v1.1 March 16, 1986 by John Q. Smallberries."
  32.     db    0dh, 0ah, 1ah
  33.  
  34. m_fbad    db    "more: can't open."
  35.     db    13, 10
  36. l_fbad    equ    $-m_fbad
  37.  
  38. m_noram    db    "more: out of memory."
  39.     db    13, 10
  40. l_noram    equ    $-m_noram
  41.  
  42. max_y    db    18h
  43. max_x    db    50h
  44. cur_y    db    01h
  45. cur_x    db    01h
  46.  
  47. old_rawness    dw    ?
  48.  
  49. stacklen    equ    400h
  50.  
  51. filbufl    equ    01000h
  52. filbuf    dw    ?    ; buffer for file reading
  53. fillen    dw    ?    ; number of chars in buffer
  54.  
  55. linbufl    equ    100h
  56. linbuf    dw    ?    ; buffer for line output
  57. linlen    dw    ?    ; number of chars in output line buffer
  58.  
  59. domain:
  60.     call    _args
  61.  
  62.     ; Check DOS version
  63.     MOV     AH,30h
  64.     INT     21h
  65.     XCHG    AL,AH
  66.     CMP     AX,200h        
  67.     JNB     version_ok
  68.         MOV     DX,OFFSET bad_version        
  69.         MOV     AH,9
  70.         INT     21h   
  71.         mov    ah, 0
  72.         int    21h
  73. bad_version:
  74.     db    "MORE: Incorrect DOS version"
  75.     db    0dh, 0ah, 24h
  76.  
  77. version_ok:
  78.     ; allocate buffer for reading in file
  79.     mov    cx, filbufl
  80.     call    new
  81.     mov    filbuf, bx
  82.  
  83.     ; allocate buffer for writing out a line
  84.     mov    cx, linbufl
  85.     call    new
  86.     mov    linbuf, bx
  87.  
  88.     ; return remainder of RAM to system; 
  89.     ; bx+stacklen+linbufl is last byte used.
  90.     push    cs
  91.     pop    es
  92.     add    bx, stacklen+linbufl
  93.     mov    cl, 4
  94.     shr    bx, cl
  95.     inc    bx        ; memory needed/16
  96.     mov    ah, 4ah        ; setblock
  97.     int    21h        ; only fails if not enough available.
  98.     ; error code 8 = not enough memory; bx = available mem.
  99.     mov    cx, l_noram
  100.     mov    dx, offset l_noram
  101.     jc    prterr
  102.  
  103.     ; allocate stack (must be last new)
  104.     mov    cx, stacklen    ; big one!
  105.     call    new
  106.     add    bx, 3feh    ; stack top
  107.     mov    ax, cs
  108.     mov    ss, ax
  109.     mov    sp, bx        ; indivisible; don't need to cli.
  110.  
  111.     ; determine screen width by calling ROM Bios
  112.     MOV     BYTE PTR [max_y],19h       
  113.     MOV     AH,0Fh
  114.     INT     10h   
  115.     MOV     byte ptr [max_x],AH      
  116.  
  117.     ; Save old rawness state of stdout
  118.     mov    bx, stdout
  119.     call    getraw
  120.     mov    old_rawness, ax
  121.     ; Set stdout to raw mode (for speed & immunity from ^C)
  122.     mov    al, 1
  123.     mov    bx, stdout
  124.     call    setraw
  125.  
  126.     mov    di, linbuf
  127.     mov    linlen, 0    ; init output line
  128.  
  129.     cmp    argc, 0        ; any arguments?
  130.     jz    play_hookey
  131.  
  132.         ; File arguments.  For now, only allow one.
  133.         mov    dx, argv[2]    ; get pointer to first arg
  134.         mov    ax, 3d00h    ; open for read access
  135.         int    21h
  136.         jnc    got_file
  137.             mov    dx, offset m_fbad
  138.             mov    cx, l_fbad
  139. prterr:            mov    bx, stderr
  140.             mov    ah, 40h        ; write
  141.             int    21h
  142.             jmp    quit
  143. got_file:    mov    bp, ax
  144.         jmp    short start_output
  145.  
  146. play_hookey:
  147.     ; If reading from stdin, play hooky with
  148.     ; file descriptors.
  149.     mov    bx, stdin
  150.     MOV     AH,45h
  151.     INT     21h
  152.     MOV     BP,AX        ; bp = copy of stdin
  153.  
  154.     MOV     AH,3Eh
  155.     INT     21h        ; close stdin
  156.  
  157.     MOV     BX,stderr
  158.     MOV     AH,45h
  159.     INT     21h        ; ax = copy of stderr (probably zero)
  160.  
  161. start_output:
  162.     ; At this point, input file descriptor is in BP;
  163.     ; somehow, fd 0 is directly connected to console...
  164.  
  165.     ; Set cooked mode on input file; this avoids problems
  166.     ; if input file is a device (say, CON:).
  167.     mov    bx, bp
  168.     mov    ax, 0
  169.     call    setraw
  170.  
  171.  
  172. ;    don't clear screen before starting, minor annoyance --CLF
  173. ;    if    cls_on_page
  174. ;    ; Clear screen before starting...
  175. ;    mov    dx, offset cls_string
  176. ;    mov    ah, 9
  177. ;    int    21h
  178. ;    endif
  179.  
  180.     ;----- outer loop -------
  181. get_more_input:
  182.     CLD
  183.     MOV     DX,filbuf        
  184.     MOV     CX,filbufl
  185.     MOV     BX,BP
  186.     MOV     AH,3Fh
  187.     INT     21h   
  188.     OR      AX,AX
  189.     jz    putquit
  190.     mov    fillen, ax    ; save number of chars in buffer
  191.     MOV     CX,AX
  192.     MOV     SI,DX
  193.  
  194.     ;---- inner loop ----
  195. get_another_char:
  196.     lodsb        
  197.     cmp     AL,1Ah
  198.     jz    putquit            ; eof, so flush buffer & exit
  199.     cmp     AL,0Dh
  200.     jz    is_cr
  201.     cmp    al, 0ah
  202.     jz    is_lf
  203.     cmp    al, 8
  204.     jz    is_bsp
  205.     cmp    al, 9
  206.     jz    is_tab
  207.     cmp    al, 1bh
  208.     jz    is_escape
  209.     cmp    al, 7
  210.     jz    is_bel
  211. not_funny:
  212.     ; Just a normal char in AL; increment X and put the char.
  213.     inc    cur_x
  214.     MOV     AH, cur_x
  215.     CMP     AH, max_x
  216.     JB    do_stosb
  217.         ; Ran over screen edge; do a CRLF after putting the char,
  218.         ; and flush the buffer.
  219.         INC     cur_y
  220.         MOV     cur_x, 1       
  221.         stosb
  222.         mov    al, 0dh
  223.         stosb
  224.         mov    al, 0ah
  225.         stosb
  226.         call    putlin
  227.         jmp    short skip_putc
  228. do_stosb:
  229.     stosb
  230. skip_putc:
  231.     MOV     AH,[cur_y]      
  232.     CMP     AH,[max_y]      
  233.     loopnz    get_another_char
  234.     jcxz    get_more_input
  235.     jmp    inquire            ; must have come to bottom of screen
  236.  
  237. putquit:    call    putlin
  238. quitgate:    jmp    quit   
  239.  
  240. is_cr:    MOV    cur_x,1       
  241. is_bel:    JMP    do_stosb
  242.  
  243. is_lf:    stosb
  244.     call    putlin
  245.     INC    cur_y
  246.     JMP    skip_putc
  247.  
  248. is_bsp:    dec    cur_x
  249.     jnz    bsp_ok
  250.     inc    cur_x
  251. bsp_ok:    jmp    do_stosb
  252.  
  253. is_tab:    MOV     AH, cur_x
  254.     ADD     AH, 7
  255.     AND     AH, 0F8h
  256.     INC     AH
  257.     mov    cur_x, ah
  258.     jmp    do_stosb
  259.  
  260.     ; escloop avoids screwing up tabs when outputting escape sequences
  261.     ; It screws up slightly when the input buffer is empty, but who cares.
  262. escloop:
  263.     lodsb
  264.     cmp    al, 'A'
  265.     jb    do_stosb
  266. is_escape:    ; Don't count it as printing, most of time, at least...
  267.     stosb
  268.     loop    escloop
  269.     jmp    get_more_input
  270.  
  271. inquire:
  272. try_again_stupid:
  273.     MOV     DX, offset more_msg        ; print "More?"
  274.     mov    ah, 9
  275.     int    21h
  276.     ; get char; don't echo it, don't check for ctrl-break.
  277.     MOV     AH, 7
  278.     INT     21h   
  279.     ; Clear "more?" message.
  280.     push    ax
  281.     MOV     DX,OFFSET clear
  282.     mov    ah, 9
  283.     int    21h
  284.     pop    ax
  285.     ; Response in AL; check response, exit if q or Q, line if <CR> ----
  286.     cmp    al, 'q'
  287.     jz    quit
  288.     cmp    al, 'h'
  289.     jz    helpme
  290.     cmp    al, '?'
  291.     jnz    not_help
  292. helpme:        mov    dx, offset help_msg
  293.         mov    ah, 9
  294.         int    21h
  295.         jmp    inquire
  296. not_help:
  297.     cmp    al, 'd'
  298.     jnz    not_d
  299.         ; do another half screenful
  300.         MOV     BYTE PTR [cur_x],01
  301.         shr     BYTE PTR [cur_y],1       
  302.         jmp    short do_more
  303. not_d:    cmp    al, 0dh            ; <CR>
  304.     jnz    not_cr
  305.         ; just do one line more
  306.         mov    byte ptr [cur_x],1
  307.         dec    byte ptr [cur_y]
  308.         jmp    short do_more
  309. not_cr:    cmp    al, ' '
  310.     jnz    try_again_stupid
  311.         ; do another screenful
  312.         MOV     BYTE PTR [cur_x],01      ; clear x, y
  313.         MOV     BYTE PTR [cur_y],01       
  314.         if    cls_on_page
  315.         mov    dx, offset cls_string
  316.         mov    ah, 9
  317.         int    21h
  318.         endif
  319. do_more:
  320.     jmp    get_another_char
  321.  
  322.  
  323. quit:    mov    bx, stdout
  324.     mov    ax, old_rawness
  325.     call    setraw
  326.     mov    ax, 4c00h
  327.     int    21h
  328.  
  329. main    endp
  330.  
  331. ;---- putlin ------------
  332. ; Puts line at linbuf to stdout, resets DI and linlen.
  333.  
  334. putlin    proc    near
  335.     push    bx
  336.     push    cx
  337.     mov    bx, stdout
  338.     mov    dx, linbuf
  339.     mov    cx, di
  340.     sub    cx, dx
  341.     mov    ah, 40h        ; write to file
  342.     int    21h
  343.     jc    quit
  344.     mov    di, linbuf
  345.     pop    cx
  346.     pop    bx
  347.     ret
  348. putlin    endp
  349.  
  350.  
  351. help_msg:
  352.     db    0dh, 0ah
  353.     db    "More understands these keystrokes:", 0dh, 0ah
  354.     db    "q: quit", 0dh, 0ah
  355.     db    "h: help (prints this message)", 0dh, 0ah
  356.     db    "d: down half screen", 0dh, 0ah
  357.     db    "space: down full screen", 0dh, 0ah
  358.     db    "ENTER: down one line.", 0dh, 0ah
  359.     db    "$"
  360.  
  361. more_msg:
  362.     db    0dh
  363.     db    " More (cr, sp, ?) $"
  364.  
  365. clear:    db    0dh, 18 dup (20h), 0dh, '$'
  366.  
  367. cls_string:
  368.     db    27,"[H",27,"[2J$"
  369.  
  370. code    ends
  371.     end    main
  372.