Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP
Filename : MARKS.ASM

 
Output of file : MARKS.ASM contained in archive : EMAC15ES.ZIP
;History:576,1,1
;02-21-88 00:09:37 use the form pointer in get_syntax:,1
;07-06-87 06:53:58 Use botbot for end, rather than LINENEW,1
.xlist
page ,132

include memory.def
include mint.def
include mintform.def

formSeg segment public
extrn syntax_table: word
formSeg ends

data segment byte public
extrn syntax_seg: word
extrn textseg: word

;Marks are referred to by a single ASCII character. If the mark is a digit,
; it is a user-defined mark.
mark_first_temp equ '0' ;first temp mark
mark_last_temp equ '9' ;last temp mark
mark_first_perm equ '@' ;first permanent mark.
mark_last_perm equ 'Z' ;last permanent mark.
mark_split equ '*' ;split mark

;If the mark is one of the following characters, it is a system-defined mark.
mark_list label byte
db '>' ;character to the right of the point
dw mark_right
db '<' ;character to the left of the point.
dw mark_left
db '[' ;first character in the file.
dw mark_top
db ']' ;last character in the file.
dw mark_bot
db '^' ;beginning of this line.
dw mark_begin
db '$' ;end of this line.
dw mark_end
db '-' ;blanks to the left.
dw mark_lblanks
db '+' ;blanks to the right.
dw mark_rblanks
db '}' ;word to the right of this one.
dw mark_word_right
db '{' ;word to the left of this one.
dw mark_word_left
db '.' ;point or anything else no in the list.
dw mark_point
mark_list_size equ ($-mark_list)/3


data ends


bufseg segment public

byte_ptr label byte

extrn toptop: word
extrn topbot: word
extrn bottop: word
extrn botbot: word

comment /*******************************************************************
marks contains the marks, which is a count of characters from the
beginning of the file. There are permanent (global) marks and temporary
(local) marks. The permanent marks are accessible at all times, while the
temporary marks are accessible only while they are on the top of the stack.
There are a These marks are defined below. The actual number of temporary
marks is given by the value of [temp_mark_count]-[temp_mark_base]. As you can
see, this is initially zero. The number of marks is adjusted by calling
stack_marks.
****************************************************************************/

MAX_MARKS equ 50
temp_mark_base db ? ;first temporary mark
temp_mark_count db ? ;total number of temporary marks
perm_mark_count db ? ;number of permanent marks
public split_mark
split_mark dw ? ;mark used for split screen.
mark_offset dw max_marks dup(?)
marks_sp dw ?
db max_marks dup(?)

wdummy struc
w dw ?
wdummy ends

bdummy struc
b db ?
bdummy ends

bufseg ends


code segment byte public
assume cs:code, ds:data, es:data

public set_mark
set_mark:
push ds
mov ds,textseg
call set_mark$
pop ds
ret


public stack_marks
stack_marks:
push ds
mov ds,textseg
call stack_marks$
pop ds
ret

code ends

code segment byte public
assume cs:code, ds:bufseg, es:data

public init_marks
public set_mark_si
public get_mark
public adjust_marks_del
public adjust_marks_ins


init_marks:
mov temp_mark_base,1
mov temp_mark_count,1
mov perm_mark_count,1
mov bx,offset marks_sp+2
mov byte ptr [bx],0 ;initial stack frame is empty.
mov marks_sp,bx
mov mark_offset[0],0 ;init the only mark.
mov split_mark,0 ;set the mark to the beginning.
ret


user_mark:
;enter with al=mark.
;if user mark, exit with bx->proper marks array entry, nc.
;if sytem mark, exit with cy.
cmp al,mark_first_perm ;permanent user mark?
jb user_mark_3
cmp al,mark_last_perm
ja user_mark_3
mov bl,al
sub bl,mark_first_perm
cmp bl,perm_mark_count
jae user_mark_1 ;too bit, can't be user mark.
jmp short user_mark_2
user_mark_3:
cmp al,mark_first_temp
jb user_mark_1
cmp al,mark_last_temp
ja user_mark_1
mov bl,al
sub bl,mark_first_temp
mov bh,temp_mark_count ;compute the number of temporary marks.
sub bh,temp_mark_base
cmp bl,bh
jae user_mark_1 ;too big, can't be user mark.
add bl,temp_mark_base

