Category : Word Processors
Archive   : NOTEPAD4.ZIP
Filename : NOTEPAD4.ASM

 
Output of file : NOTEPAD4.ASM contained in archive : NOTEPAD4.ZIP
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

;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,100H

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


  3 Responses to “Category : Word Processors
Archive   : NOTEPAD4.ZIP
Filename : NOTEPAD4.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/