home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / masm / masm6 / show / pagerr.asm < prev    next >
Encoding:
Assembly Source File  |  1991-01-14  |  11.5 KB  |  341 lines

  1. ;* PAGERR.ASM - Module containing routines for paging through a file and
  2. ;* writing text to the screen buffer. Works with main module SHOWR.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                   ; Atttribute
  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
  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 occurs 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.