user_mark_2:
add bl,bl
mov bh,0
lea bx,mark_offset[bx]
ret ;cy was cleared by previous operation
user_mark_1:
cmp al,mark_split ;split is a settable mark.
jne user_mark_4
mov bx,offset split_mark
ret
user_mark_4:
stc
ret


stack_marks$:
;enter with ax>0=number of temporary marks to stack or
; ax<0=number of permanent marks to create (temporary marks are destroyed) or
; ax=0 to unstack.
;exit with cy if overflow/underflow.
cmp ax,0
jg stack_marks_1 ;stack
jl stack_marks_4 ;create perms.
mov bx,marks_sp
mov al,[bx] ;get the current frame size
or al,al
je stack_marks_2 ;nothing to unstack.
sub temp_mark_count,al ;reduce count by this frame size
dec bx
mov al,[bx] ;get the previous frame size
sub temp_mark_base,al
mov marks_sp,bx
clc
ret
stack_marks_4:
neg ax
cmp al,MAX_MARKS ;stack overflow?
jae stack_marks_2 ; yes.
mov temp_mark_base,al
mov temp_mark_count,al
mov perm_mark_count,al
mov bx,offset marks_sp ;find the new tos.
add bx,ax
mov byte ptr [bx],0 ;initial stack frame is empty.
mov marks_sp,bx
mov ax,'.'*256+mark_first_perm
mov cl,perm_mark_count
mov ch,0
jmp short stack_marks_3
stack_marks_1:
mov ah,temp_mark_count ;get number of marks.
add ah,al ;add desired number
cmp ah,MAX_MARKS ;stack overflow?
jae stack_marks_2 ; yes.
mov bx,marks_sp
inc bx ;bump stack pointer
mov [bx],al ;save the frame size
mov marks_sp,bx
mov al,temp_mark_count
mov temp_mark_base,al ;new base is old max.
mov temp_mark_count,ah ;new max is old+count of new marks
;set all the new temp marks to the point.
sub ah,al ;ah=temp_mark_count-temp_mark_base
mov cl,ah
mov ch,0
mov ax,'.'*256+mark_first_temp
stack_marks_3:
push ax
push cx
call set_mark$
pop cx
pop ax
inc al
loop stack_marks_3
clc
ret
stack_marks_2:
stc
ret


set_mark_si:
;enter with al=number of dest mark, si->text.
;note that system marks cannot be set.
call user_mark
jc set_mark_si_1 ;not a user mark.
cmp si,topbot ;is new mark above point?
jb set_mark_si_2 ;no, make it relative to toptop
sub si,bottop
add si,topbot
sub si,toptop
jmp short set_mark_si_3
set_mark_si_2:
sub si,toptop
set_mark_si_3:
mov [bx],si
set_mark_si_1:
ret


set_mark$:
;enter with al=dest mark, ah=source mark.
push ax
mov al,ah
call get_mark_count
pop ax
call user_mark
jc set_mark_1
mov [bx],cx ;store the mark.
set_mark_1:
ret


assume es:nothing, ss:data

get_mark_count:
;enter with al=number of mark to get.
;exit with cx=number of characters before the mark.
call user_mark
jc get_mark_count_1 ;anything larger (or negative)
mov cx,[bx]
ret
get_mark_count_1:
mov bx,offset mark_list-3 ;get the mark list.
mov cx,mark_list_size
get_mark_count_2: ;scan the list for the mark.
add bx,3 ;preincrement
cmp al,ss:[bx] ;is it this one?
loopne get_mark_count_2 ;continue if not.
jmp word ptr ss:[bx+1] ;go to the correct mark.


