home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / SCREEN / SNIPPR24.ZIP / SNIPPER.ASM next >
Encoding:
Assembly Source File  |  1991-03-14  |  32.3 KB  |  991 lines

  1. page 60,132
  2. ; SNIPPER by Tom Kihlken
  3. ;
  4. ; Copyright (c) 1987 by Ziff Communications Co.
  5. ; PC Magazine 1987:  Vol 6/No. 19, October 27, 1987 (Utilities)
  6. ;
  7. ; SNIPPER is a resident utility which allows cutting out a portion
  8. ; of the screen.  The selected portion may be printed, written
  9. ; to disk or entered in the keyboard buffer.  Activate SNIPPER by
  10. ; pressing ALT-W, then position the cursor in the upper left corner of
  11. ; the window using the cursor pad keys,(i.e.,arrows plus Home, End, PgUp v2.3
  12. ; and PgDn).  Press CR to fix the first corner,                v2.3
  13. ; then expand the window with arrow keys.  Finally, type "P" to print,
  14. ; "F" for disk file, "G" to retrieve or CR for a help menu.  Press ESC
  15. ; any time to exit SNIPPER.  When installing SNIPPER, use the optional
  16. ; parameters to expand its internal buffer for displays (such as the
  17. ; EGA) containing more than the standard 25 rows and 80 columns.
  18. ;   SNIPPER  [rows,columns]
  19.  
  20. ; Version 1.0 -    as published.
  21. ; Version 1.1 -    corrects a bug in the INT 21 interrupt routine.
  22. ; Version 1.2 -    runs correctly on the AT&T 6300
  23. ; Version 2.0 -     6/22/88 allow "R" to go to Right Edge.    Jim Turner 71560,3452
  24. ; Version 2.1 -    10/30/88 suggestions from Tom K.    Jim Turner 71560,3452
  25. ; Version 2.2 -    01/25/90 Consolidated.        Tim Farley, Atlanta, GA
  26. ;           (Turner's revisions did not include all of Kihlken's
  27. ;           published fixes, and    he untabified the file).
  28. ;        Added support for Expanded 101/102 key keyboard.
  29. ;        Added scan code to RETURN--some programs check the scan
  30. ;           code, so it needs to be there so RETURN will be processed.
  31. ;        Moved patch locations to fixed spot at 17F and 18F.
  32. ;        Removed call to INT 16 *inside* INT 9 (yikes!).
  33. ;        Made sure all changes since published version are notated.
  34. ;
  35. ;v2.2a    19 May 90 Toad Hall Tweak
  36. ; - A few CS: overrides just to keep things clear
  37. ; - Replaced LEA's with "mov reg,offset" (faster)
  38. ; - Added envseg as a variable at CS:002CH
  39. ;
  40. ; Version 2.3 - Cursor Pad Keys(Home,End,PgUp,PgDn) added by T.Gentile
  41. ;        New & Modified Lines have V2.3 Suffix in Columns 75-78
  42. ;
  43. ;v2.4    14 Mar 91 Toad Hall Tweak
  44. ; - Got a request for trailing space trimming.  Done.
  45. ; - Request to consolidate v2.3 code (but keep v2.2+ fixes).
  46. ; - Request to eliminate direct screen writes (conflict with
  47. ;   speech synthesizers, DeskView).
  48. ;   That's easy to do:  there are NO direct screen writes!
  49. ;   Everything is via the BIOS.
  50.  
  51. ;------------------------------------
  52. ; BIOS_SEG IS THE ROM-BIOS DATA AREA
  53. ;------------------------------------
  54. BIOS_SEG    SEGMENT    AT 0040H
  55.         ORG    0017H                        ;[TF]
  56. kb_flag        DB    ?        ;CURRENT SHIFT STATE        ;[TF]
  57.         ORG    004AH
  58. crt_cols    DB    ?        ;CURRENT NUMBER OF COLUMNS
  59.         ORG    0050H
  60. cursor_posn    DW    8 DUP(?)    ;CURRENT CURSOR LOCATION
  61.         ORG    0062H
  62. active_page    DB    ?        ;ACTIVE PAGE FOR CGA AND EGA
  63.         ORG    0084H
  64. bios_rows    DB    ?        ;LAST ROW NUMBER FOR EGA
  65. BIOS_SEG    ENDS
  66.  
  67. CSEG        SEGMENT
  68.         ASSUME    CS:CSEG,DS:NOTHING
  69.  
  70.         org    2CH        ;v2.2a
  71. envseg        label    word        ;Environment segment        v2.2a
  72.  
  73.         ORG    100H        ;BEGINNING FOR .COM PROGRAMS
  74. Start:        JMP    Initialize    ;INITIALIZATION CODE IS AT END
  75.  
  76. ;--------------------------------
  77. ; DATA AREA USED BY THIS PROGRAM
  78. ;--------------------------------
  79. copyright    DB    "SNIPPER 2.4 (c) 1987 Ziff Communications Co."
  80.         DB    13,10,"PC Magazine ",254," Tom Kihlken"
  81.         DB    13,10,"Hotkey is ALT-W",13,10,"$",1AH
  82.         DB    17 DUP (0)    ;room to patch hot key name    [TF]
  83.  
  84.         DB    "KEY SCAN CODE->"    ;alert snoops to patch    [TF]
  85. hotkey        DB    11H            ;SCAN CODE FOR "W" KEY    [TF]
  86.         DB    "SHIFT MASK---->"    ;alert snoops to patch    [TF]
  87. shift_mask    DB    00001000B        ;MASK FOR ALT KEY    [TF]
  88. ;
  89. installed$    DB    "Already Installed",13,10,"$"
  90. bad_dos$    DB    "Requires DOS 2.0+",13,10,"$"
  91. file_prompt    DB    "Enter Filename: "
  92. filename    DB    "SCREEN.CUT"    ;THE DEFAULT FILENAME
  93.         DB    15 DUP (0)    ;LEAVE ROOM FOR DRIVE AND PATH
  94.  
  95.         EVEN            ;v2.4
  96. oldint09    DD    ?        ;OLD KEYBOARD BREAK INTERRUPT VECTOR
  97. oldint13    DD    ?        ;OLD BIOS DISK IO INTERRUPT VECTOR
  98. oldint16    DD    ?        ;OLD KEYBOARD INTERRUPT VECTOR
  99. oldint21    DD    ?        ;OLD DOS FUNCTION INTERRUPT VECTOR
  100. BUFF_START    EQU    OFFSET Initialize
  101. buff_next    DW    BUFF_START    ;POINTER TO NEXT KEY IN BUFFER
  102. buff_last    DW    BUFF_START    ;POINTER TO LAST KEY IN BUFFER
  103. BUFF_SIZE    EQU    25*(80+2)    ;ROOM FOR 25 ROWS OF 80 COLUMNS
  104. buff_end    DW    BUFF_START+BUFF_SIZE
  105.  
  106. top_left    LABEL    WORD        ;FIRST CORNER OF WINDOW
  107. left_side    DB    0        ;COLUMN NUMBER OF LEFT SIDE
  108. top_row        DB    0        ;ROW NUMBER OF TOP SIDE
  109. bot_right    LABEL    WORD        ;SECOND CORNER OF WINDOW
  110. right_side    DB    ?        ;COLUMN NUMBER OR RIGHT SIDE
  111. bot_row        DB    ?        ;ROW NUMBER OF BOTTOM
  112.  
  113. send_char    DW    ?        ;POINTER TO CHARACTER HANDLER
  114. send_keys    DB    0        ;IF=1, USE KEYSTROKES FROM BUFFER
  115. writ_file    DB    0        ;IF=1, NEED TO WRITE TO DISK
  116. busy_flags    DB    0        ;BIT MASKED AS FOLLOWS:
  117.                     ; 1 - DOS IS ACTIVE
  118.                     ; 2 - BIOS IO IS ACTIVE
  119.                     ; 4 - SNIPPER IS ACTIVE
  120. err_stat    DB    ?        ;ERROR STATUS DURING FILE OUTPUT
  121. dos_stat    DB    0        ;CURRENT DOS FUNCTION
  122. end_flag    DB    0        ;"END"  Key Pressed =1        V2.3
  123. pgdn_flag    DB    0        ;"PGDN" Key Pressed =1        V2.3
  124. home_flag    DB    0        ;"HOME" Key Pressed =1        V2.3
  125. pgup_flag    DB    0        ;"PGUP" Key Pressed =1        V2.3
  126. scrn_rows    DB    ?        ;real screen rows        [TK]
  127.  
  128. help_menu    DB    201,10 DUP(205),187
  129.         DB    186," F - File ",186
  130.         DB    186," P - Print",186
  131.         DB    186," S - Save ",186
  132.         DB    186," G - Get  ",186
  133.         DB    186,"Esc- Quit ",186
  134.         DB    200,10 DUP(205),188
  135.  
  136. ;------------------------------------------------------------------
  137. ; Snipper BUILDS THE WINDOW AND ACCEPTS COMMANDS FROM THE KEYBOARD
  138. ;------------------------------------------------------------------
  139. Snipper        PROC    NEAR
  140.         ASSUME    DS:CSEG, ES:BIOS_SEG
  141.  
  142.         MOV    scrn_rows,24    ;DEFAULT NUMBER OF ROWS        ;[TK]
  143.         MOV    AH,12H                        ;[TK]
  144.         MOV    BL,10H        ;GET EGA INFO            ;[TK]
  145.         INT    10H                        ;[TK]
  146.         CMP    BL,10H        ;DID BL CHANGE?            ;[TK]
  147.         JE    Not_Ega        ;IF NO, EGA IS NOT PRESENT    ;[TK]
  148.         TEST    BYTE PTR ES:[00087H],8 ;IS EGA ACTIVE?        ;[TK]
  149.         JNZ    Not_Ega                        ;[TK]
  150.          MOV    AL,bios_rows                    ;[TK]
  151.          MOV    scrn_rows,AL                    ;[TK]
  152. Not_Ega:                                ;[TK]
  153.         XOR    BX,BX        ;BX IS INCREMENT FOR ROW/COLUMN
  154. Get_Kb_Key1:
  155.         MOV    DX,top_left    ;GET LOCATION OF FIRST CORNER
  156.         ADD    DH,BH        ;ADD IN THE ROW INCREMENT
  157.         ADD    DL,BL        ;ADD IN THE COLUMN INCREMENT
  158.         CMP    DL,0        ;AT LEFT EDGE OF SCREEN?
  159.         JGE    Not_Left_Edge
  160. FORCE_RIGHT:     MOV    DL,crt_cols    ;JUMP TO THE RIGHT EDGE        V2.3
  161.          DEC    DL
  162. Not_Left_Edge:
  163.         CMP    DL,crt_cols    ;AT RIGHT EDGE OF SCREEN YET?
  164.         JB    Not_Right_Edge    ;IF NOT, KEEP MOVING RIGHT
  165. FORCE_LEFT:     XOR    DL,DL        ;IF YES, WRAP TO LEFT EDGE    V2.3
  166. Not_Right_Edge:
  167.         CMP    DH,0        ;AT TOP OF SCREEN YET?
  168.         JGE    Not_At_Top
  169. FORCE_BOTTOM:     MOV    DH,scrn_rows    ;JUMP DOWN TO THE BOTTOM    V2.3
  170. Not_At_Top:
  171.         CMP    DH,scrn_rows    ;AT BOTTOM OF SCREEN?        ;[TK]
  172.         JLE    Not_At_Bottom
  173. FORCE_TOP:     XOR    DH,DH        ;JUMP BACK TO THE TOP        V2.3
  174. Not_At_Bottom:
  175.         MOV    top_left,DX    ;SAVE NEW CORNER LOCATION
  176.         CALL    Rev_Video    ;CHANGE IT TO REVERSE VIDEO
  177.         XOR    AH,AH        ;BIOS KEYBOARD INPUT
  178.         INT    16H        ;GET A KEYSTROKE
  179.         PUSH    AX
  180.         CALL    Rev_Video    ;PUT ATTRIBUTE BACK TO NORMAL
  181.         POP    AX
  182.         CMP    AH,1        ;IS IT ESCAPE?
  183.         JNE    Not_Esc
  184.          RET            ;JUST RETURN TO EXIT
  185.  
  186. Not_Esc:
  187.         MOV    BX,0FF00H    ;INCREMENT TO SUBTRACT ONE ROW
  188.         CMP    AH,48H        ;IS IT UP ARROW?
  189.         JE    Get_Kb_Key1
  190.         MOV    BX,0100H    ;INCREMENT TO ADD ONE ROW
  191.         CMP    AH,50H        ;IS IT DOWN ARROW?
  192.         JE    Get_Kb_Key1
  193.         MOV    BX,0001H    ;INCREMENT TO ADD ONE COLUMN
  194.         CMP    AH,4DH        ;IS IT RIGHT ARROW?
  195.         JE    Get_Kb_Key1
  196.         MOV    BX,00FFH    ;INCREMENT TO SUBTRACT ONE COLUMN
  197.         CMP    AH,4BH        ;IS IT LEFT ARROW?
  198.         JE    Get_Kb_Key1
  199.  
  200.         CMP    AH,47H        ;IS IT HOME KEY?        V2.3
  201.         JE    FORCE_LEFT    ;JUMP TO LEFT SCREEN EDGE    V2.3
  202.         CMP    AH,49H        ;IS IT PGUP KEY?        V2.3
  203.         JE    FORCE_TOP    ;JUMP TO TOP SCRREN EDGE    V2.3
  204.         CMP    AH,4FH        ;IS IT END KEY?            V2.3
  205.         JE    FORCE_RIGHT    ;JUMP TO RIGHT SCREEN EDGE    V2.3
  206.         CMP    AH,51H        ;IS IT PGDN KEY?        V2.3
  207.         JE    FORCE_BOTTOM    ;JUMP TO BOTTOM SCREEN EDGE    V2.3
  208.  
  209.         XOR    BX,BX
  210.         CMP    AL,13        ;IS IT A CARRIAGE RETURN?
  211.         JNE    Not_Cr
  212.          MOV    DX,top_left    ;A CARRIAGE RETURN WAS PRESSED
  213.          MOV    bot_right,DX    ;INITIALIZE THE SECOND CORNER
  214.          CALL    Rev_Video    ;CHANGE IT BACK TO REVERSE VIDEO
  215.          JMP    SHORT Get_Kb_Key2
  216.  
  217. Not_Cr:
  218.         CMP    AH,22H        ;IS IT THE "G" KEY
  219.         JE    Type_Buff    ;IF YES, THEN GET THE WINDOW
  220.          JMP    Get_Kb_Key1    ;JUST GET ANOTHER KEY
  221.  
  222. Type_Buff:
  223.         MOV    send_keys,1    ;SIGNAL TO SEND THE KEYS
  224.         RET
  225.  
  226. Get_Kb_Key2:
  227.         xor    ax,ax        ;handy 0, AH=0            v2.4
  228.         MOV    end_flag,al    ; CLEAR END FLAG        V2.3,4
  229.         MOV    pgdn_flag,al    ; CLEAR PGDN FLAG        V2.3,4
  230.         MOV    home_flag,al    ; CLEAR HOME FLAG        V2.3,4
  231.         MOV    pgup_flag,al    ; CLEAR PGUP FLAG        V2.3,4
  232. ;v2.4 done    XOR    AH,AH
  233.         INT    16H        ;GET A KEYSTROKE
  234. Got_Key2:    MOV    DX,bot_right
  235.         CMP    AH,4BH        ;IS IT LEFT ARROW?        v2.3
  236.         JE    Sub_Col        ;SUBTRACT A COLUMN FROM WINDOW    v2.3
  237.         CMP    AH,4DH        ;IS IT RIGHT ARROW?        v2.3
  238.         JE    Add_Col        ;ADD A COLUMN TO THE WINDOW    v2.3
  239.         CMP    AH,4FH        ;IS IT "END"?            V2.3
  240.         JE    Got_End        ;GO TO RIGHT EDGE OF SCREEN    V2.3
  241.         CMP    AH,51H        ;IS IT "PGDN"?            V2.3
  242.         JE    Got_PgDn    ;GO TO BOTTOM EDGE OF SCREEN    V2.3
  243.         CMP    AH,47H        ;IS IT "HOME"?            V2.3
  244.         JE    Got_Home    ;GO TO LEFT EDGE OF WINDOW    V2.3
  245.         CMP    AH,49H        ;IS IT "PGUP"?            V2.3
  246.         JE    Got_PgUp    ;GO TO TOP EDGE OF WINDOW    V2.3
  247.  
  248.         CMP    AH,48H        ;IS IT UP ARROW?
  249.         JE    Sub_Row        ;SUBTRACT A ROW FROM WINDOW
  250.         CMP    AH,50H        ;IS IT DOWN ARROW?
  251.         JE    Add_Row        ;ADD A ROW TO THE WINDOW
  252.          JMP    Not_Arrow_Key
  253.  
  254. Got_Home:    MOV    home_flag,1    ;"HOME" KEY PRESSED        V2.3
  255. Sub_Col:
  256.         MOV    DX,bot_right    ;2ND CORNER COORDS        V2.3
  257.         DEC    DL        ;SUBTRACT A COLUMN
  258.         CMP    DL,left_side    ;DONT ERASE IT COMPLETELY
  259.         JL    Get_Kb_Key2
  260.          MOV    right_side,DL    ;SAVE NEW RIGHT SIDE COLUMN
  261.          INC    DL
  262.          JMP    SHORT Col_Loop
  263.  
  264. Got_End:    MOV    end_flag,1    ;"END" KEY PRESSED        V2.3
  265.  
  266. Add_Col:
  267.         MOV    DX,bot_right    ;2ND CORNER COORDS        V2.3
  268.         INC    DL        ;ADD A COLUMN
  269.         CMP    DL,crt_cols    ;AT RIGHT EDGE OF SCREEN?
  270.         JAE    Get_Kb_Key2    ;STOP WHEN SCREEN IS FILLED
  271.  
  272.         MOV    right_side,DL    ;SAVE NEW RIGHT SIDE COLUMN
  273. Col_Loop:
  274.         CALL    Rev_Video    ;REVERSE THIS CHARACTER
  275.         DEC    DH        ;MOVE TO NEXT ROW
  276.         CMP    DH,top_row    ;AT TOP ROW YET?
  277.         JGE    Col_Loop    ;LOOP UNTIL AT TOP ROW
  278.         CMP    end_flag,1    ;IF "END", REPEAT TO RIGHT EDGE V2.3
  279.         JE    Add_Col        ;ADD ANOTHER COLUMN        V2.3
  280.         CMP    home_flag,1    ;IF "HOME", REPEAT TO LEFT EDGE    V2.3
  281.         JE    Sub_Col        ;REMOVE ANOTHER COLUMN        V2.3
  282. Get_Kb_K2_Jmp:    JMP    Get_Kb_Key2    ;                V2.3
  283.  
  284. Got_PgUp:    MOV    pgup_flag,1    ;"PGUP" KEY PRESSED        V2.3
  285. Sub_Row:
  286.         MOV    DX,bot_right    ;2ND CORNER COORDS        V2.3
  287.         DEC    DH
  288.         CMP    DH,top_row    ;AT TOP OF WINDOW?
  289.         JL    Get_Kb_K2_Jmp    ;DONT ERASE IT COMPLETELY    v2.3
  290.          MOV    bot_row,DH
  291.          INC    DH
  292.          JMP    SHORT Row_Loop
  293.  
  294. Got_PgDn:    MOV    pgdn_flag,1    ;"PGDN" KEY PRESSED        V2.3
  295. Add_Row:
  296.         MOV    DX,bot_right    ;2ND CORNER COORDS        V2.3
  297.         INC    DH
  298.         CMP    DH,scrn_rows    ;AT BOTTOM OF SCREEN?        [TK]
  299.         JG    Get_Kb_K2_Jmp    ;STOP WHEN SCREEN IS FILLED    v2.3
  300.  
  301.         MOV    bot_row,DH
  302. Row_Loop:
  303.         CALL    Rev_Video    ;REVERSE THIS CHARACTER
  304.         DEC    DL        ;MOVE TO NEXT COLUMN
  305.         CMP    DL,left_side    ;AT LEFT EDGE YET?
  306.         JGE    Row_Loop    ;CONTINUE UNTIL AT LEFT EDGE
  307.         CMP    pgdn_flag,1    ;IF "PGDN", REPEAT TO BOTTOM EDGE V2.3
  308.         JE    Add_Row        ;ADD ANOTHER ROW        V2.3
  309.         CMP    pgup_flag,1    ;IF "PGUP", REPEAT TO TOP EDGE    V2.3
  310.         JE    Sub_Row        ;REMOVE ANOTHER ROW        V2.3
  311.  
  312.          JMP    Get_Kb_Key2
  313.  
  314. Not_Arrow_Key:
  315.         CMP    AH,19H        ;WAS IT THE "P" KEY?
  316.         JNE    Not_P
  317.          MOV    send_char,OFFSET Print_Char
  318.          JMP    Read_Window
  319.  
  320. Not_P:
  321.         MOV    buff_next,BUFF_START
  322.         MOV    buff_last,BUFF_START
  323.         MOV    send_char,OFFSET Buff_Char
  324.  
  325.         CMP    AH,1FH            ;WAS IT THE "S" KEY?
  326.         JNE    Not_S
  327.          MOV    send_char,OFFSET Buff_Char
  328.          JMP    Read_Window
  329.  
  330. Not_S:
  331.         CMP    AH,22H            ;IS IT THE "G" KEY
  332.         JNE    Not_G
  333.          MOV    send_keys,1
  334.          JMP    Read_Window
  335.  
  336. Not_G:
  337.         CMP    AH,21H            ;IS IT THE "F" KEY
  338.         JNE    Not_F
  339.  
  340.         MOV    writ_file,0
  341.         CALL    Get_Filename
  342.         CMP    writ_file,-1        ;WAS ESCAPE REQUESTED?
  343.         JE    Erase_Box
  344.  
  345.         CALL    Read_Window
  346.         MOV    writ_file,1
  347.         TEST    busy_flags,00000011B    ;IS INT21 OR INT13 BUSY?
  348.         JNZ    Return            ;IF YES, WAIT TILL LATER
  349.          CALL    Write_To_File        ;IF NOT, DO IT NOW
  350. Return:
  351.         RET
  352.  
  353. Not_F:
  354.         CMP    AH,1            ;IS IT ESCAPE?
  355.         JE    Erase_Box        ;IF YES, ERASE BOX AND EXIT
  356.          CMP    AL,13            ;IS IT A CARRIAGE RETURN?
  357.          JE    Display_Help        ;IF YES, DISPLAY HELP
  358.           JMP    Get_Kb_Key2        ;OTHERWISE JUST GET ANOTHER KEY
  359.  
  360. Erase_Box:
  361.         MOV    send_char,OFFSET Return    ;next procedure is Return
  362.         JMP    Read_Window
  363.  
  364. Display_Help:
  365.         CALL    Exchange_Help    ;PUT UP THE HELP MENU
  366.         XOR    AH,AH
  367.         INT    16H        ;GET ANOTHER KEYSTROKE
  368.         PUSH    AX        ;SAVE THE KEYSTROKE
  369.         CALL    Exchange_Help    ;PULL DOWN THE HELP MENU
  370.         POP    AX        ;GET BACK THE KEYSTROKE
  371.         JMP    Got_Key2
  372.  
  373. ;*********************************************************************
  374. Rev_Video:
  375.         CALL    Read_Char    ;READ CHARACTER AND ATTRIBUTE
  376.         MOV    BL,AH        ;SAVE ATTRIBUTE IN BL
  377.         AND    BL,10001000B    ;GET BLINK AND INTENSITY BITS
  378.         AND    AH,01110111B    ;NOW LOOK ONLY AT COLOR BITS
  379.         MOV    CL,4        ;ROTATE FOUR COUNTS
  380.         ROR    AH,CL        ;ROTATE FOREGROUND AND BACKGROUND
  381.         OR    BL,AH        ;PUT BACK BLINK AND INTENSITY BITS
  382.         CALL    Display_Char    ;WRITE CHARACTER AND ATTRIBUTE
  383.         RET
  384. ;*********************************************************************
  385. ;v2.4    Let's do our trailing space trimming here
  386. ;    Old code:
  387.  
  388. Read_Window:
  389.         MOV    DX,top_left    ;GET LOCATION OF FIRST CORNER
  390. Read_Loop:
  391.         xor    si,si        ;init space counter
  392. ReadR_Loop:
  393.         CALL    Rev_Video    ;PUT ATTRIBUTE BACK TO NORMAL
  394.         CALL    Read_Char    ;READ THE CHARACTER (returned in AL)
  395.         cmp    al,' '        ;space?
  396.         jnz    NonSpace    ;nope
  397.          inc    si            ;yep, bump counter
  398.          jmp    short Skip_Space    ;skip, don't send it
  399.  
  400. ;We've hit a non-space char. If there are any accumulated spaces,
  401. ;we must send them now.
  402. NonSpace:
  403.         or    si,si        ;any unsent spaces accrued?
  404.         jz    No_SpaceCnt    ;nope, send this char
  405.  
  406.         push    ax        ;save this char
  407. Space_Loop:
  408.         mov    al,' '        ;space to [send_char]
  409.         call    [send_char]    ;call to the pointer
  410.         dec    si        ;count down
  411.         jnz    Space_Loop    ;send all accrued spaces
  412.  
  413.         pop    ax        ;restore original non-space char
  414. No_SpaceCnt:
  415.         call    [send_char]    ;call to the pointer
  416. Skip_Space:
  417.         inc    dl        ;next char in row
  418.         cmp    dl,right_side    ;at the right border yet?
  419.         jle    ReadR_Loop    ;nope, do all chars in this row
  420.  
  421. ;If there are any accumulated spaces, they're trailing spaces
  422. ;and we can ignore them.
  423.  
  424.         CALL    Cr_Lf        ;SEND CR-LF AFTER EACH ROW
  425.         INC    DH        ;MOVE TO NEXT ROW
  426.         MOV    DL,left_side    ;BACK TO LEFT EDGE
  427.         CMP    DH,bot_row    ;AT THE BOTTOM BORDER YET?
  428.         JLE    Read_Loop    ;READ ENTIRE WINDOW
  429.         RET
  430.  
  431. ;*********************************************************************
  432. Cr_Lf:
  433.         MOV    AL,13
  434.         CALL    [send_char]    ;SEND A CARRIAGE RETURN
  435.         MOV    AL,10
  436.         CALL    [send_char]    ;SEND A LINE FEED
  437.         RET
  438.  
  439. ;*********************************************************************
  440. Display_Char:
  441.         PUSH    BX        ;SAVE THE ATTRIBUTE
  442.         CALL    Get_Curs_Addr    ;GET ADDRESS OF BIOS CURSOR
  443.         MOV    ES:[BX],DX    ;TELL BIOS WHERE THE CURSOR IS
  444.         POP    BX        ;GET BACK THE ATTRIBUTE
  445.         MOV    BH,active_page    ;GET ACTIVE PAGE
  446.         PUSH    CX        ;SAVE THE LOOP COUNT
  447.         MOV    CX,1        ;WRITE 1 CHARACTER
  448.         MOV    AH,9        ;WRITE CHARACTER AND ATTRIBUTE
  449.         INT    10H
  450.         POP    CX        ;RECOVER LOOP COUNT
  451.         RET            ;DONE WRITING THE CHARACTER
  452. ;*********************************************************************
  453. Read_Char:
  454.         CALL    Get_Curs_Addr    ;GET ADDRESS OF BIOS CURSOR
  455.         MOV    ES:[BX],DX    ;TELL BIOS WHERE THE CURSOR IS
  456.         MOV    BH,active_page    ;GET ACTIVE PAGE
  457.         MOV    AH,8        ;BIOS FUNCTION TO READ CHARACTER
  458.         INT    10H        ;READ THE CHARACTER/ATTRIBUTE
  459.         RET
  460. ;*********************************************************************
  461. Print_Char:
  462.         PUSH    DX
  463.         XOR    AH,AH        ;USE FUNCTION 0
  464.         XOR    DX,DX        ;PRINTER NUMBER 0
  465.         INT    17H        ;BIOS PRINT CHARACTER FUNCTION
  466.         ROR    AH,1        ;LOOK AT BIT ZERO
  467.         JNC    Print_Ok    ;DID A TIMEOUT OCCUR?
  468.          MOV    send_char,OFFSET Return    ;new send_char function
  469. Print_Ok:
  470.         POP    DX
  471.         RET            ;DONE PRINTING CHARACTER
  472. ;*********************************************************************
  473. Buff_Char:
  474.         MOV    BX,buff_last    ;GET LOCATION OF LAST CHARACTER
  475.         MOV    [BX],AL        ;PUT THE CHARACTER IN BUFFER
  476.         INC    BX        ;ADVANCE THE POINTER
  477.         MOV    buff_last,BX    ;CHECK FOR BUFFER FULL
  478.         CMP    BX,buff_end    ;IS THE BUFFER FULL YET?
  479.         JNE    Buff_Ok        ;IF NOT, KEEP GOING
  480.          MOV    send_char,OFFSET Return    ;new send_char function
  481. Buff_Ok:
  482.         RET            ;NOW IT'S IN THE BUFFER
  483. ;*********************************************************************
  484. Get_Curs_Addr:
  485.         MOV    BL,active_page    ;GET THE CURRENT PAGE NUMBER
  486.         XOR    BH,BH        ;CONVERT TO A WORD OFFSET
  487.         SHL    BX,1        ;TIMES TWO FOR A WORD
  488.         ADD    BX,OFFSET cursor_posn    ;ADD IN BASE ADDRESS
  489. Get_Ret:                ;handy return            v2.4
  490.         RET
  491. ;*********************************************************************
  492. Exchange_Help:
  493.         XOR    DX,DX        ;START AT TOP LEFT CORNER
  494.         mov    si,offset help_menu    ;v2.2a
  495. Exchange_Loop:
  496.         CMP    DL,12        ;AT LAST COLUMN IN THIS ROW YET?
  497.         JL    Swap_Char
  498.          XOR    DL,DL        ;BACK TO FIRST COLUMN
  499.          INC    DH        ;DO THE NEXT ROW
  500.          CMP    DH,7        ;AT LAST ROW YET?
  501. ;v2.4         JL    Swap_Char    ;QUIT WHEN LAST ROW IS DONE
  502. ;v2.4          RET
  503.         jnl    Get_Ret        ;quit when last row is done    v2.4
  504. Swap_Char:
  505.         CALL    Read_Char    ;READ CHARACTER AT THIS POSITION
  506.         XCHG    AL,CS:[SI]    ;SWAP WITH THE HELP TEXT
  507.         MOV    BL,AH        ;ATTRIBUTE IS THE SAME
  508.         CALL    Display_Char    ;PUT NEW CHARACTER ON SCREEN
  509.         INC    DL        ;POINT TO NEXT POSITION
  510.         INC    SI
  511.         JMP    Exchange_Loop
  512.  
  513. ;*********************************************************************
  514. Get_Filename:
  515.         mov    si,offset file_prompt    ;point to prompt for source v2.2a
  516.         XOR    DI,DI        ;USE THE PSP FOR BUFFER
  517.         XOR    DX,DX        ;PUT PROMPT AT TOP LEFT CORNER
  518.         MOV    CX,40        ;USE MAX OF 40 CHARACTERS
  519. Display_Prompt:
  520.         PUSH    CX        ;SAVE LOOP COUNT
  521.         CALL    Read_Char    ;GET CHARACTER ON THIS LINE
  522.         MOV    CS:[DI],AX    ;STORE IT IN THE PSP
  523.         INC    DI        ;ADD TWO FOR NEXT CHARACTER
  524.         INC    DI
  525.         MOV    AL,CS:[SI]    ;GET NEXT PROMPT CHARACTER
  526.         INC    SI        ;NEXT CHARACTER IN PROMPT
  527.         MOV    BL,47H        ;ATTRIBUTE FOR PROMPT
  528.         CALL    Display_Char    ;PUT UP THE PROMPT CHARACTER
  529.         INC    DL        ;POINT TO NEXT COLUMN
  530.         POP    CX        ;GET BACK LOOP COUNT
  531.         LOOP    Display_Prompt    ;ENTIRE PROMPT AND FILENAME
  532.  
  533. Find_Last_Letter:
  534.         DEC    SI        ;BACKUP TO LAST LETTER
  535.         DEC    DL        ;BACKUP TO LAST COLUMN
  536.         CMP    BYTE PTR [SI],0    ;IS THIS A LETTER?
  537.         JE    Find_Last_Letter;BACKUP    UNTILL A LETTER IS FOUND
  538.  
  539.         INC    DL        ;PUT BLINKING BOX AT LAST LETTER
  540. Read_Kb:
  541.         MOV    AL,219        ;ASCII FOR BOX CHARACTER
  542.         MOV    BL,47H+80H    ;MAKE IT A BLINKING BOX CHARACTER
  543.         CALL    Display_Char    ;WRITE THE BLINKING BOX
  544.  
  545.         XOR    AH,AH        ;0, GET NEXT KEY
  546.         INT    16H        ;BIOS KEYBOARD INPUT
  547.         CMP    AL,13        ;IS IT A CARRIAGE RETURN?
  548.         JE    Erase_Prompt
  549.         CMP    AL,8        ;IS IT A BACKSPACE?
  550.         JE    Back_Space
  551.         CMP    AH,1        ;IS IT ESCAPE?
  552.         JE    Esc_Ret
  553.         CMP    AL,"."        ;IS IT A VALID LETTER?
  554.         JL    Read_Kb
  555.         CMP    AL,"z"        ;IS IT A VALID LETTER?
  556.         JG    Read_Kb
  557.         CMP    DL,39        ;ONLY ALLOW 40 CHARACTERS
  558.         JGE    Read_Kb
  559. ;Tty_Key:
  560.         MOV    BL,47H        ;ATTRIBUTE FOR FILENAME
  561.         CALL    Display_Char    ;WRITE THE LETTER
  562.         INC    DL        ;MOVE TO NEXT COLUMN
  563.         JMP    Read_Kb        ;GET ANOTHER KEYSTROKE
  564.  
  565. Back_Space:
  566.         CMP    DL,16        ;AT BEGINNING OF LINE?
  567.         JLE    Read_Kb        ;IF YES, CAN'T BACKUP FROM HERE
  568.          xor    al,al        ;WRITE A NORMAL BLANK (ASCII 0) v2.2a
  569.          MOV    BL,47H        ;ATTRIBUTE FOR FILENAME
  570.          CALL    Display_Char    ;WRITE THE LETTER
  571.          DEC    DL        ;BACKUP THE CURSOR
  572.          JMP    Read_Kb        ;THEN GET THE NEXT KEY
  573.  
  574. Esc_Ret:
  575.         MOV    writ_file,-1    ;INDICATE ESCAPE IS REQUESTED
  576. Erase_Prompt:
  577.         XOR    AL,AL        ;GET RID OF THE CURSOR
  578.         CALL    Display_Char    ;WRITE THE LETTER
  579.         mov    di,offset file_prompt    ;copy to filename    v2.2a
  580.         XOR    SI,SI        ;COPY FROM PSP
  581.         XOR    DX,DX        ;PROMPT IS AT ROW ZERO
  582.         MOV    CX,40        ;COPY ALL 40 CHARACTERS
  583. Erase_Loop:
  584.         CALL    Read_Char    ;GET CHARACTER ON THIS LINE
  585.         MOV    CS:[DI],AL    ;PUT IN BACK IN MEMORY
  586.         INC    DI
  587.         MOV    AX,CS:[SI]    ;GET THE ORIGINAL CHARACTER BACK
  588.         MOV    BL,AH        ;PUT ATTRIBUTE INTO BL
  589.         INC    SI
  590.         INC    SI
  591.         CALL    Display_Char    ;WRITE ORIGINAL CHARACTER
  592.         INC    DL        ;MOVE TO NEXT COLUMN
  593.         LOOP    Erase_Loop    ;ERASE THE ENTIRE PROMPT
  594.         RET
  595. Snipper        ENDP
  596.  
  597. ;---------------------------------------------------------------------
  598. ; THIS COPIES THE BUFFER CONTENTS TO A FILE. IT SHOULD ONLY BE CALLED
  599. ; WHEN DOS IS IN A STABLE AND REENTRANT CONDITION.
  600. ;---------------------------------------------------------------------
  601. Write_To_File    PROC    NEAR
  602.         ASSUME    DS:NOTHING, ES:NOTHING
  603.  
  604.         MOV    CS:writ_file,0    ;TURN OFF REQUEST FLAG        v2.2a
  605.         PUSH    AX        ;MUST PRESERVE ALL REGISTERS
  606.         PUSH    BX
  607.         PUSH    CX
  608.         PUSH    DX
  609.         PUSH    DS
  610.         PUSH    ES
  611.         mov    ax,CS        ;larger than push/pop        v2.2a
  612.         mov    DS,ax        ;.. but much faster        v2.2a
  613.         ASSUME    DS:CSEG        ;DS POINTS TO OUR CODE SEGMENT
  614.         MOV    AX,3524H    ;GET DOS CRITICAL ERROR VECTOR
  615.         INT    21H        ;DOS FUNCTION TO GET VECTOR
  616.         PUSH    BX        ;SAVE OLD VECTOR ON STACK
  617.         PUSH    ES
  618.  
  619. ; REPLACE THE DOS SEVERE ERROR INTERRUPT WITH OUR OWN ROUTINE.
  620.  
  621.         MOV    DX,OFFSET NewInt24
  622.         MOV    AX,2524H    ;SETUP TO CHANGE INT 24h VECTOR
  623.         INT    21H        ;CHANGE DOS SEVERE ERROR VECTOR
  624.         MOV    DX,OFFSET filename ;POINT TO FILENAME
  625.  
  626. ; FIRST TRY TO OPEN THE FILE.  IF DOS RETURNS WITH THE CARRY FLAG SET,
  627. ; THE FILE DIDN'T EXIST AND WE MUST CREATE IT.  ONCE THE FILE IS OPENED,
  628. ; ADVANCE THE FILE POINTER TO THE END OF FILE TO APPEND.
  629.  
  630.         MOV    AX,3D02H    ;DOS FUNCTION TO OPEN FILE
  631.         INT    21H        ;DOS WILL RETURN WITH CARRY FLAG
  632.         JC    File_Not_Found    ;SET IF FILE DOESN'T EXIST.
  633.  
  634.         MOV    BX,AX        ;KEEP HANDLE IN BX
  635.         XOR    CX,CX        ;MOVE DOS FILE POINTER TO THE
  636.         XOR    DX,DX        ;END OF THE FILE. THIS LETS US
  637.         MOV    AX,4202H    ;APPEND THIS TO AN EXISTING FILE
  638.         INT    21H        ;DOS FUNCTION TO MOVE POINTER
  639.         JNC    Write_File    ;IF NO ERROR, CONTINUE TO WRITE
  640. Dos_Error:
  641.         CMP    err_stat,0    ;DID A SEVERE ERROR OCCUR?
  642. ;v2.2a        JNE    Rep_Vector    ;IF SEVERE ERROR, JUST QUIT
  643. ;v2.2a        JMP    SHORT Close_File;JUST CLOSE THE FILE
  644.         jz    Close_File    ;no error, just close file    v2.2a
  645.         jmp    short Rep_Vector    ;if severe error, quit    v2.2a
  646.  
  647. File_Not_Found:    CMP    err_stat,0    ;DID A SEVERE ERROR OCCUR?
  648.         JNE    Rep_Vector    ;IF SEVERE ERROR, JUST QUIT
  649.  
  650.         MOV    CX,0020H    ;ATTRIBUTE FOR NEW FILE
  651.         MOV    AH,3CH        ;CREATE FILE FOR WRITING
  652.         INT    21H        ;DOS FUNCTION TO CREATE FILE
  653.         JC    Dos_Error    ;ON ANY ERROR, TAKE JUMP
  654.  
  655.         MOV    BX,AX        ;SAVE HANDLE IN BX
  656. Write_File:    MOV    DX,BUFF_START    ;POINT TO BUFFER
  657.         MOV    CX,buff_last    ;GET BUFFER POINTER
  658.         SUB    CX,DX        ;NUMBER OF CHARS IN BUFFER
  659.         MOV    AH,40H        ;DOS WRITE TO A DEVICE FUNCTION
  660.         INT    21H        ;WRITE TO THE FILE
  661. Close_File:
  662.         MOV    AH,3EH        ;DOS FUNCTION TO CLOSE THE FILE
  663.         INT    21H
  664. Rep_Vector:
  665.         POP    DS        ;GET INT 24H VECTOR FROM STACK
  666.         POP    DX
  667.         MOV    AX,2524H    ;RESTORE CRITICAL ERROR VECTOR
  668.         INT    21H        ;DOS FUNCTION TO CHANGE VECTOR
  669.         POP    ES        ;FINALLY RESTORE ALL REGISTERS
  670.         POP    DS
  671.         POP    DX
  672.         POP    CX
  673.         POP    BX
  674.         POP    AX
  675.         RET            ;FINISHED WRITING TO DISK
  676. Write_To_File    ENDP
  677. ;---------------------------------------------------------------------
  678. ; INTERRUPT 09 ROUTINE.  WATCH FOR TRIGGER KEY TO POP UP.
  679. ;---------------------------------------------------------------------
  680. NewInt09    PROC    FAR
  681.         ASSUME    DS:NOTHING, ES:NOTHING
  682.         STI            ;ALLOW OTHER INTERRUPTS
  683.         PUSH    AX        ;MUST SAVE PROCESSOR STATE
  684.         IN    AL,60H        ;GET THE SCAN CODE
  685.         CMP    AL,CS:[hotkey]    ;IS IT THE HOT KEY?        [TF]
  686.         JE    Trigger        ;IF YES, CHECK THE MASK
  687. Int09_Exit:    POP    AX        ;RESTORE THE PROCESSOR STATE
  688.         JMP    CS:oldint09    ;CONTINUE WITH ROM ROUTINE    v2.2a
  689.  
  690. Trigger:
  691.         PUSH    DS                        ;[TF]
  692.         MOV    AX,BIOS_SEG    ;ES POINTS TO BIOS DATA AREA    ;[TF]
  693.         MOV    DS,AX                        ;[TF]
  694.         ASSUME    DS:BIOS_SEG                    ;[TF]
  695.         MOV    AL,kb_flag    ;GET KEYBOARD STATUS FROM BIOS    ;[TF]
  696.         POP    DS                        ;[TF]
  697.         ASSUME    DS:NOTHING                    ;[TF]
  698.  
  699.         AND    AL,0FH            ;Take lower four bits
  700.         CMP    AL,CS:[shift_mask]    ;IS ALT KEY DOWN?    [TF]
  701.         JNZ    Int09_Exit        ;IF NOT, IGNORE IT
  702.         TEST    CS:busy_flags,00000100B    ;IS Snipper ALREADY ACTIVE? v2.2a
  703.         JNZ    Int09_Exit        ;IF ACTIVE, THEN EXIT
  704.  
  705.         OR    CS:busy_flags,00000100B    ;IT'S ACTIVE NOW    v2.2a
  706.         PUSHF                ;fake interrupt
  707.         CALL    CS:oldint09        ;LET ROM PROCESS THE KEY  v2.2a
  708.         PUSH    BX            ;MUST PRESERVE ALL REGISTERS
  709.         PUSH    CX
  710.         PUSH    DX
  711.         PUSH    BP
  712.         PUSH    SI
  713.         PUSH    DI
  714.         PUSH    DS
  715.         PUSH    ES
  716.         mov    ax,CS        ;set DS to CSEG            v2.2a
  717.         mov    DS,ax        ;larger, but faster        v2.2a
  718.         MOV    AX,BIOS_SEG    ;ES POINTS TO BIOS DATA AREA
  719.         MOV    ES,AX
  720.         ASSUME    DS:CSEG, ES:BIOS_SEG
  721.  
  722.         CALL    Get_Curs_Addr    ;CURSOR ADDRESS FOR THIS PAGE
  723.         PUSH    ES:[BX]        ;SAVE CURSOR POSITION
  724.         CALL    Snipper        ;DO THE WINDOW
  725.         CALL    Get_Curs_Addr    ;CURS0R ADDRESS FOR THIS PAGE
  726.         POP    ES:[BX]        ;GET BACK CURSOR  POSITION
  727.         AND    busy_flags,11111011B  ;Snipper IS NOT ACTIVE
  728.  
  729.         POP    ES        ;RESTORE ALL REGISTERS
  730.         POP    DS
  731.         POP    DI
  732.         POP    SI
  733.         POP    BP
  734.         POP    DX
  735.         POP    CX
  736.         POP    BX
  737.         POP    AX
  738.         IRET            ;NOW WERE ALL DONE
  739. NewInt09    ENDP
  740. ;---------------------------------------------------------------------
  741. ; INTERRUPT 13 ROUTINE. SET BIOS BUSY BIT
  742. ;---------------------------------------------------------------------
  743. NewInt13    PROC    FAR
  744.         ASSUME    DS:NOTHING, ES:NOTHING
  745.  
  746.         OR    CS:busy_flags,00000010B    ;SET BIOS BUSY BIT    v2.2a
  747.         PUSHF                ;fake interrupt
  748.         CALL    CS:oldint13        ;DO THE BIOS FUNCTION    v2.2a
  749.         PUSHF                ;SAVE RESULT FLAGS
  750.         AND    CS:busy_flags,11111101B    ;CLEAR BIOS BUSY BIT    v2.2a
  751.         POPF                ;GET BACK RESULT FLAGS
  752.         STI                ;MUST RETURN WITH INTERUPTS ON
  753.         RET    2            ;RETURN BIOS RESULT FLAGS
  754.  
  755. NewInt13    ENDP
  756. ;---------------------------------------------------------------------
  757. ; INTERRUPT 16 ROUTINE. INSERT KEYSTROKES FROM BUFFER
  758. ;---------------------------------------------------------------------
  759. NewInt16    PROC    FAR
  760.         ASSUME    DS:NOTHING, ES:NOTHING
  761.         PUSH    BX
  762.         CMP    CS:send_keys,1    ;SENDING KEYS FROM BUFFER?    v2.2a
  763.         JE    Insert_Key    ;IF YES, THEN GET NEXT ONE
  764.         CMP    CS:writ_file,1    ;ANYTHING TO WRITE TO DISK?    v2.2a
  765.         JE    Check_Dos_Stat    ;IF YES, THIS IS THE TIME
  766. Bios_Kb:
  767.         POP    BX
  768.         JMP    CS:oldint16    ;JUST DO NORMAL KB ROUTINE    v2.2a
  769.  
  770. Check_Dos_Stat:
  771.         CMP    CS:dos_stat,0AH    ;DOING READ STRING?        v2.2a
  772.         JE    Begin_Now    ;IF YES, IT'S SAFE TO BEGIN
  773.          CMP    CS:dos_stat,8    ;DOING KEYBOARD INPUT?        v2.2a
  774.          JNE    Bios_Kb        ;IF YES, IT'S SAFE TO BEGIN
  775. Begin_Now:
  776.         STI            ;GET INTERRUPTS BACK ON
  777.         CALL    Write_To_File    ;EMPTY THE BUFFER
  778.         JMP    Bios_Kb        ;CONTINUE WITH BIOS ROUTINE
  779.  
  780. Insert_Key:
  781.         STI            ;INTERRUPTS BACK ON
  782.         MOV    BX,CS:buff_next    ;GET ADDRESS OF NEXT BYTE    v2.2a
  783.         CMP    BX,CS:buff_last    ;AT END OF BUFFER YET?        v2.2a
  784.         JL    Get_A_Key    ;IF NOT, GET THE NEXT ONE
  785.          MOV    CS:send_keys,0    ;WHEN DONE, TURN OFF SEND SWITCH v2.2a
  786. Get_A_Key:
  787.         MOV    AL,CS:[BX]    ;GET THE NEXT KEY CODE
  788.         CMP    AL,10        ;IS IT A LINE FEED?
  789.         JNE    Not_Lf        ;DONT RETURN THE LINE FEEDS
  790.          INC    CS:buff_next    ;SKIP TO NEXT KEY        v2.2a
  791.          JMP    Insert_Key
  792.  
  793. Not_Lf:
  794.         CMP    AH,1        ;REQUEST FOR STATUS ONLY?
  795.         JE    Return_Status    ;IF YES, RETURN STATUS ONLY
  796.         CMP    AH,11H        ;Request for ENHANCED status?    [TF]
  797.         JE    Return_Status    ;If yes, return that status    [TF]
  798.         or    ah,ah        ;request to get the next key?    v2.2a
  799.         JE    Return_Key    ;If yes, return that key    [TF]
  800.         CMP    AH,10H        ;Get key on ENHANCED keyboard?    [TF]
  801.         JNE    Bios_Kb        ;IF NOT, IGNORE THIS FUNCTION
  802. Return_Key:                                ;[TF]
  803.         INC    BX        ;REMOVE THIS KEY FROM OUR BUFFER
  804.         MOV    CS:buff_next,BX    ;SAVE THE POINTER TO NEXT KEY    v2.2a
  805. Return_Status:
  806.         CMP    AL,0DH        ;Is this a Carriage Return?    [TF]
  807.         JNE    Next_Key1    ;Nope, just pass it.        [TF]
  808.          MOV    AH,01CH        ;Put in proper scan code for CR    [TF]
  809.          JMP    short Next_Key2    ;And send it            v2.2a
  810. Next_Key1:                                ;[TF]
  811.         XOR    AH,AH        ;Scan code of zero        [TF]
  812. Next_Key2:
  813.         OR    BL,1        ;CLEAR ZERO FLAG TO INDICATE A
  814.         POP    BX        ;KEY IS AVAILIABLE
  815.         RET    2        ;RETURN WITH THESE FLAGS
  816. NewInt16    ENDP
  817. ;---------------------------------------------------------------------
  818. ; INTERRUPT 21 ROUTINE.  THIS ROUTINE IS USED TO MONITOR DOS FUNCTION
  819. ; CALLS. IF THE BUFFER NEEDS TO BE FLUSHED, IT WIL BE DONE HERE.
  820. ;---------------------------------------------------------------------
  821. NewInt21    PROC    FAR
  822.         ASSUME    DS:NOTHING, ES:NOTHING
  823.  
  824.         PUSHF            ;SAVE ENTRY FLAGS        ;[TK]
  825.  
  826.         STI            ;ALLOW INTERRUPTS
  827.         CMP    AH,4BH        ;IF EXEC            ;[TK]
  828.         JNE    Not_Exec                    ;[TK]
  829.          POPF                            ;[TK]
  830.          JMP    CS:oldint21    ;GO DIRECT            ;[TK]
  831.  
  832. Not_Exec:
  833.         OR    AH,AH        ;DOING FUNCTION ZERO?
  834.         JNE    Not_Zero
  835.          MOV    AH,4CH        ;IF YES, CHANGE IT TO A 4CH
  836. Not_Zero:
  837.         OR    CS:busy_flags,00000001B    ;SET DOS BUSY BIT    v2.2a
  838.         MOV    CS:dos_stat,AH    ;                v2.2a
  839.         POPF            ;RESTORE ORIGINAL FLAGS        ;[TK]
  840.         PUSHF            ;SIMULATE AN INTERRUPT
  841.         CALL    CS:oldint21    ;DO THE DOS FUNCTION
  842.         PUSHF            ;SAVE THE RESULT FLAGS
  843.         AND    CS:busy_flags,11111110B    ;CLEAR DOS BUSY BIT    v2.2a
  844.         CMP    CS:writ_file,1    ;ANYTHING TO WRITE TO DISK?    v2.2a
  845.         JNE    No_Write    ;IF NOT JUST RETURN
  846.          CALL    Write_To_File    ;SAFE TO ACCESS DISK NOW
  847. No_Write:
  848.         POPF            ;RECOVER DOS RESULT FLAGS    ;[TK]
  849.         STI                            ;[TK]
  850.         RET    2        ;RETURN WITH DOS RESULT FLAGS
  851. NewInt21    ENDP
  852.  
  853. ;---------------------------------------------------------------------
  854. ; NEW INTERRUPT 24H (CRITICAL DOS ERROR).  THIS INTERRUPT IS ONLY IN
  855. ; EFFECT ONLY DURING A WRITE SCREEN.  IT IS REQUIRED TO SUPPRESS THE
  856. ; 'ABORT, RETRY, IGNORE' MESSAGE.  ALL FATAL DISK ERRORS ARE IGNORED.
  857. ;---------------------------------------------------------------------
  858. NewInt24    PROC    FAR
  859.         ASSUME    CS:CSEG, DS:NOTHING, ES:NOTHING
  860.         STI            ;TURN INTERRUPTS BACK ON
  861.         INC    CS:err_stat    ;SET THE ERROR FLAG        v2.2a
  862.         XOR    AL,AL        ;TELLS DOS TO IGNORE THE ERROR
  863.         IRET            ;THATS ALL WE DO HERE
  864. NewInt24    ENDP
  865.  
  866. ;--------------------------------------------------------------------
  867. ; HERE IS THE CODE USED TO INITIALIZE Snipper.
  868. ;--------------------------------------------------------------------
  869.         ASSUME    CS:CSEG, DS:CSEG, ES:CSEG
  870. Initialize:
  871.         mov    dx,offset copyright    ;            v2.2a
  872.         MOV    AH,9        ;DOS DISPLAY STRING SERVICE
  873.         INT    21H        ;DISPLAY TITLE MESSAGE
  874. ; SEARCH FOR AN PREVIOUSLY INSTALLED COPY OF Snipper
  875.         NOT    BYTE PTR Start    ;MODIFY TO AVOID FASLE MATCH
  876.         XOR    BX,BX        ;START SEARCH AT SEGMENT ZERO
  877.         MOV    AX,CS        ;COMPARE TO THIS CODE SEGMENT
  878. Next_Segment:
  879.         INC    BX        ;LOOK AT NEXT SEGMENT
  880.         CMP    AX,BX        ;UNTIL REACHING THIS CODE SEG
  881.         MOV    ES,BX
  882.         JE    Not_Installed
  883.         mov    si,offset Start        ;setup to compare strings v2.2a
  884.         MOV    DI,SI
  885.         MOV    CX,16            ;16 BYTES MUST MATCH
  886.         REP    CMPSB            ;COMPARE DS:SI TO ES:DI
  887.         OR    CX,CX            ;DID THE STRINGS MATCH?
  888.         JNZ    Next_Segment        ;IF NO MATCH, TRY NEXT SEGMENT
  889.         mov    dx,offset installed$    ;'Already installed'    v2.2a
  890.         JMP    SHORT Err_Exit
  891.  
  892. Not_Installed:
  893.         MOV    AH,30H
  894.         INT    21H            ;GET DOS VERSION NUMBER
  895.         CMP    AL,2            ;IS IT HIGHER THAN 2.0?
  896.         JAE    Ver_Ok            ;IF YES, PROCEED
  897.          mov    dx,offset bad_dos$    ;'Requires DOS 2.0'    v2.2a
  898. Err_Exit:    MOV    AH,9            ;DOS DISPLAY STRING SERVICE
  899.         INT    21H            ;DISPLAY ERROR MESSAGE
  900.         RET                ;RETURN TO DOS
  901.  
  902. Ver_Ok:
  903. ;v2.4 dumb    INC    SI        ;POINT TO FIRST PARAMETER
  904.         MOV    SI,81H        ;POINT TO PARAMETER AREA
  905.         CALL    Get_Param    ;GET FIRST PARAMETER (ROWS)
  906.         PUSH    AX        ;SAVE THE ROW COUNT
  907.         CALL    Get_Param    ;GET SECOND PARAMETER (COLUMNS)
  908.         ADD    AX,2        ;ADD SPACE FOR CR AND LF
  909.         POP    BX        ;GET BACK FIRST PARAMETER
  910.         MUL    BX        ;PRODUCT OF ROWS AND COLUMNS
  911.         OR    AX,AX        ;WAS ANYTHING ENTERED?
  912.         JZ    No_Params    ;IF NOT, USE DEFAULT VALUE
  913.  
  914.         CMP    AX,10000    ;MAXIMUM BUFFER IS 10000 BYTES
  915.         JLE    Size_Is_Ok
  916.          MOV    AX,10000
  917. Size_Is_Ok:
  918.         ADD    AX,BUFF_START
  919.         MOV    buff_end,AX    ;SET THE NEW BUFFER SIZE
  920. No_Params:
  921. ;
  922. ; EGA check here was removed & code was added to popup routine (1.2)    ;[TK]
  923. ;
  924.         ASSUME    ES:NOTHING
  925.         MOV    AX,3509H        ;GET KEYBOARD BREAK VECTOR
  926.         INT    21H
  927.         MOV    WORD PTR [oldint09],  BX  ;SAVE SEGMENT
  928.         MOV    WORD PTR [oldint09+2],ES  ;SAVE OFFSET
  929.         MOV    DX, OFFSET NewInt09
  930.         MOV    AX, 2509H        ;change int 9 vector
  931.         INT    21H
  932.  
  933.         MOV    AX,3513H        ;GET BIOS DISK INTERRUPT VECTOR
  934.         INT    21H
  935.         MOV    WORD PTR [oldint13],  BX  ;SAVE SEGMENT
  936.         MOV    WORD PTR [oldint13+2],ES  ;SAVE OFFSET
  937.         MOV    DX, OFFSET NewInt13
  938.         MOV    AX, 2513H        ;set new Int 13H vector
  939.         INT    21H
  940.  
  941.         MOV    AX,3516H        ;GET KEYBOARD INPUT VECTOR
  942.         INT    21H
  943.         MOV    WORD PTR [oldint16],  BX  ;SAVE SEGMENT
  944.         MOV    WORD PTR [oldint16+2],ES  ;SAVE OFFSET
  945.         MOV    DX, OFFSET NewInt16
  946.         MOV    AX, 2516H        ;set new Int 16H vector
  947.         INT    21H
  948.  
  949.         MOV    AX,3521H        ;GET DOS FUNCTION VECTOR
  950.         INT    21H
  951.         MOV    WORD PTR [oldint21],  BX
  952.         MOV    WORD PTR [oldint21+2],ES
  953.         MOV    DX, OFFSET NewInt21
  954.         MOV    AX, 2521H        ;set new Int 21H vector
  955.         INT    21H
  956.  
  957. ;--------------------------------------------------------------------
  958. ; DEALLOCATE OUR COPY OF THE ENVIRONMENT.
  959. ; EXIT USING INT 27H. LEAVE CODE AND SPACE FOR BUFFER RESIDENT.
  960. ;--------------------------------------------------------------------
  961.  
  962.         mov    ES,envseg    ;get segment of environment    v2.2a
  963.         MOV    AH,49H        ;RELEASE ALLOCATED MEMORY
  964.         INT    21H
  965.         MOV    DX,buff_end    ;LEAVE THIS MUCH RESIDENT
  966.         INT    27H        ;TEMINATE AND STAY RESIDENT
  967.  
  968. ;---------------------------------------------------------
  969. ; Get_Param RETRIEVES AN INTEGER FROM THE COMMAND LINE.
  970. ;---------------------------------------------------------
  971. Get_Param:    XOR    AX,AX        ;CLEAR AX FOR TOTAL
  972. Get_Digit:    MOV    BL,[SI]        ;GET CHARACTER INTO BL
  973.         CMP    BL,0DH        ;IS IT THE LAST ONE?
  974.         JE    Done
  975.         INC    SI        ;POINT TO NEXT CHARACTER
  976.         CMP    BL,","        ;IS IT THE DELIMITER?
  977.         JE    Done
  978.         SUB    BL,30H        ;CONVERT ASCII TO INTEGER
  979.         JC    Get_Digit    ;IS IT A VALID DIGIT
  980.         CMP    BL,9
  981.         JA    Get_Digit    ;IF NOT VALID, JUST SKIP IT
  982.         MOV    BH,10        ;TIMES 10 FOR NEXT DIGIT
  983.         MUL    BH        ;MULTIPLY SUM AND ADD THIS DIGIT
  984.         ADD    AL,BL        ;ADD DIGIT TO SUM
  985.         JMP    Get_Digit    ;READ ALL CHARACTERS ON LINE
  986.  
  987. Done:        RET
  988.  
  989. CSEG        ENDS
  990.         END    Start
  991.