home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mass61.zip / mass.zip / masm61 / DISK3 / SAMPLES / SHOW / PAGER.AS$ / PAGER
Text File  |  1992-11-12  |  10KB  |  341 lines

  1. ;* PAGER.ASM - Module containing routines for paging through a file and
  2. ;* writing text to the screen buffer. Works with main module SHOW.ASM.
  3.  
  4.  
  5.     .MODEL  small, pascal, os_dos   ; This code also works in tiny model
  6.  
  7.     INCLUDE show.inc
  8.  
  9.     .CODE
  10.  
  11. ;* Pager - Displays status line and all the text lines for a screen.
  12. ;*
  13. ;* Params: cLines - lines to scroll (negative up, positive down)
  14. ;*
  15. ;* Uses:   Global variables: segBuf, offBuf, yCur
  16. ;*
  17. ;* Return: None
  18.  
  19. Pager   PROC,
  20.     cLines:SWORD
  21.  
  22.     mov     es, segBuf              ; Initialize buffer position
  23.     mov     di, offBuf
  24.  
  25.     mov     cx, cLines              ; Get line count
  26.     mov     ax, 10                  ; Search for linefeed
  27.  
  28.     or      cx, cx                  ; Argument 0?
  29.     jg      forward                 ; If above, forward
  30.     jl      backward                ; If below, backward
  31.     jmp     showit                  ; If equal, done
  32. backward:
  33.     call    GoBack                  ; Adjust backward
  34.     jmp     showit                  ; Show screen
  35. forward:
  36.     call    GoForeward              ; Adjust forward
  37.  
  38. ; Write line number to status line
  39.  
  40. showit:
  41.     cld                             ; Forward
  42.     push    di                      ; Save
  43.     push    ds                      ; ES = DS
  44.     pop     es
  45.  
  46.     INVOKE  BinToStr,               ; Write line number as string
  47.         yCur,
  48.         ADDR stLine[LINE_POS]
  49.  
  50. ; Fill in status line
  51.  
  52.     mov     cx, 6                   ; Seven spaces to fill
  53.     sub     cx, ax                  ; Subtract those already done
  54.     mov     al, ' '                 ; Fill with space
  55.     rep     stosb
  56.  
  57.     INVOKE  ShowLine,               ; Write to screen
  58.         ADDR stLine,            ; Far pointer to line
  59.         0,                      ; Line number
  60.         atSta                   ; Attribute
  61.  
  62.     pop     di
  63.     mov     si, di                  ; Update position
  64.     mov     cx, yMax                ; Lines per screen
  65.  
  66.     .REPEAT
  67.     mov     bx, yMax                ; Lines per screen
  68.     inc     bx                      ; Adjust for 0
  69.     sub     bx, cx                  ; Calculate current row
  70.     push    cx                      ; Save line number
  71.     mov     es, segBuf              ; Reload
  72.  
  73.     INVOKE  ShowLine,               ; Write line to screen
  74.         es::si,                 ; Far pointer to text
  75.         bx,                     ; Line number
  76.         atScr                   ; Attribute
  77.  
  78.     pop     cx                      ; Restore line number
  79.     mov     si, ax                  ; Get returned position
  80.  
  81.     dec     cx                      ; Count the line
  82.     .UNTIL  (ax >= cbBuf) || !cx    ; Continue if more lines and not CX
  83.     jcxz    exit                    ; Done if more lines,
  84.                     ;   else fill screen with spaces
  85.     mov     al, cl                  ; Columns * remaining lines
  86.     mov     dl, X_MAX               ;   is count of cells to fill
  87.     mul     dl
  88.     mov     dx, ax                  ; Save in DX (INVOKE uses AX)
  89.  
  90.     sub     cx, yMax                ; Calculate starting line
  91.     neg     cx
  92.     inc     cx
  93.  
  94.     INVOKE  CellFill,               ; Write space cells
  95.         cx,                     ; Starting line
  96.         dx,                     ; Cells to write
  97.         celScr                  ; Cell to write
  98. exit:
  99.     ret
  100.  
  101. Pager   ENDP
  102.  
  103.  
  104. ;* WriteNCell - Macro to write a cell one or more times. For CGA, the
  105. ;* macro writes during horizontal retrace. Note that this is a macro
  106. ;* even though it may result in more code than if it were a procedure.
  107. ;* This is because writes to the screen buffer are a speed bottleneck
  108. ;* that only occur at a few key points in the program. The extra
  109. ;* size cost is worth paying.
  110. ;*
  111. ;* Uses:   ES:DI has screen buffer position
  112. ;*         AX has cell
  113. ;*         DX should have port number for rescan check if CGA
  114. ;*
  115. ;* Params: isCGA - One of the following:
  116.         CGA     EQU     1
  117.         NoCGA   EQU     0
  118. ;*
  119. ;*         count - If blank, write cell in AX once. If count given, write
  120. ;*         cell in AX count times. Note that the count is optimized for a
  121. ;*         CX argument. The argument should normally be blank or CX.
  122.  
  123. WriteNCell MACRO isCGA:REQ, count:=<1>
  124.  
  125.     IF isCGA EQ 0                       ; First handle non-CGA
  126.     IFIDNI <count>, <1>             ; Special case one cell
  127.         stosw
  128.     ELSE
  129.         IFDIFI <count>, <cx>        ; Load count if necessary
  130.         mov  cx, count
  131.         ENDIF
  132.         rep  stosw                  ; Do repeated sequence
  133.     ENDIF
  134.     ELSE
  135.     IFIDNI <count>, <1>             ; Special case one cell
  136.         push    ax                  ; Save character
  137.         .REPEAT
  138.         in      al, dx              ; Look in the port
  139.         shr     al, 1               ;   until it goes low
  140.         .UNTIL  !carry?
  141.         cli
  142.         .REPEAT
  143.         in      al, dx              ; Look in the port
  144.         shr     al, 1               ;   until it goes high
  145.         .UNTIL  carry?
  146.         pop     ax                  ; Restore and write it
  147.         stosw
  148.         sti
  149.     ELSE
  150.         IFDIFI <count>, <cx>        ; Load count if necessary
  151.         mov  cx, count
  152.         ENDIF
  153.         .REPEAT
  154.         push    ax                  ; Save character
  155.         .REPEAT
  156.         in      al, dx              ; Look in the port
  157.         shr     al, 1               ;   until it goes low
  158.         .UNTIL  !carry?
  159.         cli
  160.         .REPEAT
  161.         in      al, dx              ; Look in the port
  162.         shr     al, 1               ;   until it goes high
  163.         .UNTIL  carry?
  164.         pop     ax                  ; Restore and write it
  165.         stosw
  166.         sti
  167.         .UNTILCXZ
  168.     ENDIF
  169.     ENDIF
  170. ENDM
  171.  
  172. ;* ShowLine - Writes a line to the screen buffer.
  173. ;*
  174. ;* Params: fpBuffer - Far pointer to line to write
  175. ;*         y - Line number
  176. ;*         attr - Attribute
  177. ;*
  178. ;* Return: None
  179.  
  180. ShowLine PROC USES si di ds,
  181.     fpBuffer:FAR PTR BYTE,
  182.     y:WORD,
  183.     attr:BYTE
  184.  
  185.     sub     dx, dx                  ; Zero
  186.     .IF     fCGA                    ; User port number as CGA flag
  187.     mov     dx, 03DAh               ; Load port #
  188.     .ENDIF
  189.     mov     es, segVid              ; Load screen buffer segment
  190.     lds     si, fpBuffer            ; Buffer segment
  191.     mov     cx, X_MAX               ; Cells per row
  192.     mov     ax, y                   ; Starting row
  193.     mov     bx, X_MAX * 2           ; Bytes per row
  194.     mul     bl                      ; Figure columns per row
  195.     mov     di, ax                  ; Load as destination
  196.     mov     bx, di                  ; Save start for tab calculation
  197.     mov     ah, attr                ; Attribute
  198. movechar:
  199.     lodsb                           ; Get character
  200.     cmp     al, 13                  ; CR?
  201.     je      fillspc
  202.     cmp     al, 9                   ; Tab?
  203.     jne     notab
  204.     call    FillTab                 ; Yes? Fill with spaces
  205.     jcxz    nextline                ; If beyond limit, done
  206.     jmp     movechar
  207. notab:
  208.     or      dx, dx                  ; CGA?
  209.     je      notab2
  210.     WriteNCell CGA                  ; Yes? Write during retrace
  211.     loop    movechar                ; Duplicate code here and below
  212.     jmp     nextline                ;   is worth cost in tight loop
  213. notab2:
  214.     WriteNCell NoCGA                ; Write
  215.     loop    movechar
  216.     jmp     nextline                ; Done
  217. fillspc:
  218.     mov     al, ' '                 ; Fill with space
  219.  
  220.     .IF     dx != 0                 ; CGA?
  221.     WriteNCell CGA, cx
  222.     inc     si                      ; Adjust
  223.     jmp     exit                    ; Done
  224.     .ENDIF
  225.     WriteNCell NoCGA, cx
  226.     inc     si                      ; Adjust for LF
  227.     jmp     exit                    ; Done
  228. nextline:
  229.     mov     ah, 10                  ; Search for next line feed
  230.     .REPEAT
  231.     lodsb                           ; Load and compare
  232.     .UNTILCXZ al == ah
  233. exit:
  234.     mov     ax, si                  ; Return position
  235.     ret
  236.  
  237. ShowLine ENDP
  238.  
  239.  
  240. ;* CellFill - Fills a portion of the screen with a specified
  241. ;* character/attribute cell.
  242. ;*
  243. ;* Params: yStart - Starting line
  244. ;*         cbCell - Number of cells
  245. ;*         celFill - Attribute and character
  246. ;*
  247. ;* Return: None
  248.  
  249. CellFill PROC,
  250.     yStart:WORD,
  251.     cbCell:WORD,
  252.     celFill:WORD
  253.  
  254.     mov     dx, 03DAh               ; Load port #
  255.     mov     cx, yStart              ; Starting line
  256.     mov     al, X_MAX * 2           ; Convert line to starting offset
  257.     mul     cl
  258.     mov     di, ax                  ; Make it the target
  259.     mov     es, segVid              ; Load screen buffer segment
  260.     mov     cx, cbCell              ; Characters to fill
  261.     mov     ax, celFill             ; Attribute
  262.     .IF     fCGA                    ; Write cells
  263.     WriteNCell CGA, cx
  264.     .ELSE
  265.     WriteNCell NoCGA, cx
  266.     .ENDIF
  267.  
  268.     ret
  269.  
  270. CellFill ENDP
  271.  
  272.  
  273. ;* FillTab - Writes spaces for tab to screen.
  274. ;*
  275. ;* Input:  BX points to start of line
  276. ;*         DI points to current position
  277. ;*
  278. ;* Return: None
  279.  
  280. FillTab PROC
  281.  
  282.     push    bx
  283.     push    cx
  284.  
  285.     sub     bx, di                  ; Get current position in line
  286.     neg     bx
  287.     shr     bx, 1                   ; Divide by 2 bytes per character
  288.  
  289.     mov     cx, 8                   ; Default count 8
  290.     and     bx, 7                   ; Get modulus
  291.     sub     cx, bx                  ; Subtract
  292.     mov     bx, cx                  ; Save modulus
  293.  
  294.     mov     al, ' '                 ; Spaces
  295.     .IF     dx != 0                 ; Write cells
  296.     WriteNCell CGA, cx
  297.     .ELSE
  298.     WriteNCell NoCGA, cx
  299.     .ENDIF
  300.     pop     cx
  301.     sub     cx, bx                  ; Adjust count
  302.     .IF     sign?
  303.     sub     cx, cx                  ; Make negative count 0
  304.     .ENDIF
  305.     pop     bx
  306.     ret
  307.  
  308. FillTab ENDP
  309.  
  310.  
  311. ;* IsEGA - Determines if the current adapter can handle more than 25
  312. ;* lines per screen (usually an EGA or VGA).
  313. ;*
  314. ;* Params: None
  315. ;*
  316. ;* Return: 0 if no CGA or MONO, lines per screen if EGA/VGA
  317.  
  318. IsEGA   PROC
  319.  
  320.     mov     ah, 12h                 ; Call EGA status function
  321.     mov     bl, 10h
  322.     sub     cx, cx                  ; Clear status bits
  323.     int     10h
  324.     sub     ax, ax                  ; Segment 0 and assume no EGA
  325.     jcxz    noega                   ; If status still clear, no EGA
  326.  
  327.     mov     es, ax                  ; ES=0
  328.     test    BYTE PTR es:[487h], 1000y; Test active bit
  329.     jnz     noega                   ; If set, not active
  330.     mov     ax, 1130h               ; Get EGA information
  331.     int     10h
  332.     mov     al, dl                  ; Return lines per screen
  333.     cbw
  334. noega:
  335.     ret
  336.  
  337. IsEGA   ENDP
  338.  
  339.  
  340.     END
  341.