mark_right:
mov cx,botbot ;compute the number of characters after the
sub cx,bottop ; point.
je mark_bot ; return the mark at the end of the file.
mov cx,topbot ;compute the number of characters before the
sub cx,toptop ; point.
inc cx ;because we want the character to the right.
mov bx,bottop ;check for breaking up a NEWLINE
cmp [bx].w,LINENEW
jne mark_right_1 ;not NEWLINE.
inc cx ;because we don't want to split a newline.
mark_right_1:
ret


mark_left:
mov cx,topbot
sub cx,toptop
jz mark_left_1 ;if no characters, mark is at beginning of file.
dec cx ;because we want the character to the left.
mov bx,topbot
cmp [bx-2].w,LINENEW
jne mark_left_1
dec cx ;because we don't want to split a newline.
mark_left_1:
ret


mark_top:
mov cx,0 ;zero characters before beginning of file.
ret


mark_bot:
mov cx,topbot ;size of text before point +
sub cx,toptop
add cx,botbot ;size of text after point.
sub cx,bottop
ret


mark_point:
mov cx,topbot ;size of text before point.
sub cx,toptop
ret


mark_begin:
mov cx,topbot
mov bx,cx
sub cx,toptop
mark_begin_1:
cmp [bx-2].w,LINENEW ;at beginning?
je mark_begin_2 ;yes.
dec bx
dec cx
jmp mark_begin_1
mark_begin_2:
ret


mark_end:
mov cx,topbot ;start at point
sub cx,toptop
mov bx,bottop
mark_end_1:
cmp bx,botbot ;at end?
je mark_end_2 ;yes.
cmp [bx].w,LINENEW ;at end?
je mark_end_2 ;yes.
inc bx
inc cx
jmp mark_end_1
mark_end_2:
ret


mark_word_right:
mov cx,topbot ;start at point
sub cx,toptop
mov bx,bottop
mark_word_right_1:
cmp bx,botbot ;end of buffer is end of word.
je mark_word_right_2
mov al,[bx] ;is this character a blank?
call get_syntax
test al,1
je mark_word_right_2 ;yes - we're done.
inc bx
inc cx
jmp mark_word_right_1
mark_word_right_2:
ret


mark_word_left:
mov cx,topbot ;start at point
mov bx,cx
sub cx,toptop
jcxz mark_word_left_1 ;if nothing to the left, leave.
dec bx
mark_word_left_2:
mov al,[bx] ;is this character a blank?
call get_syntax
test al,1
je mark_word_left_1 ;yes - exit now.
dec bx
dec cx
jne mark_word_left_2
mark_word_left_1:
ret


mark_lblanks:
mov cx,topbot ;start at point
mov bx,cx
sub cx,toptop
jcxz mark_lblanks_1 ;if nothing to left, leave.
dec bx
cmp [bx-1].w,LINENEW ;starting at newline?
jne mark_lblanks_2 ;no.
sub cx,2 ;yes - move back over it.
sub bx,2
jcxz mark_lblanks_1 ;if nothing more to left, leave.
mark_lblanks_2:
mov al,[bx] ;is this char a blank?
call get_syntax
test al,3 ;non-blank or line break?
jne mark_lblanks_1 ;yes - exit now.
dec bx
dec cx
jne mark_lblanks_2
mark_lblanks_1:
ret


mark_rblanks:
mov cx,topbot ;start at point
sub cx,toptop
mov bx,bottop
cmp bx,botbot ;starting at end of buffer?
je mark_rblanks_2 ;yes - end.
cmp [bx].w,LINENEW ;starting at newline?
jne mark_rblanks_1 ;no.
add bx,2 ;start by skipping the newline.
add cx,2
mark_rblanks_1:
cmp bx,botbot ;end of buffer is end of word.
je mark_rblanks_2 ;yes - end.
mov al,[bx]
call get_syntax
test al,3 ;non-blank or line break?
jne mark_rblanks_2 ;yes - exit now.
inc bx
inc cx
jmp mark_rblanks_1
mark_rblanks_2:
ret


public split_at_point
split_at_point:
;return cy if the split mark is at or after the point.
mov cx,split_mark
mov ax,topbot
sub ax,toptop
cmp split_mark,ax ;is the split mark at or after the point?
jae split_at_point_1 ;yes - return cy.
clc
ret
split_at_point_1:
stc
ret


