home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
edit
/
fremacsr
/
memory.asm
< prev
next >
Wrap
Assembly Source File
|
1987-03-16
|
13KB
|
727 lines
sequential_read equ 0
debugging equ 0
.xlist
HT equ 09h
LF equ 0ah
CR equ 0dh
LINENEW equ CR+LF*256 ;the way a newline is stored in memory.
bufseg segment public
public toptop,topbot,bottop,botbot,margin
margin equ 0
toptop dw ?
topbot dw ?
bottop dw ?
botbot dw ?
extrn memsize: word
public linecount, linesbefore
linecount dw ?
linesbefore dw ?
public buffer_modified
buffer_modified db ?
extrn bufseg_size: byte
bufseg ends
data segment byte public
;the following externs are in 'buffers'
extrn textseg: word
insert_ds dw ?
if sequential_read
read_pointer dw ?
endif
data ends
b_struc struc
b db ?
b_struc ends
w_struc struc
w dw ?
w_struc ends
byte_ptr label byte
code segment 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 'buffers'
extrn init_all_buffers: near
;the following externs are in 'marks'
extrn init_marks: near
extrn get_mark: near
extrn adjust_marks_del: near
extrn adjust_marks_ins: near
;the following externs are in 'redisp'
extrn prevline: near
extrn nextline: near
extrn compute_one: near
public init_memory
init_memory:
;enter with ax=>first paragraph of available memory, bx=> first paragraph of
; unavailable memory.
;exit with cy if no memory available.
call init_all_buffers
jc init_memory_1 ;if error, don't bother continuing.
clc
init_memory_1:
ret
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:
;exit with dx=column.
push ds
mov ds,textseg
call compute_cursor$
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
jmp short read_variable
public read_linesbefore
read_linesbefore:
mov bx,offset linesbefore
jmp short 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,bufseg:[bx]
pop ds
assume ds:data
ret
public file_size
file_size:
;exit with ax=size of the current buffer in bytes.
mov ds,textseg
assume ds:bufseg
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:
;return the percent full amount in ax.
;destroy ax,cx,dx.
push ds
mov ds,textseg
assume ds:bufseg
mov ax,100
mov cx,memsize
jcxz percent_full_1
mov ax,botbot ;compute the size of the buffer
sub ax,bottop
add ax,topbot
sub ax,toptop
mov dx,0
div cx
cmp dx,0
je percent_full_1
inc ax
percent_full_1:
pop ds
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
jmp short 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
extrn 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 ;toptop
call hexout
pop ax ;topbot
call hexout
pop ax ;bottop
call hexout
pop ax ;botbot
call hexout
pop ax ;linecount
call hexout
pop ax ;linesbefore
call hexout
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
shr al,1
shr al,1
shr al,1
shr al,1
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 segment 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
extrn trash_line: near
extrn window_insert: near
extrn window_delete: near
extrn up_lines: near
extrn down_lines: near
public init_vars$
init_vars$:
mov bx,offset bufseg_size+2
mov [bx-02].w,LINENEW
mov toptop,bx
mov topbot,bx
mov bottop,bx
mov botbot,bx
mov [bx].w,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 insert_ds,ax
jcxz insert_string_1
mov ax,bottop ;compute the free space.
sub ax,topbot
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,insert_ds
mov ax,ds:[si] ;get an entire word, even 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
add si,2
dec cx
loop insert_string_2
jmp short 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 [bx].b,LF
jne inschar
inc bottop
jmp short insone_2
insone_1:
cmp al,LF
jne inschar
mov bx,topbot
cmp [bx-01].b,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 [di].w,LINENEW
add di,2
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 ;are we at the beginning of the file?
cmp di,topbot
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:
jmp short 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 [si].w,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 [bx-1].b,CR
jne del_to_mark_4
mov bx,bottop
cmp [bx].b,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
jmp short 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 [di].b,LF
jne count_lines_1
inc bx
jmp 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
jmp short set_line_1
set_line_2:
neg ax ;ax is the number of lines to move.
mov cx,ax
mov si,topbot
cmp [si-2].w,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
jmp short set_column$_2
set_column$_1:
dec si
set_column$_2:
cmp [si-2].w,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 [si].w,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
jmp 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.
;find the beginning of this line.
mov si,topbot
jmp short compute_cursor$_2
compute_cursor$_1:
dec si
compute_cursor$_2:
cmp [si-2].w,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