home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
deskaces
/
notepad4.arc
/
NOTEPAD4.ASM
next >
Wrap
Assembly Source File
|
1986-02-12
|
30KB
|
1,007 lines
PAGE 55,132
TITLE NOTEPAD4
;
;NotePad IV - NON BIOS VERSION
; Permission is granted to copy and distribute freely copies of this
; program with the following restrictions:
;
; 1) this program be passed in the public domain
; 2) a fee, beyond the cost of the disk, not be charged
; 3) improvements not be passed on but rather sent to me
; to check for possible incompatibilities with other programs
;
; (Stephen) Randy Davis and Larry Weiss
; (214)454-2426
;
; feel free to call with bugs or questions
;
;PARAMETERS -- MOST OF THESE MAY BE CHANGED TO ANY DESIRED VALUE
wndw_ht equ 24 ;mark the size of the window to open
wndw_wd equ 40
our_key equ 07100H ;scan code - ascii of key to open window
;now scan codes of edit keys (AltF10)
up_arrow equ 4800H
down_arrow equ 5000H
left_arrow equ 4B00H
right_arrow equ 4D00H
del_left equ 0008H ;user rubout (cntrl H) key
delete equ 5300H ;use del (lower right)
insert equ 5200H
cr equ 000DH
home equ 4700H
escape equ 001BH
tab equ 7400H ; ^right arrow
rev_tab equ 7300H ; ^left arrow
line_ins equ 5100H ;pg down
line_del equ 4900H ;pg up
mark_char equ 4F00H ;end key
print_char equ 372AH ;PrtSc* = print note on printer
file_change equ 4A2DH ;key to update file and get a new one
blank equ 07020H ;define the character which is a blank
attrib equ 070H ;and our default attribute (should agree with blank)
video equ 10H ;video BIOS call
inv_attrib equ 007H ;inverse of 'attrib'
PAGE
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:CSEG,SS:CSEG,ES:NOTHING ;STANDARD DECL FOR .COM FILE
ORG 100H
Start:
JMP INSTALL
DB (100H) DUP(0) ;ALLOCATE SOME EXTRA DISK SPACE
STACK:
;PLACE DATA AREA HERE FOR READIBILITY
COPYRITE DB 'Copyright Stephen R. Davis, Larry Weiss 1985 All Rights Reserved'
DB '(214)454-2426'
SCREENSAVE: DW (WNDW_HT * (WNDW_WD+1)) DUP (BLANK);RESERVE SPACE TO SAVE OPENED WINDOW
LINESAVE: DW WNDW_WD DUP (BLANK) ;BUFFER FOR LINE DELETE
CURSOR_POS DW 0
OLD_CUR_POS DW 0
SAVESTACK DW 0,0
REQUEST DB 0 ;REQUEST TYPE
KEY_RQST_HANDLER DD 0 ;ADDRESS OF THE ORIGINAL KEYBOARD REQUEST HANDLER
LEFT_MARG DB 00 ;define the confines of the window
RIGHT_MARG DB 00
TOP_MARG DB 00
BOT_MARG DB 00
UPPER_LEFT DW 00
MARK DW 00 ;FLAGS USED IN CHARACTER FEED
FEED_START DW 00 ;ADDRESS IN BUFFER OF BEGIN...
FEED_END DW 00 ;...AND END OF FEED
DISPLAY_SEG DW 00 ;DISPLAY SEGMENT (B000 -> MONOCHROME,
; B800 -> GRAPHIX)
FILE_NM_LOC DW 00 ;ADDRESS OF FILE NAME (0 -> NO FILE)
PAGE
BEGIN PROC FAR ;FAR LABEL SINCE ITS ENTERED BY INTERRUPT
MAINLOOP:
MOV CS:REQUEST,AH ;SAVE HIS AX REGISTER
MOV AX,CS:FEED_START ;ARE WE IN THE MIDDLE OF FEEDING CHARS...
CMP AX,CS:FEED_END ;...TO THE APPLICATION?
JZ NOFEED ;NO
JMP FEED ;YES
NOFEED:
MOV AH,CS:REQUEST ;RESTORE USERS AX
PUSHF ;CALL OLD INTERRUPT HANDLER (EMULATE INT INSTRUCTION)
CALL DWORD PTR [CS:KEY_RQST_HANDLER] ;GO AHEAD AND GET THE CHARACTER
PUSHF ;SAVE THE FLAG RETURNED (FOR AH = 1 REQUESTS)
CMP CS:REQUEST,00H ;WE ARE ONLY INTERESTED IN CHAR. REQUESTS
JZ CNTINUE
JMP FORGET_IT
CNTINUE: ;YES -- CHECK CHARACTER FOR 'OURS'
POPF ;FOR NON-TYPE 1 REQUESTS DONT NEED TO SAVE FLAGS
CMP AX,OUR_KEY
JZ CNT_AGIN
JMP RETURN_CHAR
CNT_AGIN: ;WE GOT IT! GO INTO EDITOR MODE
MOV CS:SAVESTACK,SP
MOV CS:SAVESTACK+2,SS
MOV AX,CS
MOV SS,AX
MOV SP,OFFSET STACK
STI ;ENABLE INTERRUPTS WHILE PROCESSING CHARACTERS
PUSH BP ;SET UP A STACK FRAME
MOV BP,SP
SUB SP,0EH
CALL SAVEREG
MOV DS,AX
CALL CALC_WINDOW ;CALCULATE WINDOW EXTREMETIES
CALL READ_CURSOR
MOV OLD_CUR_POS,DX ;SAVE THE CURSOR FOR LATER RESTORING
CALL WINDOW_SWAP ;SWING IN THE EDIT WINDOW (WITH NOTES?)
CALL INSERT_CR ;PUT THE CARRIAGE RETURNS ON UNPRINTABLE COL.S
MOV DX,CURSOR_POS ;RESTORE CURSOR IN EDIT WINDOW
CALL PLACE_CURSOR
CALL EDITOR ;LET HIM EDIT IN THE WINDOW
CALL READ_CURSOR
MOV CURSOR_POS,DX ;SAVE CURSOR IN EDIT WINDOW FOR NEXT EDIT
CMP MARK,00H ;CLEAR THE MARK POSITION (IF IT'S SET)
JZ NOT_SET
MOV DX,MARK
CALL READ_CHAR ;GET THE CHARACTER...
MOV AH,ATTRIB ;...PUT ITS ATTRIBUTE BACK TO EVERYONE ELSE'S...
CALL WRITE_CHAR ;...AND PUT IT BACK
MOV MARK,00H
NOT_SET:
CALL WINDOW_SWAP ;PUT BACK WHATEVER WAS ORIGINALLY THERE
CALL UPDATE_FILE ;NOW ATTEMPT TO UPDATE THE DISK FILE
MOV DX,OLD_CUR_POS ;RESTORE THE CURSOR POSITION
CALL PLACE_CURSOR
CALL RESTREG
ADD SP,0EH
POP BP
MOV SS,CS:SAVESTACK+2
MOV SP,CS:SAVESTACK
MOV AH,00 ;RESTORE REQUEST TO SOMETHING DECENT
JMP MAINLOOP ;GO GET ANOTHER CHARACTER TO RETURN HIM
RETURN_CHAR:
IRET ;RETURN WITH CHARACTER
;HANDLE REQUEST TYPE 1'S BY FAR RETURNING 2 AND TYPE 2'S BY JUST RETURNING
FORGET_IT:
CMP CS:REQUEST,1 ;was it a "is char present" request?
JZ FI100
POPF ;no -- just return whatever BIOS returned
IRET
FI100:
POPF ;yes -- make funny return
RET 02
PAGE
;HERE WE ARE IN THE PROCESS OF FEEDING CHARACTERS TO THE APPLICATION
;FROM THE WINDOW BUFFER (SCREENSAVE)
FEED:
CMP CS:REQUEST,1 ;WAS THIS A CHAR TYPE REQUEST?
JA KSTAT
;YES -- RETURN HIM CHAR
PUSH BX ;GET THE NEXT CHARACTER FROM THE BUFFER
CALL SKIP_SPACES ;STRIP LEADING SPACES
MOV BX,CS:FEED_START ;OK - GET THE NEXT CHARACTER WE NEED
MOV AX,CS:[BX]
POP BX
XOR AH,AH ;WE NO LONGER HAVE THE SCAN CODE, BUT ALL
;ARE ASCII ANYWAY
CMP CS:REQUEST,0 ;IS THIS A 'GET KEYBOARD CHAR' RQST?
JNZ FEED_KEY_STAT
ADD CS:FEED_START,2 ;YES -- MOVE UP THE POINTER BY 1
IRET
FEED_KEY_STAT:
STI ;NO -- ENABLE INTERRUPTS AND FEED HIM THE
RET 02 ;THE Z FLAG CLEAR WITH HIS CHAR
KSTAT:
MOV AH,CS:REQUEST ;RESTORE REQUEST TO AH
CALL DWORD PTR [CS:KEY_RQST_HANDLER] ;PERFORM BIOS CALL -- WE DON'T KNOW
;WHAT HE'S DOING AND WE SHOULDN'T GET IN THE WAY
IRET ;RETURN THE RESULTS TO HIM (WHATEVER THEY ARE)
BEGIN ENDP
PAGE
BODY PROC NEAR ;MAKE SHORT CALLS ONLY TO THE MAIN ROUTINES
SKIP_SPACES:
;TRY TO AVOID FEEDING SPACES WITH NOTHING AFTER THEM ON A LINE --
;JUST SKIP OVER TO THE RETURN AND FEED THAT ALONE
MOV BX,CS:FEED_START ;START WITH THE NEXT FEED CHARACTER
LOOK_AHEAD:
MOV AX,CS:[BX]
CMP AL,CR ;IS THIS CHAR A RETURN
JZ STRIP_SPACES
CMP AL,' ' ;IS THIS CHARACTER ANOTHER SPACE?
JNZ GO_ON
ADD BX,2 ;YES -- KEEP LOOKING AHEAD
CMP BX,CS:FEED_END ;IS THAT IT?
JNZ LOOK_AHEAD
;YES--
SUB BX,2 ;RAN OFF THE END -- BACK UP ONE CHAR AT LEAST!
STRIP_SPACES:
MOV CS:FEED_START,BX ;HERE WE FOUND NOTHING BUT SPACES BEFORE THE
;CARRIAGE RETURN -- SKIP THAT!
GO_ON:
RET
PAGE
CALC_WINDOW:
MOV AH,0FH ;FIND OUT VIDEO MODE FOR CALCULATING WINDOW SIZE
INT VIDEO ;GO AHEAD AND GET THE CHARACTER
MOV CX,0B000H ;IS IT MONOCHROME?
CMP AL,7 ;WELL LOOK FOR MODE 7
JZ CW100
MOV CX,0B800H ;NO -- ITS GRAPHIX
CW100:
MOV DISPLAY_SEG,CX ;SAVE THIS OFF
DEC AH ;THIS IS THE NUMBER OF COLS ON SCREEN
MOV RIGHT_MARG,AH ;SET UP RIGHT AND LEFT MARGINS
SUB AH,(WNDW_WD - 1)
MOV LEFT_MARG,AH
MOV TOP_MARG,0 ;WE HAVE NO INFORMATION ON NUMBER OF ROWS
MOV BOT_MARG,WNDW_HT-1 ;SO WE MUST ASSUME SOMETHING NORMAL (IT ISNT
;AS CRITICAL ANYWAY)
MOV AL,AH ;NOW ADD UPPER_LEFT HAND CORNER VALUE
XOR AH,AH
MOV UPPER_LEFT,AX
CMP CURSOR_POS,0 ;IF THIS IS THE FIRST TIME WEVE DONE THIS...
JNZ CW200
MOV CURSOR_POS,AX ;...PLACE THE CURSOR IN THE UPPER LEFT HAND CORNER
CW200:
RET
PAGE
INSERT_CR: ;INSERT CARRIAGE RETURNS 1 PAST RIGHT MARGIN
MOV CX,WNDW_HT
MOV SI,OFFSET SCREENSAVE
MOV BX,WNDW_WD
ADD BX,BX ;EVERY LOCATION TAKES A WORD, NOT A BYTE
ICR_LOOP:
ADD SI,BX ;GO 1 BEYOND RIGHT MARGIN
MOV [SI],CR
ADD SI,2 ;THAT CR TAKES A SPACE
LOOP ICR_LOOP
RET
WRITE_POS DW 0
WINDOW_SWAP:
MOV CX,WNDW_HT ;GET THE NUMBER OF ROWS IN WINDOW AREA
MOV SI,OFFSET SCREENSAVE;START AT BEGINNING OF BUFFER
MOV ES,DISPLAY_SEG ;LOAD UP THE VIDEO SEGMENT
MOV DI,00
XOR BX,BX
WS050:
MOV BL,LEFT_MARG ;START ON THIS LINE AT THE LEFT MARGIN
WS100:
SHL BX,1 ;CHANGE THE COLUMN NUMBER TO BYTE POINTER
MOV AX,ES:[BX][DI] ;GET THE NEXT CHARACTER FROM SCREEN
XCHG AX,[SI] ;STORE IT AWAY AND WRITE THE SAVED CHARACTER
ADD SI,2 ;AND MOVE SAVE POINTER OVER A WORD
MOV ES:[BX][DI],AX ;NOW RESTORE THAT CHARACTER TO THE SCREEN
SHR BX,1 ;PUT THE BYTE OFFSET BACK TO COLUMN NUMBER
INC BX
CMP BL,RIGHT_MARG ;ARE WE BEYOND THE END OF THE LINE?
JNA WS100
;YES -- SKIP DOWN TO NEXT LINE
ADD SI,2 ;SKIP BEYOND CARRIAGE RETURN
SHL BX,1
ADD DI,BX
LOOP WS050
RET
PAGE
EDITOR:
;first check for "special" keys -- print screen and close file
;if not one of these, check for edit keys (such as insert, delete, etc.)
;if not one of those, assume its ascii and just insert it in the notepad
;return when AltF10 detected.
ED100:
CALL GET_CHAR ;read a character from the keyboard
CMP AX,PRINT_CHAR ;check for print note first
JNZ ED102
CALL PRINTNOTE ;we need to print the note -- not change it
MOV BX,CURSOR_POS ;in many cases we need the cursor position
JMP ED500
ED102:
CMP AX,FILE_CHANGE ;is he wanting to close and open a new file
JNZ ED103
CALL CHANGE_FILE
MOV BX,CURSOR_POS
JMP ED500
ED103:
OR AL,AL ;if this is ascii then dont retain scan code
JZ ED105
XOR AH,AH
ED105:
MOV BX,CURSOR_POS ;in many cases we need the cursor position
CMP AX,OUR_KEY ;check for exit
JNZ ED110
JMP ED800
ED110:
CMP AX,CR ;check for each special character individually
JNZ ED120
MOV BL,LEFT_MARG
INC BH
JMP ED500
ED120:
CMP AX,LEFT_ARROW
JNZ ED140
DEC BL
JMP ED500
ED140:
CMP AX,RIGHT_ARROW
JNZ ED160
INC BL
JMP ED500
ED160:
CMP AX,UP_ARROW
JNZ ED180
DEC BH
JMP ED500
ED180:
CMP AX,DOWN_ARROW
JNZ ED200
INC BH
JMP ED500
ED200:
CMP AX,HOME
JNZ ED205
MOV BX,UPPER_LEFT
JMP ED500
ED205: ;tab and back tab functions
CMP AX,TAB
JNZ ED210
MOV CL,1 ;go forward
JMP ED213
ED210:
CMP AX,REV_TAB
JNZ ED220
MOV CL,0FFH ;go backwards one tab slot
ADD DL,CL ;start one char to left initially
ED213:
CALL READ_CHAR ;get char at current position
MOV CH,AL ;save it for comparison
ED215:
ADD DL,CL ;move over one character
CMP DL,RIGHT_MARG ;stop at left and right margins (or beyond)
JGE ED218
CMP DL,LEFT_MARG
JLE ED218
CALL READ_CHAR ;read current character
CMP CH,' ' ;if original was a space...
JNZ ED216
CMP AL,' ' ;...then go until not space
JZ ED215
JMP ED217
ED216:
CMP AL,' ' ;...else, go until space
JNZ ED215
ED217:
CMP CL,0FFH ;if we were going backwards (towards left)...
JNZ ED218
ADD DL,1 ;...then scoot back to the right by 1
ED218:
MOV BX,DX
JMP ED500
ED220:
CMP AX,ESCAPE ;wipe out remainder of line
JNZ ED240
MOV DX,BX
CALL ERASE_LINE
JMP ED500
ED240:
CMP AX,DEL_LEFT ;move cursor left one char and then do normal del
JNZ ED260
DEC BL
CMP BL,LEFT_MARG
JNB ED250
MOV BL,RIGHT_MARG
CMP BH,00
JZ ED250
DEC BH
ED250:
JMP ED270
ED260:
CMP AX,DELETE ;in delete char we...
JNZ ED280
ED270:
MOV CL,RIGHT_MARG
SUB CL,BL ;calculate how many chars to right margin
XOR CH,CH
MOV DX,BX ;...start at current cursor position...
JCXZ ED275
ED272:
INC DL ;...get character just to the right...
CALL READ_CHAR
DEC DL ;...move left one position...
CALL WRITE_CHAR ;...and write it there...
INC DL ;...now do it again for the char to the right...
LOOP ED272 ;...for the distance from cursor to right margin;...
ED275:
MOV AX,BLANK
CALL WRITE_CHAR
JMP ED500
ED280:
CMP AX,INSERT ;in the case of insert we do reverse of delete
JNZ ED300
MOV DH,BH ;start at the right margin
MOV DL,RIGHT_MARG
MOV CL,DL ;caculate number of spaces to right
SUB CL,BL
XOR CH,CH
JCXZ ED290
ED285:
DEC DL
CALL READ_CHAR
INC DL
CALL WRITE_CHAR
DEC DL
LOOP ED285
ED290:
MOV AX,BLANK
CALL WRITE_CHAR
JMP ED500
ED300:
CMP AX,LINE_INS ;check for insert line
JNZ ED320
MOV DH,BOT_MARG ;we're going to need that
ED305:
MOV DL,LEFT_MARG ;always start at the far left
CMP DH,BH ;are we on our current line?
JZ ED315
;no -- then move it down
MOV CX,WNDW_WD
ED310:
DEC DH
CALL READ_CHAR ;get the character
INC DH
CALL WRITE_CHAR ;and put it back one line higher
INC DL ;move right one character
LOOP ED310
DEC DH ;now move up a line and do it again
JMP ED305
ED315:
MOV BL,LEFT_MARG ;move us over the far left marg
CALL ERASE_LINE ;and wipe out the line we are on
JMP ED500
ED320:
CMP AX,LINE_DEL ;and check for line delete
JNZ ED340
ED325:
MOV DL,LEFT_MARG ;always start at the far left
CMP DH,BOT_MARG ;are we on the last line?
JZ ED335
;no -- then move it up
MOV CX,WNDW_WD
ED330:
INC DH
CALL READ_CHAR ;get the character
DEC DH
CALL WRITE_CHAR ;and put it back one line lower
INC DL ;move right one character
LOOP ED330
INC DH ;now move down a line and do it again
JMP ED325
ED335:
MOV BL,LEFT_MARG ;move us over the far left marg of our line
CALL ERASE_LINE ;and wipe out the bottom line
JMP ED500
ED340:
CMP AX,MARK_CHAR ;check for mark
JNZ ED400
MOV DX,BX
CMP MARK,00H ;if mark isnt set...
JNZ ED350
MOV MARK,BX ;...just set it and switch its attrib
CALL READ_CHAR
MOV AH,INV_ATTRIB
CALL WRITE_CHAR
JMP ED500
ED350: ;else, store off feed start and end addresses
CALL CONVERT_LOC
MOV FEED_START,AX
MOV DX,MARK
CALL CONVERT_LOC
MOV FEED_END,AX
MOV CX,FEED_START
CMP CX,AX
JNA ED355
MOV FEED_START,AX
MOV FEED_END,CX
ED355:
JMP ED800 ;note that this char exits the note pad
ED400: ;wasnt an edit character -- must be ascii
;just write the character at current position
MOV AH,ATTRIB
CALL W_CHAR
INC BL ;move over one position
ED500: ;adjust resulting cursor position
CMP BL,RIGHT_MARG
JNA ED550
MOV BL,RIGHT_MARG
ED550:
CMP BH,BOT_MARG
JNA ED600
MOV BH,BOT_MARG
ED600:
CMP BL,LEFT_MARG
JNB ED650
MOV BL,LEFT_MARG
ED650:
CMP BH,0FFH ;special case for a top margin of 0
JNZ ED700
MOV BH,BOT_MARG
ED700:
MOV CURSOR_POS,BX
MOV DX,BX ;be sure and move the cursor to the new
CALL PLACE_CURSOR ;position
JMP ED100
ED800: ;exit
RET
PAGE
PRINTNOTE:
CALL P_SPLAT_ROW ;put a row of splats across the top
;to delineate the note on the printer page
MOV DX,UPPER_LEFT
PN100:
CMP DL,LEFT_MARG ;put a splat on left hand side also
JNZ PN150
MOV AL,2AH
CALL PRINT_C
JNZ PN400 ;don't proceede on timeout of printer
PN150:
CALL READ_CHAR ;get the character @ DX
CALL PRINT_C ;and print it
JNZ PN400 ;quit immediatly on i/o timeout
CMP DL,RIGHT_MARG
JNZ PN200
MOV AL,2AH ;print a right margin delineator
CALL PRINT_C
MOV AL,0AH ;print carriage return-line feed after every line
CALL PRINT_C
MOV AL,0DH
CALL PRINT_C
CMP DH,BOT_MARG ;are we finished?
JZ PN300
;no -- drop down a line
INC DH
MOV DL,LEFT_MARG
DEC DL
PN200:
INC DL ;skip over to next character in note
JMP PN100
PN300:
CALL P_SPLAT_ROW
PN400:
RET
P_SPLAT_ROW:
MOV CX,WNDW_WD+2 ;put a row of splats across the page
PS100:
MOV AL,2AH
CALL PRINT_C
JNZ PS200 ;return immediately on time out
LOOP PS100
MOV AL,0AH
CALL PRINT_C
MOV AL,0DH
CALL PRINT_C
PS200:
RET
PAGE
;
; THE FOLLOWING ROUTINE CLOSES THE CURRENT FILE AND ASKS FOR A NEW
; FILE; IT ATTEMPTS TO OPEN THIS FILE UP AND READ IT AS A NOTE PAD
;
CHANGE_FILE:
CALL WINDOW_SWAP ;PUT THE NOTE PAD INTO THE SAVE BUFFER FOR WRITING
CALL UPDATE_FILE ;IF CURSOR HOMED, WRITE THE NOTEPAD OUT TO THE CURRENT FILE
MOV FILE_NM_LOC,0 ;THAT FILE IS NOW CLOSED PERMANENTLY
MOV DX,UPPER_LEFT ;ERASE THE TOP LINE AND POSE FILE NAME QUESTION
MOV BX,DX
CALL ERASE_LINE
MOV DX,BX
CALL PLACE_CURSOR ;PUT CURSOR ON LEFT AND ASK FOR FILE NAME
MOV BX,OFFSET CF500
CF100:
MOV AL,BYTE PTR [BX]
INC BX
CMP AL,0 ;0 TERMINATES AN ASCIIZ STRING
JZ CF200
MOV AH,ATTRIB
CALL W_CHAR
INC DL
CALL PLACE_CURSOR
JMP CF100
CF200:
MOV BX,80H ;STORE NAME IN PSP
CF300:
CALL GET_CHAR ;GET FILE NAME UNTIL RETURN
CMP AL,0DH ;CHECK FOR RETURN
JZ CF400
CMP AL,08H ;WE DO NEED TO HANDLE DEL CHAR SEPERATLY
JNZ CF350
DEC BX ;HE'S TRYING TO DELETE THE LAST CHAR
DEC DL ;MOVE THE POINTER BACK IN THE FILE AND DEL CHAR
MOV AL,20H ;ON SCREEN W/ A SPACE
MOV AH,ATTRIB
CALL WRITE_CHAR
JMP CF300
CF350:
INC BX ;SAVE OFF NEXT CHARACTER OF NAME FIELD
MOV BYTE PTR [BX],AL
MOV AH,ATTRIB
CALL W_CHAR ;ECHO CHAR SO HE CAN SEE WHAT HE IS TYPING
INC DL
CALL PLACE_CURSOR
JMP CF300
CF400:
SUB BX,80H ;CALCULATE CHARACTER COUNT
MOV BYTE PTR [80H],BL
MOV DL,LEFT_MARG ;NOW ERASE NAME OF FILE AND RESTORE WHAT WAS THERE
MOV BX,DX
CALL RESTORE_LINE
CALL READ_FILE ;READ UP THE INDICATED FILE INTO SAVE BUFFER
CALL WINDOW_SWAP ;NOW PUT NOTE PAD DISPLAY BACK UP
RET
CF500: DB 'ENTER FILE NAME:',0
READ_FILE: ;READS FILE NAME IN 81 WITH LENGTH COUNT IN 80
;ON SUCCESSFUL READS, RETURNS CARRY CLEARED
MOV BX,80H ;FIND BEGINNING OF NAME FIELD
XOR CH,CH
MOV CL,BYTE PTR [BX] ;GO GET THE ARGUMENT COUNT FROM THE PSP
JCXZ RF300
RF100: ;FIND THE BEGINNING OF THE FILE NAME
INC BX
CMP BYTE PTR [BX],20H
JNZ RF150
LOOP RF100
RF150:
MOV DI,BX ;NOW TERMINATE IT WITH A 0
JCXZ RF300 ;A 0 LENGTH FILE NAME INDICATES NO FILE TO READ
MOV FILE_NM_LOC,BX ;SAVE THE LOCATION OF THE NAME
RF200:
INC DI
LOOP RF200
MOV BYTE PTR [DI],0
MOV AH,3DH ;OPEN FILE
MOV AL,0 ;FILE FOR READ ONLY
MOV DX,BX ;PUT FILE NAME IN GOOD REGISTER
INT 21H
JC RF400 ;CARRY SET INDICATES OPEN ERROR
MOV BX,AX ;READ THE FILE INTO THE NOTE PAD AREA
MOV CX,(WNDW_HT*(WNDW_WD+1)*2)
MOV DX,OFFSET SCREENSAVE
MOV AH,3FH
INT 21H
MOV AH,3EH ;CLOSE THE FILE
INT 21H
RF300:
CLC ;MAKE SURE CARRY CLEAR FOR NO ERROR RETURN
RET
RF400:
RET ;LEAVE CARRY SET ON ERROR RETURN
UPDATE_FILE:
CMP FILE_NM_LOC,0 ;IF THERE IS NOT FILE...
JZ UP100 ;...THEN JUST SKIP THIS WHOLE THING
MOV AX,CURSOR_POS ;UPDATE IF CURSOR HOMED
CMP AX,UPPER_LEFT
JNZ UP100
MOV AL,1H ;OPEN THE FILE FOR WRITING
MOV AH,3DH
MOV DX,FILE_NM_LOC ;GET THE FILENAME IN DX
INT 21H
JC UP100 ;IF ERROR ON OPEN, JUST GIVE IT UP
MOV BX,AX
MOV AH,40H ;WRITE THE FILE
MOV CX,(WNDW_HT*(WNDW_WD+1)*2)
MOV DX,OFFSET SCREENSAVE
INT 21H
MOV AH,3EH
INT 21H ;NOW CLOSE THE FILE
UP100:
RET
PAGE
;
; HERE WE PLACE SOME SMALL GENERAL PURPOSE ROUTINES
;
PRINT_C: ;print the char in AL on LPT1 (parrallel)
;returns printer status in AH
PUSH DX
XOR DX,DX ;select LPT1
XOR AH,AH ;select "print"
INT 17H
POP DX
TEST AH,1 ;set the zero flag if not error,
;clear zero flag if char not printed
RET
PLACE_CURSOR: ;place cursor at location in dx
MOV AH,2H
PUSH BX
XOR BX,BX
INT VIDEO
POP BX
RET
READ_CURSOR: ;read cursor location into dx
MOV AH,3H
PUSH BX
XOR BX,BX
INT VIDEO
POP BX
RET
READ_CHAR: ;read screen character at location in dx
CALL CALC_VID_LOC ;covert the row and column into location
MOV AX,ES:[DI] ;get the character at that location
RET
R_CHAR: ;read screen char at current cursor location
MOV AH,8H
PUSH BX
XOR BH,BH
INT VIDEO
POP BX
RET
WRITE_CHAR: ;write attrib/char in ax at location in dx
PUSH AX ;save the attrib from destruction
CALL CALC_VID_LOC ;convert the row and column into location
POP AX
MOV ES:[DI],AX
RET
W_CHAR: ;write character at current cursor location
PUSH BX ;save bx register
MOV BL,AH
XOR BH,BH
PUSH CX ;retain cx register also
MOV CX,1
MOV AH,9H
INT VIDEO
POP CX
POP BX
RET
CALC_VID_LOC: ;convert the row and column in dx into an
;offset into the video display buffer
XOR AX,AX
XOR DI,DI
PUSH CX ;save cx -- some of those who call us need it
XOR CX,CX
MOV AL,RIGHT_MARG ;get the width of a row
INC AX
MOV CL,DH ;put the number of rows into cx
JCXZ CVL200
CVL100:
ADD DI,AX ;for every row add in another 80/40 columns
LOOP CVL100
CVL200:
MOV AL,DL ;now move over to the current column
ADD DI,AX
POP CX ;restore cx
SHL DI,1 ;now convert this into byte offset
MOV ES,DISPLAY_SEG
RET
GET_CHAR: ;get character from keyboard into ax
MOV AH,0H
PUSHF ;simulate call to keyboard handler
CALL DWORD PTR [KEY_RQST_HANDLER]
RET
ERASE_LINE: ;erase the current line from dx to right margin
MOV CL,RIGHT_MARG
SUB CL,BL
INC CL
XOR CH,CH
MOV SI,OFFSET LINESAVE
ER100:
CALL READ_CHAR ;get the character @ current location
MOV [SI],AX
ADD SI,2
MOV AX,BLANK
CALL WRITE_CHAR
INC DL
LOOP ER100
RET
RESTORE_LINE: ;restore the current line from dx to right margin
MOV CL,RIGHT_MARG
SUB CL,BL
INC CL
XOR CH,CH
MOV SI,OFFSET LINESAVE
RL100:
MOV AX,[SI] ;get the saved char
CALL WRITE_CHAR ;put the saved char where indicated
ADD SI,2
INC DL
LOOP RL100
RET
CONVERT_LOC: ;convert a location on the screen (in dx) into location
;in the screen save buffer
MOV CX,DX
MOV AX,OFFSET SCREENSAVE
CL100:
CMP CH,TOP_MARG
JZ CL200
ADD AX,(WNDW_WD+1)*2
DEC CH
JMP CL100
CL200:
CMP CL,LEFT_MARG
JZ CL300
ADD AX,2
DEC CL
JMP CL200
CL300:
RET
SAVEREG:
MOV -2[BP],BX ;save reggies on stack frame
MOV -4[BP],CX
MOV -6[BP],DX
MOV -8[BP],SI
MOV -0AH[BP],DI
MOV -0CH[BP],DS
MOV -0EH[BP],ES
RET
RESTREG:
MOV BX,-2[BP] ;NOW PUT THE REGGIES BACK AND PULL DOWN
MOV CX,-4[BP] ;THE STACK FRAME
MOV DX,-6[BP]
MOV SI,-8[BP]
MOV DI,-0AH[BP]
MOV DS,-0CH[BP]
MOV ES,-0EH[BP]
RET
BODY ENDP
PAGE
INSTALL:
;THIS PROGRAM INSTALLS THE REST OF THE CODE FOR NOTE PAD
;TRY TO READ THE INITIAL FILE UP INTO THE NOTE PAD AREA
CALL READ_FILE
JNC GO_AHEAD ;ON ERROR READING FILE...
;...OUTPUT ERROR MESSAGE AND QUIT
MOV DX,OFFSET ERRMSG
MOV AH,9H
INT 21H
MOV AH,4CH
MOV AL,1 ;SET THE ERROR LEVEL
INT 21H
GO_AHEAD:
MOV DX,OFFSET MESSAGE ;OUTPUT 'OK' MESSAGE
MOV AH,9H
INT 21H
MOV AX,3516H ;GET INTERRUPT 16 VECTOR
INT 21H
MOV WORD PTR KEY_RQST_HANDLER,BX
MOV WORD PTR KEY_RQST_HANDLER+2,ES
MOV AX,2516H
MOV DX,OFFSET BEGIN ;NOW PUT OUR ROUTINE THERE
INT 21H
MOV DX,OFFSET INSTALL ;TERMINATE AND STAY RESIDENT
ADD DX,100H
MOV CL,4
SHR DX,CL
MOV AH,31H
INT 21H
MESSAGE DB 10,13,'NotePad4 installed',10,13,'Alt-F10 to enter and exit',10,13,'$'
ERRMSG DB 10,13,'NotePad4 not installed',10,13,'Error on file read',10,13,'$'
CSEG ENDS
END START