public get_split_mark
get_split_mark:
;same as get_mark('*'), only faster.
mov cx,split_mark
jmp short compute_mark
get_mark:
;enter with al=number of mark to get.
call get_mark_count
compute_mark:
;enter with cx=the number of characters before the point.
;exit with cx=count of chars between the mark and the point, si->text at mark,
;cy=1 if mark is after the point.
mov si,topbot
sub si,toptop
sub cx,si
jb compute_mark_1
mov si,bottop ;make si->bottom
add si,cx ;make si->text.
stc
ret
compute_mark_1:
mov si,topbot ;Compute pointer to text.
add si,cx ; cx is difference between topbot and mark,
neg cx ; which is negative. make it positive.
clc
ret


assume es:data


adjust_marks_ins:
;enter with ax=number of characters inserted
;exit with all marks adjusted accordingly.
;if a mark is at or after the point, move it up or down.
;if a mark is before the point, leave it alone.
mov cl,temp_mark_count
mov ch,0
inc cx
mov bx,offset mark_offset-2
mov dx,topbot
sub dx,toptop
adjust_marks_ins_1:
mov si,[bx] ;get a mark
cmp si,dx ;is it before the point?
jb adjust_marks_ins_2 ;yes.
adjust_marks_ins_3:
add si,ax ;no - adjust it and store it back.
mov [bx],si
adjust_marks_ins_2:
add bx,2 ;go to the next mark.
loop adjust_marks_ins_1
ret


adjust_marks_del:
;enter with ax=number of characters deleted.
;exit with all marks adjusted accordingly.
;if a mark is after the point, move it up or down.
;if a mark is at or before the point, leave it alone.
;Adjusting for deletion is more complex than adjusting for insertion,
; because we have to adjust all the marks that fall in the range of
; the characters deleted.
mov cl,temp_mark_count
mov ch,0
inc cx
mov bx,offset mark_offset-2
mov dx,topbot
sub dx,toptop ;make dx -> before first mark to adjust
mov di,dx
add di,ax ;make di -> last mark to adjust.
adjust_marks_del_1:
mov si,[bx] ;get a mark
cmp si,dx ;is it at or before the point?
jbe adjust_marks_del_2 ;yes.
cmp si,di ;does it mark a deleted character?
ja adjust_marks_del_3 ;no - adjust it down.
mov [bx],dx ;all deleted marks will mark the point.
jmp short adjust_marks_del_2
adjust_marks_del_3:
sub si,ax ;no - adjust it and store it back.
mov [bx],si
adjust_marks_del_2:
add bx,2 ;go to the next mark.
loop adjust_marks_del_1
ret

assume es:nothing

public get_syntax
get_syntax:
;enter with al=character.
;don't change any other registers.
;exit with al=syntax of that character.
push ds
push bx
mov ds,ss:syntax_seg
assume ds:formSeg
mov bx,formSeg:syntax_table
cmp bx,NIL
je get_syntax_3
push ax
mov ax,formSeg:[bx].name_length
add ax,formSeg:[bx].form_pointer
add bx,(size form_struc) ;make bx->name.
add bx,ax ;make bx->data.
pop ax
xlat formSeg:byte_ptr
pop bx
pop ds
ret
get_syntax_3:
pop bx
pop ds
assume ds:nothing
cmp al,'_'
je get_syntax_1
cmp al,cr
je get_syntax_2
cmp al,lf
je get_syntax_2
cmp al,'0'
jb get_syntax_0
cmp al,'9'
jbe get_syntax_1
cmp al,'A'
jb get_syntax_0
cmp al,'Z'
jbe get_syntax_1
cmp al,'a'
jb get_syntax_0
cmp al,'z'
jbe get_syntax_1
get_syntax_0:
mov al,0
ret
get_syntax_1:
mov al,1
ret
get_syntax_2:
mov al,2
ret


code ends

end



  3 Responses to “Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP
Filename : MARKS.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/