home *** CD-ROM | disk | FTP | other *** search
- ;History:560,23301,1
- .xlist
- page ,132
-
- include memory.def
- include mintdefs.asm
-
- data segment byte public
- extrn syntax_table: 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].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].w,LINENEW ;starting at newline?
- jne mark_rblanks_1 ;no.
- cmp bx,botbot ;starting at end of buffer?
- je mark_rblanks_2 ;yes - end.
- 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 bx
- mov bx,ss:syntax_table
- cmp bx,NIL
- je get_syntax_3
- push ax
- mov ax,ss:[bx].name_length
- lea bx,[size form + bx] ;make bx->name.
- add bx,ax ;make bx->data.
- pop ax
- xlat ss:byte_ptr
- pop bx
- ret
- get_syntax_3:
- pop bx
- 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
-