home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
cpm86
/
fmacs86.ark
/
MEMORY.A86
< prev
next >
Wrap
Text File
|
1989-02-09
|
12KB
|
472 lines
sequential_read equ 0
debugging equ 0
pagesize 86
HT equ 09h
LF equ 0ah
CR equ 0dh
LINENEW equ CR+LF*256 ;the way a newline is stored in memory.
include bufseg.a86 ;buffer definitions
data dseg byte public
;the following externs are in 'buffers'
extrn textseg:word
insert_ds rw 1
if sequential_read
read_pointer rw 1
endif
;data ends
code cseg byte public
;all the routines in this segment are entered with ds=data, es=data
;assume ### cs:code, ds:data, es:data
;the following externs are in 'marks'
extrn init_marks:near,get_mark:near
extrn adjust_marks_del:near,adjust_marks_ins:near
;the following externs are in 'redisp'
extrn prevline:near,nextline:near,compute_one:near
public count_lines
count_lines: push ds ! mov ds,textseg
call count_lines?
pop ds ! ret
public del_to_mark
del_to_mark: push ds ! mov ds,textseg
call del_to_mark?
pop ds ! ret
public read_mark
read_mark: mov ds,textseg
call read_mark?
ret
public goto_mark
goto_mark: push ds ! mov ds,textseg
call goto_mark?
pop ds ! ret
public insert_string
insert_string: push ds ! mov ax,es ;use data for insert_ds.
mov ds,textseg
call insert_string?
pop ds ! ret
public set_column
set_column: push ds ! mov ds,textseg
call set_column?
pop ds ! ret
public set_line
set_line: push ds ! mov ds,textseg
call set_line?
pop ds ! ret
public compute_cursor
compute_cursor: push ds ! mov ds,textseg
call compute_cursor? ;exit with dx=column.
pop ds ! ret
public store_buffer_modified
store_buffer_modified:
push ds ! mov ds,textseg
;assume ### ds:bufseg
mov buffer_modified,al
pop ds
;assume ### ds:data
ret
public read_linecount
read_linecount: mov bx,offset linecount
jmps read_variable
public read_linesbefore
read_linesbefore:
mov bx,offset linesbefore
jmps read_variable
public read_buffer_modified
read_buffer_modified:
mov bx,offset buffer_modified
read_variable: push ds ! mov ds,textseg
;assume ### ds:bufseg
mov ax,[bx] ! pop ds
;assume ### ds:data
ret
public file_size
file_size: mov ds,textseg ;exit with ax=size of the
;assume ### ds:bufseg ; current buffer in bytes.
mov ax,topbot
sub ax,toptop
add ax,botbot
sub ax,bottop
push es ! pop ds
;assume ### ds:data
ret
public percent_full
percent_full: push ds ! mov ds,textseg ;return the percent full
;assume ### ds:bufseg ; amount in ax.
mov ax,100 ! mov cx,memsize ;destroy ax,cx,dx.
jcxz percent_full_1
mov ax,botbot ! sub ax,bottop ;compute the size
add ax,topbot ! sub ax,toptop ; of the buffer
mov dx,0 ! div cx
or dx,dx ! jz $+3
inc ax ! pop ds
percent_full_1: ;assume ### ds:data
ret
if sequential_read
public reset_to_top
reset_to_top: push es ! mov es,textseg
;assume ### es:bufseg
mov ax,toptop
mov read_pointer,ax
pop es
;assume ### es:data
ret
public read_next
read_next: mov bx,read_pointer
push es ! mov es,textseg
;assume ### es:bufseg
cmp bx,topbot ;time to switch to bottom?
jb read_next_1 ;no.
mov bx,bottop
read_next_1: cmp bx,botbot ;end of file?
jb read_next_2 ;no.
stc ! jmps read_next_3
read_next_2: mov al,[bx] ! inc bx
mov read_pointer,bx
clc
read_next_3: pop es
;assume ### es:data
ret
public goto_read
goto_read: ;remember not to go to the LF part of a newline!
ret ;for now, do nothing.
endif
if debugging
extrn chrout:near,get_next_buffer:near
public dump_bufseg
dump_bufseg: mov ds,textseg
;assume ### ds:bufseg
push linesbefore ! push linecount
push botbot ! push bottop
push topbot ! push toptop
mov ax,es ! mov ds,ax
;assume ### ds:data
mov ax,textseg ! call hexout
pop ax ! call hexout ;toptop
pop ax ! call hexout ;topbot
pop ax ! call hexout ;bottop
pop ax ! call hexout ;botbot
pop ax ! call hexout ;linecount
pop ax ! call hexout ;linesbefore
call get_next_buffer
; call hexout
; ret
; fall through
hexout: push ax ! mov ax,' ' ;print a leading space.
call chrout
pop ax ! push ax
mov al,ah ! call byteout
pop ax
byteout: push ax ! shrb al,4
call nibout ! pop ax
nibout: and al,0fh ! add al,90h
daa ! adc al,40h
daa ! mov ah,0
jmp chrout
endif
;code ends
code cseg ;ment byte public
;all the code in this segment is entered with ds=bufseg, es=data
;assume ### cs:code, ds:bufseg, es:data
;the following externs are in 'redisp'
extrn paint_window:near,trash_line:near
extrn window_insert:near,window_delete:near
extrn up_lines:near,down_lines:near
public init_vars?
init_vars?: mov bx,bufseg_size+2
mov word ptr 0fffeh[bx],LINENEW
mov toptop,bx ! mov topbot,bx
mov bottop,bx ! mov botbot,bx
mov word ptr [bx],LINENEW
mov linecount,0
mov linesbefore,0
mov buffer_modified,0
ret
public insert_string?
insert_string?:
;enter with si,cx describing the string to insert, ax=segment of string.
;exit with cy if there isn't enough room to insert the entire string.
mov es:insert_ds,ax
jcxz insert_string_1
mov ax,bottop ! sub ax,topbot ;compute the free space.
cmp ax,cx ;is there enough room for this string?
jb insert_string_4 ;no - give error.
mov buffer_modified,1
insert_string_2:push ds ! mov ds,es:insert_ds ;get an entire word, even
mov ax,ds:[si] ;though we might use only the low byte.
pop ds
cmp ax,LINENEW ;newline?
jne insert_string_3 ;no.
cmp cx,2 ;must be at least two chars left.
jb insert_string_3 ;no - can't be newline.
push cx ! push si
call inscrlf
pop si ! pop cx
inc si ! inc si ! dec cx
loop insert_string_2
jmps insert_string_1
insert_string_3:push cx ! push si
call insone
pop si ! pop cx
inc si ! loop insert_string_2
insert_string_1:clc ! ret
insert_string_4:stc ! ret
insone: cmp al,CR ! jne insone_1
mov bx,bottop
cmp byte ptr [bx],LF
jne inschar
inc bottop
jmps insone_2
insone_1: cmp al,LF ! jne inschar
mov bx,topbot
cmp byte ptr 0ffffh[bx],CR
jne inschar
dec topbot
insone_2: mov ax,1
call adjust_marks_del
call inscrlf
ret
inschar:
;insert the character in al at the point.
;unless there is no room.
mov bx,topbot ! cmp bx,bottop
jae inschar_1
push ax ! mov ax,1
call adjust_marks_ins
pop ax
mov di,topbot ! mov [di],al
inc di
mov topbot,di
call trash_line
inschar_1: ret
inscrlf: mov bx,topbot ! inc bx
cmp bx,bottop
jae inscrlf_3
mov ax,2
call adjust_marks_ins
mov di,topbot
mov word ptr [di],LINENEW
inc di ! inc di ! mov topbot,di
inc linesbefore ! inc linecount
call window_insert ;say that we inserted a line here.
inscrlf_3: ret
del_to_mark?: call get_mark
jcxz del_to_mark_4_j_1
mov buffer_modified,1
jc del_to_mark_2 ;go if point>mark
push bottop
call move_point_backward ;swap point and mark (sort of).
pop si ;pushed as bottop.
del_to_mark_2: mov di,toptop ! cmp di,topbot ;are we at the beginning of the file?
jne del_to_mark_1 ;no
cmp si,botbot ;deleting to the end of the file?
jne del_to_mark_1 ;no
mov ax,si ! sub ax,bottop;compute the number of chars deleted.
mov bottop,si ;no characters left.
call adjust_marks_del
mov linecount,0 ;no lines left.
call paint_window ;trash the window.
del_to_mark_4_j_1:jmps del_to_mark_4 ;now exit.
del_to_mark_1: mov bp,si ;save the char that we delete to.
mov ax,si ;compute the number of chars.
sub ax,bottop
call adjust_marks_del ;fix up the marks first.
mov si,bottop ;get the -> first char to delete.
del_to_mark_3: cmp word ptr [si],LINENEW ;a newline?
jne del1_1 ;no - just skip this char.
inc si ;extra inc to skip past the CR.
dec linecount ;one less line.
call window_delete ;fix up the window.
del1_1: inc si ! cmp bp,si
jne del_to_mark_3
mov bottop,si
call trash_line
;now check for a newly created newline.
mov bx,topbot ! cmp byte ptr 0ffffh[bx],CR
jne del_to_mark_4
mov bx,bottop ! cmp byte ptr [bx],LF
jne del_to_mark_4
;get rid of the LF and CR seperately so that any mark that points to either
; one will point to the newline.
inc bottop ;get rid of the LF
mov ax,1
call adjust_marks_del
dec topbot ;get rid of the CR
mov ax,1
call adjust_marks_del
call inscrlf ;now insert a newline.
del_to_mark_4: ret
public goto_mark?
goto_mark?: call get_mark
jcxz goto_mark_1
jnc goto_mark_2
call move_point_forward
jmps goto_mark_1
goto_mark_2: call move_point_backward
goto_mark_1: ret
public read_mark?
read_mark?: call get_mark
jnc read_mark_1
mov si,bottop
read_mark_1: ret
move_point_backward:
mov si,topbot ! mov di,bottop
push es ! push ds ! pop es
std ! dec si ! dec di
push cx ! rep movsb ! pop cx
inc si ! inc di ! cld ! pop es
mov topbot,si ! mov bottop,di
call count_lines?
sub linesbefore,bx
call up_lines
ret
move_point_forward:
mov si,bottop ! mov di,topbot
push di ! push cx ! push es
push ds ! pop es
rep movsb ! pop es
mov bottop,si ! mov topbot,di
pop cx ! pop di
call count_lines?
add linesbefore,bx
call down_lines
ret
count_lines?:
;count the number of newlines contained in the text described by ds:di,cx.
push es ! push ds ! pop es
mov bx,0
count_lines_1: mov al,CR ! repnz scasb
jcxz count_lines_2
cmp byte ptr [di],LF
jne count_lines_1
inc bx ! jmps count_lines_1
count_lines_2: pop es ! ret
public set_line?
set_line?:
;given a line number in ax, move to that line.
dec ax ;linesbefore is zero based.
or ax,ax ;if negative, use zero.
jns set_line_0
xor ax,ax
set_line_0: sub ax,linesbefore
je set_line_1 ;go if we're already on that line.
jb set_line_2 ;go if we're after that line.
mov cx,ax
mov si,bottop
set_line_4: call nextline
loopne set_line_4
mov cx,si ;compute the number of characters.
sub cx,bottop
call move_point_forward
jmps set_line_1
set_line_2: neg ax ! mov cx,ax ;ax is the number of lines to move.
mov si,topbot
cmp word ptr 0fffeh[si],LINENEW;are we at the beginning of a line?
je set_line_3 ;yes.
call prevline ;no, go to the beginning of the line.
set_line_3: call prevline
loopne set_line_3
mov cx,topbot ;compute the number of characters.
sub cx,si
call move_point_backward
set_line_1: ret
set_column?:
;given a column number in ax, move to that column.
mov bx,ax ;save the column number in bx.
dec bx ;columns are zero based.
mov si,topbot
jmps set_column?_2
set_column?_1: dec si
set_column?_2: cmp word ptr 0fffeh[si],LINENEW
jne set_column?_1
;now move over to the point, counting the size of characters on the way.
mov dx,0
mov cx,topbot
sub cx,si
jcxz set_column?_3
set_column?_4: cmp dx,bx ;are we at or past the desired column?
jae set_column?_6 ;yes - move the point backward.
lodsb
call compute_one
loop set_column?_4
set_column?_3: ;the desired column is somewhere after the point.
mov si,bottop
set_column?_7: cmp dx,bx ;are we at or past the desired column?
jae set_column?_5 ;yes - go to the column.
cmp word ptr [si],LINENEW;are we at the end of the line?
je set_column?_5 ;yes - this is as close as we can get.
lodsb ;compute the next character.
call compute_one
jmps set_column?_7
set_column?_5: mov cx,si ! sub cx,bottop
call move_point_forward
ret
set_column?_6: call move_point_backward
ret
public compute_cursor?
compute_cursor?: ;return the column in dx.
mov si,topbot ;find the beginning of this line.
jmps compute_cursor?_2
compute_cursor?_1:
dec si
compute_cursor?_2:
cmp word ptr 0fffeh[si],LINENEW
jne compute_cursor?_1
;now move over to the point, counting the size of characters on the way.
mov dx,0 ! mov cx,topbot
sub cx,si ! jcxz compute_cursor?_3
compute_cursor?_4:
lodsb ! call compute_one
loop compute_cursor?_4
compute_cursor?_3: ret
;code ends
end