home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / masm / masm6 / tsr / snap.asm < prev    next >
Encoding:
Assembly Source File  |  1990-12-07  |  20.2 KB  |  509 lines

  1.         .MODEL  small, pascal, os_dos
  2.         .DOSSEG
  3.         INCLUDE demo.inc
  4.         INCLUDE tsr.inc
  5.  
  6. OpenBox         PROTO
  7. CloseBox        PROTO
  8.  
  9.         .STACK
  10.         .DATA
  11.  
  12. DEFAULT_COLR    EQU     1Eh             ; Default = white on blue (color)
  13. DEFAULT_MONO    EQU     70h             ; Default = reverse video (mono)
  14.  
  15. ; Set ALT + LEFT SHIFT + S as hot key combination. To set multiple shift
  16. ; keys, OR the appropriate values together for the shift value (HOT_SHIFT).
  17.  
  18. HOT_SCAN        EQU     1Fh             ; Hot key scan code (S)
  19. HOT_SHIFT       EQU     shAlt OR shLeft ; Shift value (ALT + LEFT SHIFT)
  20. HOT_MASK        EQU     (shIns OR shCaps OR shNum OR shScroll) XOR 0FFh
  21.  
  22. ROW1            EQU     9               ; Query box begins on row 9
  23. ROW2            EQU     14              ;  and ends on row 14
  24. HEIGHT          EQU     ROW2 - ROW1 + 1 ; Number of rows in query box
  25.  
  26. Box     BYTE    '┌──────────────────────────────────────┐', 0
  27.         BYTE    '│  Enter file name                     │', 0
  28.         BYTE    '│  (press Esc to cancel):              │', 0
  29.         BYTE    '│                                      │', 0
  30.         BYTE    '│                                      │', 0
  31. boxend  BYTE    '└──────────────────────────────────────┘', 0
  32. LEN     EQU     (LENGTHOF boxend) - 1
  33.  
  34. OldPos  WORD    ?                       ; Original cursor position
  35. Handle  WORD    ?                       ; File handle number
  36. FilSpec BYTE    (LEN - 3) DUP(0)        ; ASCIIZ string for file spec
  37.  
  38. ; Fill attribute for prompt box. This is changed by running SNAP with
  39. ; the /Cx switch, where x = new display attribute in hexadecimal. For
  40. ; example, to change the color to yellow on brown for a color monitor,
  41. ; enter
  42. ;         SNAP /C6E
  43. ; where the first digit specifies the background color and the second
  44. ; digit the foreground color. Typical values for x on a monochrome
  45. ; system are
  46. ;       07 normal                 70 reverse video
  47. ;       0F high intensity         78 reverse video, high intensity
  48.  
  49. BoxFill BYTE    DEFAULT_MONO            ; Assume monochrome
  50.  
  51. ; Hold contains the screen text and attributes replaced by the query box.
  52. ; Buffer holds text captured from the screen, with room for 50 rows of 82
  53. ; characters, including carriage return/linefeed. To change Buffer's
  54. ; capacity, replace the dimensions with r * (c + 2) DUP(?), where r and
  55. ; c are row and column count respectively.
  56.  
  57. Hold    BYTE    (HEIGHT * LEN) + 3 DUP(?)
  58. Buffer  BYTE    50 * 82 DUP(?)
  59.  
  60.  
  61.         .CODE
  62.  
  63. ;* Snap - Main procedure for resident program. Called from the Activate
  64. ;* procedure when TSR is invoked by the proper key combination.
  65. ;*
  66. ;* Params:  DS, ES = @data
  67. ;*
  68. ;* Return:  None
  69.  
  70. Snap    PROC    FAR
  71.  
  72.         INVOKE  GetVidConfig            ; Get video information
  73.  
  74.         mov     al, vconfig.mode        ; AL = video mode
  75.         .IF     (al <= 3) || (al == 7)  ; If text mode:
  76.  
  77.         INVOKE  GetCurPos               ; Get original cursor coordinates
  78.         mov     OldPos, ax              ;   and store them
  79.  
  80.         INVOKE  OpenBox                 ; Display query box
  81.  
  82.         mov     bl, vconfig.cols        ; Calculate column
  83.         sub     bl, LEN
  84.         shr     bl, 1
  85.         add     bl, 3
  86.  
  87.         INVOKE  StrInput,               ; Request input
  88.                 ROW1 + 4,               ; Row
  89.                 bl,                     ; Column
  90.                 LEN - 4,                ; Maximum string
  91.                 ADDR FilSpec            ; Address of string buffer
  92.  
  93.         push    ax                      ; Save terminating keypress
  94.         call    CloseBox                ; Restore screen to original state
  95.         pop     ax                      ; Recover key
  96.         .IF     al != ESCAPE            ; If Esc key not pressed:
  97.         call    OpenFile                ; Open (or create) file
  98.  
  99.         .IF     !carry?                 ; If okay:
  100.         call    Capture                 ; Write screen to file
  101.         .ELSE
  102.         mov     ax, 0E07h               ; Write bell character
  103.         int     10h                     ;   (ASCII 7) to console
  104.         .ENDIF                          ; End file-okay test
  105.         .ENDIF                          ; End ESCAPE test
  106.  
  107.         mov     ax, OldPos              ; Recover original cursor position
  108.         mov     bl, ah
  109.  
  110.         INVOKE  SetCurPos,              ; Restore cursor
  111.                 bx, ax                  ; Pass cursor row and column
  112.  
  113.         .ENDIF                          ; End text mode test
  114.  
  115.         retf                            ; Far return to Activate procedure
  116.  
  117. Snap    ENDP
  118.  
  119.  
  120. ;* OpenBox - Saves portion of screen to Hold buffer, then opens a box.
  121. ;*
  122. ;* Uses:    vconfig - Video configuration structure
  123. ;*
  124. ;* Params:  None
  125. ;*
  126. ;* Return:  None
  127.  
  128. OpenBox PROC
  129.  
  130.         mov     dh, ROW1                ; DH = top screen row for box
  131.         mov     dl, vconfig.cols
  132.         sub     dl, LEN
  133.         shr     dl, 1                   ; DL = left col for centered box
  134.         push    dx                      ; Save coords
  135.         sub     ch, ch
  136.         mov     cl, dh                  ; CX = row
  137.         sub     dh, dh                  ; DX = column
  138.         GetVidOffset cx, dx
  139.         mov     si, ax                  ; Get video offset in SI
  140.         mov     bx, HEIGHT              ; BX = number of window rows
  141.         mov     cx, LEN                 ; CX = number of columns
  142.  
  143.         push    ds
  144.         pop     es
  145.         mov     di, OFFSET Hold         ; Point ES:DI to hold buffer
  146.         mov     ax, si
  147.         stosw                           ; Copy video offset to buffer
  148.         mov     ax, bx
  149.         stosw                           ; Number of rows to buffer
  150.         mov     ax, cx
  151.         stosw                           ; Number of cols to buffer
  152.         mov     al, vconfig.cols
  153.         shl     ax, 1                   ; AX = number of video cells/row
  154.         mov     ds, vconfig.sgmnt       ; DS = video segment
  155.  
  156.         .REPEAT
  157.         push    si                      ; Save ptr to start of line
  158.         push    cx                      ;   and number of columns
  159.         .IF     vconfig.adapter == CGA  ; If CGA adapter:
  160.         INVOKE  DisableCga              ; Disable video
  161.         .ENDIF
  162.         rep     movsw                   ; Copy one row to buffer
  163.         .IF     vconfig.adapter == CGA  ; If CGA adapter:
  164.         INVOKE  EnableCga               ; Reenable CGA video
  165.         .ENDIF
  166.         pop     cx                      ; Recover number of columns
  167.         pop     si                      ;   and start of line
  168.         add     si, ax                  ; Point to start of next line
  169.         dec     bx                      ; Decrement row counter
  170.         .UNTIL  zero?                   ; Loop while rows remain
  171.  
  172. ; Screen contents (including display attributes) are now copied to buffer.
  173. ; Next open window, overwriting the screen portion just saved.
  174.  
  175.         push    es
  176.         pop     ds                      ; Restore DS
  177.  
  178.         mov     ax, 0600h               ; Scroll service
  179.         mov     bh, BoxFill             ; BH = fill attribute
  180.         pop     cx                      ; CX = row/col for upper left
  181.         mov     dh, ROW2
  182.         mov     dl, cl
  183.         add     dl, LEN
  184.         dec     dl                      ; DX = row/col for lower right
  185.         int     10h                     ; Blank window area on screen
  186.  
  187. ; Write box frame and text to screen
  188.  
  189.         mov     dx, cx                  ; DX = row/col for upper left
  190.         mov     si, OFFSET Box          ; Point to text
  191.         mov     cx, HEIGHT              ; Number of rows in box
  192.  
  193.         .REPEAT
  194.         push    dx                      ; Save coordinates
  195.         sub     bh, bh
  196.         mov     bl, dh                  ; BX = row
  197.         sub     dh, dh                  ; DX = column   
  198.         INVOKE  StrWrite, bx, dx, si    ; Display one line of box
  199.         pop     dx                      ; Recover coordinates
  200.         inc     dh                      ; Next screen row
  201.         add     si, LEN                 ; Point to next line in box
  202.         inc     si
  203.         .UNTILCXZ
  204.  
  205.         ret
  206.  
  207. OpenBox ENDP
  208.  
  209.  
  210. ;* CloseBox - Restores the original screen text to close the window
  211. ;* previously opened by the OpenBox procedure
  212. ;*
  213. ;* Uses:    vconfig - Video configuration structure
  214. ;*
  215. ;* Params:  None
  216. ;*
  217. ;* Return:  None
  218.  
  219. CloseBox PROC
  220.  
  221.         mov     si, OFFSET Hold
  222.         lodsw
  223.         mov     di, ax                  ; DI = video offset of window
  224.         lodsw
  225.         mov     bx, ax                  ; BX = number of window rows
  226.         lodsw
  227.         mov     cx, ax                  ; CX = number of columns
  228.  
  229.         mov     al, vconfig.cols
  230.         shl     ax, 1                   ; AX = number of video cells/row
  231.  
  232.         .REPEAT
  233.         push    di                      ; Save ptr to start of line
  234.         push    cx                      ;   and number of columns
  235.         .IF     vconfig.adapter == CGA  ; If CGA adapter:
  236.         INVOKE  DisableCga              ; Disable video
  237.         .ENDIF
  238.         rep     movsw                   ; Copy one row to buffer
  239.         .IF     vconfig.adapter == CGA  ; If CGA adapter:
  240.         INVOKE  EnableCga               ; Reenable CGA video
  241.         .ENDIF
  242.         pop     cx                      ; Recover number of columns
  243.         pop     di                      ;   and start of line
  244.         add     di, ax                  ; Point to start of next line
  245.         dec     bx                      ; Decrement row counter
  246.         .UNTIL  zero?                   ; Loop while rows remain
  247.  
  248.         ret
  249.  
  250. CloseBox ENDP
  251.  
  252.  
  253. ;* OpenFile - Opens or creates specified file. Resets file pointer to
  254. ;* end of file so that subsequent text is appended to bottom of file.
  255. ;*
  256. ;* Params:  DS:SI = Pointer to file spec
  257. ;*
  258. ;* Return:  None
  259.  
  260. OpenFile PROC
  261.  
  262.         mov     ax, 3D01h               ; Request DOS to open file
  263.         mov     dx, OFFSET FilSpec      ; DS:DX points to file specification
  264.         int     21h                     ; Open File
  265.         .IF     carry?                  ; If it doesn't exist:
  266.         mov     ah, 3Ch                 ; Request create file
  267.         sub     cx, cx                  ;   with normal attributes
  268.         int     21h                     ; Create File
  269.         .ENDIF
  270.  
  271.         .IF     !carry?                 ; If no error:
  272.         mov     Handle, ax              ; Store file handle
  273.         mov     bx, ax
  274.         mov     ax, 4202h               ; Request DOS to reset file pointer
  275.         sub     cx, cx                  ;   to end of file
  276.         sub     dx, dx
  277.         int     21h                     ; Set File Pointer
  278.         .ENDIF
  279.         ret
  280.  
  281. OpenFile ENDP
  282.  
  283.  
  284. ;* Capture - Copies screen text to Buffer, then writes Buffer to file.
  285. ;*
  286. ;* Uses:    vconfig - Video configuration structure
  287. ;*
  288. ;* Params:  None
  289. ;*
  290. ;* Return:  None
  291.  
  292. Capture PROC
  293.  
  294.         mov     es, vconfig.sgmnt       ; ES points to video segment address
  295.         sub     si, si                  ; ES:SI points to 1st video byte
  296.         sub     bx, bx                  ; BX = index to capture buffer
  297.         mov     dx, 3DAh                ; DX = address of CGA status register
  298.  
  299.         .REPEAT
  300.         sub     ch, ch
  301.         mov     cl, vconfig.cols        ; CX = number of columns in line
  302.         mov     di, cx
  303.         dec     di
  304.         shl     di, 1                   ; ES:DI points to video byte for
  305.         add     di, si                  ;   last column in line
  306.  
  307.         .REPEAT
  308.         .IF     vconfig.adapter == CGA  ; If CGA:
  309.         cli                             ; Disallow interruptions
  310.         .REPEAT
  311.         in      al, dx                  ; Read current video status
  312.         .UNTIL  !(al & 1)               ;   until horizontal retrace done
  313.         .REPEAT
  314.         in      al, dx                  ; Read video status
  315.         .UNTIL  al & 1                  ;   until horizontal retrace starts
  316.         .ENDIF                          ; End CGA retrace check
  317.  
  318.         mov     al, es:[di]             ; Get screen char, working backward
  319.         sti                             ; Reenable interrupts in case CGA
  320.         sub     di, 2                   ; DI points to next character
  321.         .UNTILCXZ (al != ' ')           ; Scan for last non-blank character
  322.  
  323.         .IF     !zero?                  ; If non-blank char found:
  324.         inc     cx                      ; Adjust column counter
  325.         mov     di, si                  ; ES:DI points to start of line
  326.  
  327.         .REPEAT
  328.         .IF     vconfig.adapter == CGA  ; If CGA:
  329.         cli                             ; Disallow interruptions
  330.         .REPEAT
  331.         in      al, dx                  ; Read current video status
  332.         .UNTIL  !(al & 1)               ;   until horizontal retrace done
  333.         .REPEAT
  334.         in      al, dx                  ; Read video status
  335.         .UNTIL  al & 1                  ;   until horizontal retrace starts
  336.         .ENDIF                          ; End CGA retrace check
  337.  
  338.         mov     al, es:[di]             ; Get character, working forward
  339.         sti
  340.         add     di, 2                   ; DI points to next character
  341.         mov     Buffer[bx], al          ; Copy to buffer
  342.         inc     bx
  343.         .UNTILCXZ
  344.         .ENDIF                          ; End check for non-blank char
  345.  
  346.         mov     WORD PTR Buffer[bx], CRLF; Finish line with return/line feed
  347.         add     bx, 2
  348.         mov     al, vconfig.cols
  349.         sub     ah, ah
  350.         shl     ax, 1
  351.         add     si, ax                  ; SI points to start of next line
  352.         dec     vconfig.rows            ; Decrement row count
  353.         .UNTIL  sign?                   ; Repeat for next screen row
  354.  
  355.         mov     ah, 40h                 ; Request DOS Function 40h
  356.         mov     cx, bx                  ; CX = number of bytes to write
  357.         mov     bx, Handle              ; BX = file handle
  358.         mov     dx, OFFSET Buffer       ; DS:DX points to buffer
  359.         int     21h                     ; Write to File
  360.         .IF     (ax != cx)              ; If number of bytes written !=
  361.         stc                             ;   number requested, set carry
  362.         .ENDIF                          ;   flag to indicate failure
  363.  
  364.         pushf                           ; Save carry flag
  365.         mov     ah, 3Eh                 ; Request DOS Function 3Eh
  366.         int     21h                     ; Close File
  367.         popf                            ; Recover carry
  368.         ret
  369.  
  370. Capture ENDP
  371.  
  372.  
  373. @CurSeg ENDS
  374.  
  375. ;* INSTALLATION SECTION - The following code and data are used only
  376. ;* during SNAP's installation phase. When the program terminates
  377. ;* through Function 31h, the above code and data remain resident;
  378. ;* memory occupied by the following code and data segments is returned
  379. ;* to the operating system.
  380.         
  381. DGROUP  GROUP INSTALLCODE, INSTALLDATA
  382.  
  383. INSTALLDATA SEGMENT WORD PUBLIC 'DATA2'
  384.  
  385. IDstr   BYTE    'SNAP DEMO TSR', 0      ; Multiplex identifier string
  386.  
  387. INSTALLDATA ENDS
  388.  
  389. INSTALLCODE SEGMENT PARA PUBLIC 'CODE2'
  390.         ASSUME  ds:@data
  391.  
  392. Begin   PROC    NEAR
  393.  
  394.         mov     ax, DGROUP
  395.         mov     ds, ax                  ; Initialize DS
  396.         mov     ah, 15
  397.         int     10h                     ; Get Video Mode
  398.         .IF     al != 7                 ; If not default monochrome:
  399.         mov     BoxFill, DEFAULT_COLR   ; Reset to default color value
  400.         .ENDIF
  401.  
  402. ; Before calling any of the TSR procedures, initialize global data
  403.  
  404.         INVOKE  InitTsr,                ; Initialize data
  405.                 es,                     ; Segment of PSP
  406.                 ADDR IDstr,             ; Far address of multiplex ID string
  407.                 ADDR BoxFill            ; Far address of memory shared
  408.                                         ;  with multiplex handler
  409.         .IF     ax == WRONG_DOS         ; If DOS version less than 2.0:
  410.         jmp     exit                    ; Exit with message
  411.         .ENDIF
  412.  
  413. ; This section gets the command line argument to determine task:
  414. ;    No argument   = install
  415. ;    /D or -D      = deinstall
  416. ;    /Cx or -Cx    = change box fill attribute to value x
  417.  
  418.         mov     al, 'd'                 ; Search command line for
  419.         call    GetOptions              ;   /D or -D argument
  420.         cmp     ax, NO_ARGUMENT         ; No argument?
  421.         je      installtsr              ; If so, try to install
  422.         cmp     ax, OK_ARGUMENT         ; /D argument found?
  423.         je      deinstalltsr            ; If so, try to deinstall
  424.         mov     al, 'c'                 ; Else search command line for
  425.         call    GetOptions              ;   /C or -C argument
  426.         cmp     ax, BAD_ARGUMENT        ; If neither /D or /C arguments,
  427.         je      exit                    ;   quit with error message
  428.  
  429. ; This section changes the fill attribute of SNAP's prompt box. It converts
  430. ; to binary the two-digit hex number following the /C argument, calls the
  431. ; multiplex handler to find the address of the attribute variable stored in
  432. ; shared memory, then resets the attribute to the new value. It does not
  433. ; verify that the value specified in the command line is a valid two-digit
  434. ; hex number.
  435.  
  436.         mov     ax, es:[di+1]           ; AH = low digit, AL = high digit
  437.         mov     cx, 2                   ; Process two digits
  438.  
  439.         .REPEAT
  440.         sub     al, '0'                 ; Convert digit to binary
  441.         .IF     (al > 9)                ; If not digit 0-9:
  442.         and     al, 00011111y           ; Mask out lower-case bit
  443.         sub     al, 7                   ; Convert A to 10, B to 11, etc
  444.         .ENDIF
  445.         xchg    ah, al                  ; Get next digit in AL
  446.         .UNTILCXZ
  447.  
  448.         mov     cl, 4
  449.         shl     al, cl                  ; Multiply high digit by 16
  450.         or      al, ah                  ; AL = binary value of attribute
  451.         push    ax                      ; Save new attribute
  452.  
  453.         mov     al, 2                   ; Request function 2
  454.         call    CallMultiplex           ; Get shared memory addr in ES:DI
  455.         .IF     ax != IS_INSTALLED      ; If TSR is not installed:
  456.         pop     ax                      ; Clean stack and
  457.         mov     ax, CANT_ACCESS         ;   quit with error message
  458.         jmp     exit
  459.         .ELSE                           ; If TSR is installed:
  460.         pop     ax                      ; Recover new fill attribute in AL
  461.         mov     es:[di], al             ; Write it to resident shared memory
  462.         mov     ax, OK_ACCESS           ; Signal successful completion
  463.         jmp     exit
  464.         .ENDIF
  465.  
  466. ; This section sets up the TSR's interrupt handlers and
  467. ; makes the program memory-resident
  468.  
  469. installtsr:
  470.         push    es                      ; Preserve PSP address
  471.  
  472.         mov     ax, @code
  473.         mov     es, ax
  474.         mov     bx, OFFSET Snap         ; ES:BX points to Snap
  475.         INVOKE  Install,                ; Install handlers
  476.                 HOT_SCAN,               ; Scan code of hot key
  477.                 HOT_SHIFT,              ; Bit value of hot key
  478.                 HOT_MASK,               ; Bit mask for shift hot key
  479.                 es::bx                   ; Far address of Snap procedure
  480.  
  481.         pop     bx                      ; Recover PSP address
  482.         or      ax, ax                  ; If non-zero return code,
  483.         jnz     exit                    ;   exit with appropriate message
  484.         mov     ax, INSTALLCODE         ; Bottom of resident section
  485.         sub     ax, bx                  ; AX = number of paragraphs in
  486.                                         ;   block to be made resident
  487.         INVOKE  KeepTsr,                ; Make TSR memory-resident
  488.                 ax                      ; Resident paragraphs
  489.  
  490. ; This section deinstalls the resident TSR from memory
  491.  
  492. deinstalltsr:
  493.  
  494.         INVOKE  Deinstall               ; Unchain interrupt handlers
  495.  
  496.         .IF     ax > OK_ARGUMENT        ; If successful:
  497.         INVOKE  FreeTsr,                ; Deinstall TSR by freeing memory
  498.                 ax                      ; Address of resident seg
  499.         .ENDIF                          ; Else exit with message
  500. exit:
  501.         INVOKE  FatalError,             ; Exit to DOS with message
  502.                 ax                      ; Error number
  503.  
  504. Begin   ENDP
  505.  
  506. INSTALLCODE ENDS
  507.  
  508.         END     Begin
  509.