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

 
Output of file : REDISP.ASM contained in archive : EMAC15ES.ZIP
;History:474,1
;Fri Jun 02 00:36:53 1989 gotoxy should position the cursor also.
;Sun Mar 26 20:45:02 1989 optimize a little code in store_current_window.
;06-26-88 23:53:50 in chrout, CR was changing the line w/o setting TRASHED.
;05-17-88 22:39:59 Make CGA scroll if only one line [kdb]
;05-17-88 22:09:22 Force redraw for CGA [kdb]
;05-17-88 19:39:15 Remove reference to scrwait [kdb]
;04-01-88 22:42:23 add tab_size to allow for varying tab sizes.
;03-26-88 14:37:44 on 40 column screens, fix horizontal scrolling (40 / 2) % 8 != 0
;11-16-87 23:18:13 remove memsize
;11-15-87 22:50:18 make w1_windseg, and w2_windseg for buffers.asm's sake.
;09-09-87 00:48:00 compute the middle of the screen, rather than assuming column 40.
;07-13-87 23:08:49 remove xyputch
;07-13-87 22:58:51 move the call to paint_screen into init_screen.
;07-07-87 22:37:35 also check for eof in trailing blanks code
;07-07-87 22:12:44 check for bottom correctly in redraw_line
;07-07-87 22:10:54 in redraw_line, move the check where we need it.
;07-06-87 06:52:39 use botbot to check for eof, not LINENEW
.xlist

HT equ 09h
LF equ 0ah
CR equ 0dh
LINENEW equ CR+LF*256 ;the way a newline is stored in memory.

TRAIL_BLANK equ 4dh
TRAIL_TAB equ 4eh
MORE_CHAR equ 52h
NEWLINE_CHAR equ 54h

bufseg segment byte public

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

extrn linecount: word
extrn linesbefore: word

bufseg ends

data segment byte public

if 1
public w1, w2, this_point, this_row, other_row, topbotpercent
public botpercent, toppercent, firstlimit, lastlimit, overwrite_row
public overwrite_col, screen_column, window, inversed, inverse_mark
public showblanks
endif

;pointrow contains the row that the cursor is currently on, relative to the
; screen boundaries. Pointrow may be negative if the point is above the screen,
; or it may be larger than max_screen_line if the point is below the screen.

wind_struc struc
windseg dw ?
pointrow dw ?
firstline db ?
lastline db ?
firstpossible db ?
lastpossible db ?
firstcolumn dw ?
wind_struc ends

w1 wind_struc<>

w2 wind_struc<>

public w1_windseg, w2_windseg
w1_windseg equ w1.windseg
w2_windseg equ w2.windseg


this_point dw ? ;->point in the current file.
this_row dw ? ;row of point on screen.
other_row dw ? ;row of point in other window.

topbotpercent label word
botpercent db ?
toppercent db ?

firstlastlimits label word
firstlimit db ?
lastlimit db ?


public tab_size
tab_size dw 7 ;mask for tab stops.

public next_redisp_line
next_redisp_line dw 0

public overwrite_flag
overwrite_flag db 0 ;=0 if not overwriting.

overwrite_rowcol label word
overwrite_row db 0
overwrite_col db 0

;the following externs are in the computer-dependent file
extrn max_screen_line: byte
extrn num_screen_cols: byte

;the following externs are in 'buffers'
extrn textseg: word

screen_column dw ?

;window contains a list of which lines should be moved where, and which
; lines need to be redrawn. If an entry is positive, then the line which is
; currently at x belongs at window[x]. If an entry is TRASHED, it
; should be redrawn.
;inversed contains a list of which lines currently show inverse video.
window db 128 dup(?) ;128 is > max_screen_line
inversed db 128 dup(?) ;. .
inverse_flag db 0 ;=0 means no inversing.
public inverse_seg ;used by buffers.asm to adjust.
inverse_seg dw 0 ;segment of marked buffer.
public inversing ;used by ibm.asm or z100.asm to control
inversing dw 0 ; which lines are inversed.

inverse_mark dw ? ;pointing to the inverse mark.

TRASHED equ -1 ;note that TRASHED must be negative.

showblanks db 0

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 the computer-dependent file.
extrn move_line: near
extrn clear_to_eol: near
extrn xychrout: near
extrn hardware_roll_up: near
extrn hardware_roll_down: near
extrn position_cursor: near
extrn read_ibm_cga: near

;the following externs are in 'memory'
extrn compute_cursor$: near
extrn set_line$: near

;the following externs are in 'buffers'
extrn buffer_number: near
;enter with bx=paragraph of buffer.
;exit with ax=number of buffer.
extrn buffer_allocate: near
extrn find_buffer: near
;enter with cx=buffer number.
;exit with nc, dx set to that buffer if it exists, cy otherwise.

;the following externs are in 'marks'
extrn read_mark$: near
extrn goto_mark$: near
extrn get_split_mark: near
extrn get_mark: near
extrn split_at_point: near
extrn set_mark_si: near
extrn set_mark: near
extrn stack_marks: near
extrn goto_mark: near


public read_current_window
read_current_window:
mov ax,1 ;probably window 1.
cmp w2.windseg,0 ;no window 2 - must be 1.
je read_current_window_1
mov bl,w1.firstline
cmp bl,w2.firstline
jb read_current_window_1
inc ax
read_current_window_1:
ret


public store_current_window
store_current_window:
cmp ax,1
jne store_current_window_1
mov al,w1.firstline
cmp al,w2.firstline
jb store_current_window_2
jmp short store_current_window_3
store_current_window_1:
cmp ax,2
jne store_current_window_2
mov al,w1.firstline
cmp al,w2.firstline
ja store_current_window_2
store_current_window_3:
cmp w2.windseg,0 ;is there a second window?
je store_current_window_2 ;no - don't swap.
call swap_other_row
call swap_windows
store_current_window_2:
ret


swap_other_row:
mov ax,w1.windseg ;are we in the other window?
cmp ax,w2.windseg
jne swap_other_row_1 ;no - no worries.
push w1.pointrow ;remember what other_row will be.

mov ax,1
call stack_marks
mov ax,'*'*256+'0' ;0 := *
call set_mark
mov ax,'.'*256+'*' ;* := .
call set_mark
mov al,'0' ;. := 0
call goto_mark
mov ax,0
call stack_marks

pop other_row
swap_other_row_1:
ret


public read_other_window
read_other_window:
mov bx,w2.windseg
or bx,bx
je read_other_window_1
call buffer_number
ret
read_other_window_1:
xor ax,ax
ret


public store_other_window
store_other_window:
;enter with ax=buffer segment to show.
mov cx,ax ;do they want one window?
jcxz store_other_window_3 ;yes.
call find_buffer ;find the buffer.
jc store_other_window_3 ;can't find it - give them one window.

cmp w2.windseg,0 ;do we have another window to set?
jne store_other_window_1 ;yes - just set it.
push dx
call split_screen
pop dx
store_other_window_1:
cmp dx,w2.windseg ;is it already showing?
je store_other_window_2 ;yes - they're being silly.

mov w2.windseg,dx ;show the buffer here.

cmp w1.windseg,dx ;is this buffer also in w1?
jne store_other_window_4 ;no - no worries.

mov ax,w1.pointrow ;the place that the this window is at
mov other_row,ax ; becomes the other row.

mov ax,'.'*256+'*' ;set the split mark to the point.
call set_mark

store_other_window_4:
mov bl,w2.firstline ;trash what's there.
mov al,w2.lastline
call trash_some_lines
store_other_window_2:
ret

store_other_window_3:
mov w2.windseg,0
mov al,max_screen_line ;fill the screen with this window.
mov w1.lastline,al
mov w1.firstline,0
mov si,offset w1
call set_window_percent
call paint_screen
ret


split_screen:
mov al,max_screen_line
mov w2.lastline,al
sar al,1
dec al
mov w1.lastline,al
add al,2
mov w2.firstline,al
split_recompute:
mov si,offset w1
call set_window_percent

mov si,offset w2
call set_window_percent

call paint_screen

ret


public store_firstline
store_firstline:
cmp w2.windseg,0 ;do we really have two windows?
je store_firstline_1 ;no.
cmp w1.firstline,0 ;are we the top window?
je store_firstline_1 ;yes - we can't set it.
cmp al,2 ;less than 2?
jb store_firstline_1 ;yes - would leave no room for the top.
mov w1.firstline,al
sub al,2
mov w2.lastline,al

call split_recompute
store_firstline_1:
ret


public store_lastline
store_lastline:
cmp w2.windseg,0 ;do we really have two windows?
je store_lastline_1 ;no.
cmp w1.firstline,0 ;are we the top window?
jne store_lastline_1 ;no - we can't set it.
mov ah,max_screen_line
sub ah,2
cmp al,ah ;at the screen size?
ja store_lastline_1 ;yes - would leave no room for the top.
mov w1.lastline,al
add al,2
mov w2.firstline,al

call split_recompute
store_lastline_1:
ret


public store_showblanks
store_showblanks:
cmp showblanks,al ;are we changing it?
mov showblanks,al ;store it in any case.
je store_showblanks_1 ;if we changed it, paint the window.
call paint_window
store_showblanks_1:
ret


public read_showblanks
read_showblanks:
mov al,showblanks
ret


public read_firstline
read_firstline:
mov al,w1.firstline
ret


public read_lastline
read_lastline:
mov al,w1.lastline
ret


public read_newrow
read_newrow:
mov ax,w1.pointrow
ret


public read_firstcolumn
read_firstcolumn:
mov ax,w1.firstcolumn
ret


public store_firstcolumn
store_firstcolumn:
and ax,not 7 ;go to the next leftmost tab stop.
push ax
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
pop w1.firstcolumn
ret


public read_top_percent
read_top_percent:
mov al,toppercent
ret


public read_bot_percent
read_bot_percent:
mov al,botpercent
ret


public store_top_percent
store_top_percent:
mov toppercent,al
mov si,offset w1
call set_window_percent
ret


public store_bot_percent
store_bot_percent:
mov botpercent,al
mov si,offset w1
call set_window_percent
ret


public read_inverse_mark
read_inverse_mark:
mov al,inverse_flag
ret


public store_inverse_mark
store_inverse_mark:
mov inverse_flag,al
mov ax,textseg
mov inverse_seg,ax
ret

public init_screen
init_screen:
xor al,al
mov w1.firstline,al
mov w1.firstpossible,al
mov al,max_screen_line ;fill the screen with this window.
mov w1.lastline,al
mov w1.lastpossible,al
mov w1.firstcolumn,0
mov ax,textseg
mov w1.windseg,ax
call paint_screen
ret


public gotoxy
gotoxy:
cmp dl,max_screen_line ;is max_screen_line ok?
jbe gotoxy_1 ;yes.
mov dl,max_screen_line ;no - take min(dl, max_screen_line)
gotoxy_1:
cmp dh,num_screen_cols ;are we on the screen?
jb gotoxy_2
mov dh,num_screen_cols ;no - take min(dh, num_screen_cols-1)
dec dh
gotoxy_2:
mov overwrite_rowcol,dx
call position_cursor
ret


public chrout
chrout:
;enter with ax=char to "type" on screen.
;preserve si.
cmp overwrite_flag,0 ;are we already overwriting?
jne chrout_1 ;yes.
mov overwrite_flag,1 ;say that we're overwriting
mov window[0],TRASHED ;trash the first line.
chrout_1:
mov dx,overwrite_rowcol ;get the cursor position.
cmp al,CR ;go to left margin?
jne chrout_4
mov bh,0 ;trash the line because we're clearing it.
mov bl,dl
mov window[bx],TRASHED
call clear_to_eol ;yes - clear to end here.
mov dh,0
jmp chrout_exit
chrout_4:
cmp al,LF ;go down a line?
jne chrout_5
inc dl
cmp dl,max_screen_line ;are we past the last line?
jbe chrout_exit ;no.
call paint_screen ;yes - paint the whole thing.
call hardware_roll_up ;yes - roll the screen up.
jnc chrout_6
mov dl,1 ;have to software scroll.
chrout_7:
mov al,dl
dec al
call move_line
inc dl
cmp dl,max_screen_line
jbe chrout_7
chrout_6:
mov dl,max_screen_line ;say on the last line.
push dx ;clear the entire line.
mov dh,0
call clear_to_eol
pop dx
jmp short chrout_exit
chrout_5:
cmp al,HT
jne chrout_8
chrout_9:
mov ah,0
mov al,' '
call chrout_putch
test dh,byte ptr tab_size
jnz chrout_9
jmp short chrout_exit
chrout_8:
call chrout_putch
chrout_exit:
mov overwrite_rowcol,dx ;remember where we are.
call position_cursor
ret


chrout_putch:
mov bh,0 ;trash the line.
mov bl,dl
mov window[bx],TRASHED
call xychrout
inc dh
ret


public redisplay
redisplay:

mov ax,textseg ;is the current buffer showing in w1?
cmp ax,w1.windseg
je redisplay$_1 ;yes - all ok.

xchg w1.windseg,ax ;no - put it in this window.
cmp ax,w2.windseg ;was the old w1 showing in w2?
jne redisplay$_2 ;no - nothing special.

push ds
mov ds,w2.windseg
mov al,'*' ;yes - make the split mark the point
call goto_mark$
pop ds

redisplay$_2:

mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines

mov ax,w1.windseg ;is this buffer also in w2?
cmp ax,w2.windseg
jne redisplay$_1 ;no - no worries.

mov bl,w2.firstline ;yes - trash one line so that
mov bh,0 ; the point is recomputed. hack, hack.
mov window[bx],TRASHED

mov ax,w2.pointrow ;the place that the other window is at
mov other_row,ax ; becomes the other row.

mov ax,'.'*256+'*' ;set the split mark to the point.
call set_mark

redisplay$_1:

mov overwrite_flag,0 ;no longer overwriting.
mov dx,0 ;start in the upper left hand corner
mov overwrite_rowcol,dx ; the next time we overwrite.
if 0
mov dx,0*256+24 ;dh=column, dl=row.
mov si,offset window
rd_0:
lodsb
add al,'A'
call xychrout
inc dh
cmp dh,25
jb rd_0
mov si,offset inversed
rd_1:
lodsb
add al,'0'
call xychrout
inc dh
cmp dh,48
jb rd_1

endif

push ds
mov ds,w1.windseg
assume ds:bufseg

mov si,topbot
mov this_point,si

mov ax,next_redisp_line

call force_point_into_window
mov ax,w1.pointrow
mov this_row,ax

call redraw_trashed

mov ax,this_row
mov w1.pointrow,ax

pop ds
assume ds:data

mov dx,screen_column
sub dx,w1.firstcolumn
mov dh,dl
mov dl,byte ptr w1.pointrow
call position_cursor

cmp w2.windseg,0 ;is there a second window?
je redisplay_one ;no.
call swap_windows
push ds
mov ax,w1.windseg ;are they the same file?
cmp ax,w2.windseg
mov ds,ax ;really w2.
assume ds:bufseg
jne redisplay__2
;two windows into the same buffer.
call get_split_mark ;get the split mark.
cmp si,bottop ;are we at the point?
jne redisplay__1 ;no.
mov si,topbot ;yes - always use the top point.
redisplay__1:
mov this_point,si
mov ax,other_row ;get the row in the other window.
mov this_row,ax
call redraw_trashed
mov ax,this_row
xchg other_row,ax
sub ax,other_row ;how much did we adjust it by?
sub w1.pointrow,ax ;adjust pointrow, too.

jmp short redisplay__3
redisplay__2:
;two windows, two buffers.
mov si,topbot
mov this_point,si
xor ax,ax
call force_point_into_window
mov ax,w1.pointrow
mov this_row,ax
call redraw_trashed
mov ax,this_row
mov w1.pointrow,ax

redisplay__3:
call swap_windows
pop ds
assume ds:data
redisplay_one:
mov next_redisp_line,0 ;no more desired line
ret


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


set_window_percent:
;note that set_window_percent doesn't use ds.
;enter with si->window to set.
mov cl,100
mov ch,data:[si].lastline
sub ch,data:[si].firstline
inc ch
mov al,toppercent
mul ch
div cl
cmp al,ch
jb set_window_percent_1
xor al,al
set_window_percent_1:
add al,data:[si].firstline
mov data:[si].firstpossible,al
mov al,botpercent
mul ch
div cl
mov ch,data:[si].lastline
sub ch,al
jae set_window_percent_2
mov ch,data:[si].lastline
set_window_percent_2:
mov data:[si].lastpossible,ch
ret


roll_window_down_2_j_1:
jmp roll_window_down_2
roll_window_down_5_j_1:
jmp roll_window_down_5

roll_window_down:
;roll the window down until pointrow is in the window.

mov al,firstlimit
cbw
cmp w1.pointrow,ax ;if pointrow>=firstlimit, we don't
jge roll_window_down_2_j_1 ; need to roll down.

;Are there any lines now on the screen that will remain? Go if not.

mov cx,w1.pointrow
mov bh,0
mov bl,w1.lastline
add cx,bx
mov bl,w1.firstline
sub cx,bx
mov bl,firstlimit
cmp cx,bx
jl roll_window_down_5_j_1 ;we have to repaint the entire window.

;Repaint screen if CGA, believe it or not, it is faster
call read_ibm_cga
cmp al,0
je roll_window_down_normal
mov cx,w1.pointrow
mov bl,firstlimit
mov bh,0
sub cx,bx
inc cx ;Scroll if only one line
jnz roll_window_down_5_j_1 ; it looks better

roll_window_down_normal:

mov dx,w1.pointrow
mov cl,w1.firstline
mov ch,0
sub dx,cx
inc dx

;now compute the number of times we need to roll.

mov cx,w1.pointrow
sub cx,bx
mov w1.pointrow,bx ;bx is firstlimit
neg cx

if 0
;Can we use the hardware scroll? Go if not.

cmp w1.firstline,0
jne roll_window_down_3
mov al,max_screen_line
cmp w1.lastline,al
jne roll_window_down_3
endif

;Use the hardware scroll unless there isn't one.

xchg cx,dx ;get the distance to skip
call skip_to_line
mov cx,dx

roll_window_down_4:
mov ah,w1.firstline
mov al,w1.lastline
call hardware_roll_down
jc roll_window_down_3 ;can't hardware roll.

;now adjust window[] for the change we just made to the screen.

mov bl,w1.firstline
mov bh,0
mov al,window[bx] ;save the current values for later.
mov ah,inversed[bx]
push ax
push si
call redraw_compare ;remember if we're inversing here.
mov inversed[bx],al
call redraw_line
call remember_redrawn
pop si
call prevline
mov window[bx],bl ;remember that this line is real.
pop ax ;restore the old values.
roll_window_down_6:
cmp al,TRASHED ;is this a trashed line?
je roll_window_down_7
inc al ;no - say that the line's moved up.
cmp al,max_screen_line ;did it roll off the screen?
jbe roll_window_down_7 ;no.
mov al,TRASHED ;yes - it's gone.
roll_window_down_7:
inc bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.lastline
jb roll_window_down_6
loop roll_window_down_4
jmp short roll_window_down_2

;repaint screen.

roll_window_down_5:
call center_this
jmp short roll_window_down_2

;Use software scroll. All we do is roll the window array.

roll_window_down_3:
mov bl,w1.firstline
mov bh,0
mov al,window[bx] ;save the current value for later.
mov ah,inversed[bx]
mov window[bx],TRASHED
roll_window_down_1:
inc bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.lastline
jb roll_window_down_1
loop roll_window_down_3
roll_window_down_2:
ret


roll_window_up_2_j_1:
jmp roll_window_up_2
roll_window_up_5_j_1:
jmp roll_window_up_5

roll_window_up:

mov al,lastlimit
cbw
cmp w1.pointrow,ax ;if pointrow<=lastlimit, we don't
jle roll_window_up_2_j_1 ; need to roll up.

;compute: pointrow-(lastline-firstline) > lastlimit

;Are there any lines now on the screen that will remain? Go if not.

mov cx,w1.pointrow
mov bh,0
mov bl,w1.firstline
add cx,bx
mov bl,w1.lastline
sub cx,bx
mov bl,lastlimit
cmp cx,bx
jg roll_window_up_5_j_1 ;we have to repaint the entire window.

;Repaint screen if CGA, believe it or not, it is faster
call read_ibm_cga
cmp al,0
je roll_window_up_normal
mov cx,w1.pointrow
mov bl,lastlimit
mov bh,0
sub cx,bx
dec cx ;Scroll if only one line
jnz roll_window_up_5_j_1 ; it looks better

roll_window_up_normal:

mov dx,w1.pointrow
mov cl,w1.lastline
mov ch,0
sub dx,cx
dec dx

;now compute the number of times we need to roll.

mov cx,w1.pointrow
sub cx,bx
mov w1.pointrow,bx ;bx is lastlimit.

;Can we use hardware scroll? Go if not.

if 0
cmp w1.firstline,0
jne roll_window_up_3
mov al,max_screen_line
cmp w1.lastline,al
jne roll_window_up_3
endif

;Use the hardware scroll unless there isn't one.

xchg cx,dx ;get the distance to skip
call skip_to_line
mov cx,dx

roll_window_up_4:
mov ah,w1.firstline
mov al,w1.lastline
call hardware_roll_up
jc roll_window_up_3 ;can't hardware roll.

;now adjust window[] for the change we just made to the screen.

mov bl,w1.lastline
mov bh,0
mov al,window[bx] ;save the current values for later.
mov ah,inversed[bx]
push ax
call redraw_compare ;remember if we're inversing here.
mov inversed[bx],al
call redraw_line
call remember_redrawn
mov window[bx],bl ;remember that this line is real.
pop ax ;restore old values.
roll_window_up_6:
cmp al,TRASHED ;has this line been trashed?
je roll_window_up_7
dec al ;no - say the line's been moved.
roll_window_up_7:
dec bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.firstline
ja roll_window_up_6
loop roll_window_up_4
jmp short roll_window_up_2

;repaint screen.

roll_window_up_5:
call center_this
jmp short roll_window_up_2

;Use software scroll. All we do is roll the window array.

roll_window_up_3:
mov bl,w1.lastline
mov bh,0
mov al,window[bx] ;save the current value for later.
mov ah,inversed[bx]
mov window[bx],TRASHED
roll_window_up_1:
dec bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.firstline
ja roll_window_up_1
loop roll_window_up_3
roll_window_up_2:
ret


;enter with pointrow=current relative screen line
;exit with a line inserted before pointrow.
public window_insert
window_insert:
push si
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne window_insert_1
mov si,offset w1
call window_ins
window_insert_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne window_insert_2
mov si,offset w2
call window_ins
window_insert_2:
mov ax,ds ;are we showing in both windows?
cmp ax,w1.windseg
jne window_insert_3
cmp ax,w2.windseg
jne window_insert_3
call split_at_point ;is the split mark at or after the point?
jnc window_insert_3 ;no
inc other_row ;yes - must increment the other row.
window_insert_3:
pop si
ret

;private subroutine, called by window_insert to insert a line in a window.
;enter with si-> a window structure.
window_ins:
mov bx,data:[si].pointrow
mov al,data:[si].firstline
cbw
cmp bx,ax ;are we above the screen?
jl window_ins_3 ;yes - exit.
mov al,data:[si].lastline
cmp bx,ax ;are we below the screen?
jg window_ins_2 ;yes - go down a row.

mov window[bx],TRASHED
mov al,TRASHED
jmp short window_ins_4
window_ins_1:
xchg al,window[bx]
xchg ah,inversed[bx]
window_ins_4:
inc bl
cmp bl,data:[si].lastline
jbe window_ins_1
window_ins_2:
inc data:[si].pointrow
window_ins_3:
ret


;enter with pointrow=current relative screen line
;exit with the line at pointrow deleted.
public window_delete
window_delete:
push si
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne window_delete_1
mov si,offset w1
call window_del
window_delete_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne window_delete_2
mov si,offset w2
call window_del
window_delete_2:
mov ax,ds ;are we showing in both windows?
cmp ax,w1.windseg
jne window_delete_3
cmp ax,w2.windseg
jne window_delete_3
call split_at_point ;is the split mark at or after the point?
jnc window_delete_3 ;no
dec other_row ;yes - must decrement the other row.
window_delete_3:
pop si
ret

;private subroutine, called by window_delete to delete a line from a window.
;enter with si-> a window structure.
window_del:
mov bx,data:[si].pointrow
mov al,data:[si].firstline
cbw
cmp bx,ax ;are we above the screen?
jl window_del_4 ;yes.
mov al,data:[si].lastline
cbw
cmp bx,ax ;are we below the screen?
jg window_del_1 ;yes.

mov window[bx],TRASHED ;kill the line the cursor is on.
jmp short window_del_5 ;go into while...do loop
window_del_4:
inc data:[si].pointrow
jmp short window_del_1
window_del_3:
mov al,window[bx+1]
mov ah,inversed[bx+1]
mov window[bx],al
mov inversed[bx],ah
window_del_5:
inc bl
cmp bl,data:[si].lastline
jb window_del_3
mov window[bx],TRASHED ;kill lastline
window_del_1:
ret


public trash_line
trash_line:
;destroy the line that the point is on if it's also in the window.
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne trash_line_1
mov si,offset w1
call trash_line_0
trash_line_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne trash_line_2
mov si,offset w2
call trash_line_0
trash_line_2:
ret


;enter with si-> a window structure.
trash_line_0:
mov bx,data:[si].pointrow
mov al,data:[si].firstline
cbw
cmp bx,ax
jl trash_line_3
mov al,data:[si].lastline
cbw
cmp bx,ax
jg trash_line_3
mov window[bx],TRASHED
trash_line_3:
ret


public up_lines
up_lines:
mov ax,ds ;is this in window 2?
cmp ax,w1.windseg
jne up_lines_1
sub w1.pointrow,bx
up_lines_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne up_lines_2
sub w2.pointrow,bx
up_lines_2:
ret


public down_lines
down_lines:
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne down_lines_1
add w1.pointrow,bx
down_lines_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne down_lines_2
add w2.pointrow,bx
down_lines_2:
ret


public paint_screen
paint_screen:
;note that paint doesn't use ds.
;what's on the screen is garbage.
;preserve si, dx.
mov bl,0
mov al,max_screen_line
call trash_some_lines
ret


center_window:
;note that center doesn't use ds.
;preserve dx.
center_this:
mov cl,w1.lastline ;compute the middle of the screen.
sub cl,w1.firstline
sar cl,1
add cl,w1.firstline
mov ch,0
mov w1.pointrow,cx
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
ret


public paint_window
paint_window:
;preserve dx.
mov ax,textseg
cmp ax,w1.windseg
jne paint_window_1
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
paint_window_1:
mov ax,textseg
cmp ax,w2.windseg
jne paint_window_2
mov bl,w2.firstline
mov al,w2.lastline
call trash_some_lines
paint_window_2:
ret


trash_some_lines:
;enter with bl=first line to destroy, al=last line.
;preserve si, dx.
mov w1.firstcolumn,0 ;go to the first column.
mov bh,0
trash_some_lines_0:
mov window[bx],TRASHED
inc bl
cmp bl,al
jbe trash_some_lines_0
mov al,w1.firstpossible ;ensure that we're not above the screen.
cbw
cmp w1.pointrow,ax
jge trash_some_lines_1 ;we're not.
mov w1.pointrow,ax
trash_some_lines_1:
mov al,w1.lastpossible ;ensure that we're not below the screen.
cbw
cmp w1.pointrow,ax
jle trash_some_lines_2 ;we're not.
mov w1.pointrow,ax
trash_some_lines_2:
ret


;swap the two window data structures.
swap_windows:
mov si,offset w1
mov di,offset w2
mov cx,(size wind_struc)
swap_windows_0:
mov al,data:[si]
xchg al,data:[di]
mov data:[si],al
inc si
inc di
loop swap_windows_0
ret


force_point_into_window:
;enter with al=the desired row, =0 if we don't care.
comment /**********************************************************************
* roll the window array until pointrow is on the screen.
* when we roll the array, the lines we roll in must be repainted.
* for example, assume: screen is 0..23
* if pointrow is 5, then we're done.
* if pointrow is -7, then we must roll down 7 lines.
* if pointrow is <=-24, then we must roll down 24 lines, which says that the
* entire screen will be repainted.
* if pointrow is 27, then we must roll up 3 lines.
* if pointrow is >=48, then we must roll up 24 lines, which says that the
* entire screen will be repainted.
*****************************************************************************/
mov bl,w1.firstpossible
mov bh,w1.lastpossible
or al,al ;do we have a desired row?
je redisplay_1 ;no.
dec al
cmp al,bl ;above firstpossible?
ja redisplay_0 ;yes - ok.
mov al,bl ;no - clip to firstpossible.
redisplay_0:
cmp al,bh ;below lastpossible?
jb redisplay_00 ;yes - ok.
mov al,bh ;no - clip to lastpossible.
redisplay_00:
mov bl,al
mov bh,al
redisplay_1:
mov firstlastlimits,bx
;now truncate firstlimit if we can't get there.
mov al,firstlimit
cbw ;compute the number of display lines
sub al,w1.firstline ; desired before the cursor line.
cmp ax,linesbefore ;is it even possible to get there?
jb redisplay_2 ;yes - just do it.
mov ax,linesbefore ;no - truncate firstlimit to
add al,w1.firstline ; the largest possible.
mov firstlimit,al
redisplay_2:

;Now update row,col

call compute_cursor$
mov screen_column,dx
sub dx,w1.firstcolumn ;are we to the left of the screen?
jb redisplay_01 ;yes - must roll the screen right.
cmp dx,word ptr num_screen_cols ;are we on the screen?
jb redisplay_02 ;yes - we don't have the roll left.

;roll the window to the left.

comment /
Eventually, we'll be smart about all this and really scroll the screen.
For now, we'll repaint the screen every time we roll.
jmp short redisplay_02
/

redisplay_01:

;roll the window to the right.

comment /
Eventually, we'll be smart about all this and really scroll the screen.
For now, we'll repaint the screen every time we roll.
/

add dx,w1.firstcolumn ;restore the cursor position.
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
mov ax,word ptr num_screen_cols
shr ax,1
sub dx,ax ;put the cursor in middle of screen.
jae redisplay_03
mov dx,0 ;column is less than 40.
redisplay_03:
and dl,not 7 ;back up to previous tab stop.
mov w1.firstcolumn,dx ;that is where we start redisplaying.......................
redisplay_02:

;now roll the screen up or down, as needed.

call roll_window_down
call roll_window_up
ret


redraw_trashed:
;redraw all changed lines if there are any to redraw.
redraw_trashed_4:
mov bl,w1.firstline
mov bh,0
mov dh,0 ;initially, we don't need to redraw any.
redraw_trashed_3:
mov dl,window[bx] ;get new window contents.
or dh,dl ;remember if we need to redraw any.
or dl,dl ;if positive, it's a line to be moved.
js redraw_trashed_5 ;if negative, skip it.
cmp dl,bl ;is the line already there?
je redraw_trashed_5 ;yes - skip it.
mov di,offset window ;is this row referred to?
mov cl,max_screen_line
inc cl
mov ch,0
mov al,bl
repne scasb ;scan for the row.
je redraw_trashed_5 ;yes - we can't move something here.
call move_line ;move dl to al.
mov dh,0 ;get the source line.
mov di,dx
mov al,inversed[di] ;transfer the inversed contents.
mov inversed[bx],al
mov window[bx],bl ;say that this line is where it is.
jmp redraw_trashed_4 ;restart search.
redraw_trashed_5:
inc bl
cmp bl,w1.lastline
jbe redraw_trashed_3

cmp inverse_flag,0 ;if we're inversing, we might need to redraw.
jne redraw_trashed_1
or dh,dh ;do we need to redraw any lines?
jns redraw_trashed_9 ;no.

redraw_trashed_1:
mov bl,w1.firstline
mov bh,0
mov cx,this_row ;get the row that the point is on.
sub cx,bx
call skip_to_line ;find the first line on the screen.
call redraw_anyway ;see if we need to redraw anyway.
redraw_trashed_7:
call redraw_compare ;remember if we're inversing here.
mov inversed[bx],al
cmp window[bx],0
jns redraw_trashed_a ;if negative, redraw it.
call redraw_line
mov window[bx],bl ;remember that this line is drawn.
redraw_trashed_a:
call remember_redrawn
inc bl
cmp bl,w1.lastline
jbe redraw_trashed_7
redraw_trashed_9:
mov inversing,0 ;say that we're not inversing.
ret


remember_redrawn:
;enter with si->text, bx=screen line.
;exit with si->next line.
call nextline
shl inversed[bx],1
shl inversed[bx],1
call redraw_compare
or inversed[bx],al
ret


redraw_anyway:
;preserve si,bx.
cmp inverse_flag,0
je redraw_anyway_1
push si
push bx
redraw_anyway_2:
call redraw_compare
push ax
call nextline ;see if this line contains the mark or point.
call redraw_compare
pop cx
mov ch,cl ;save a copy.
xor cl,al ;see if the bits changed.
test cl,1 ;is the point in this line?
jne redraw_anyway_yes ;yes - must redraw.
shl ch,1
shl ch,1
or al,ch ;make up the compare byte.
cmp al,inversed[bx] ;have they changed?
je redraw_anyway_no ;no - don't necessarily redraw.
redraw_anyway_yes:
mov window[bx],TRASHED ;say that this line is gone.
redraw_anyway_no:
inc bl
cmp bl,w1.lastline
jbe redraw_anyway_2
pop bx
pop si
redraw_anyway_1:
ret


redraw_compare:
;enter with si->text buffer.
;exit with al and 1 = 1 if si ; al and 2 = 2 if si cmp si,inverse_mark ;set cy if si is below inverse_mark (mark)
rcl al,1
cmp si,bottop ;set cy if si is below bottop (point)
rcl al,1
and al,3 ;get rid of other bits.
ret



skip_to_line:
;enter with cx=number of lines to move forward or backward.
;Note: positive values move toward top of file.
;return si -> beginning of desired line.
;don't destroy dx.
mov si,this_point ;get the point.
or cx,cx ;is cx negative?
js skip_to_line_4 ;yes - we have to move forward.
cmp [si-2].w,LINENEW ;if we're not at the beginning of
je skip_to_line_3 ; this line, backup to beginning.
call prevline
skip_to_line_3:
jcxz skip_to_line_2
skip_to_line_1:
call prevline
loopne skip_to_line_1
jne skip_to_line_2 ;did we hit the beginning?
inc cx ;yes - restore the count.
sub this_row,cx ;adjust this row.
jmp short skip_to_line_2
skip_to_line_4:
neg cx ;make cx into a positive count.
;cx is at least one.
skip_to_line_5:
call nextline
loopne skip_to_line_5
skip_to_line_2:
mov al,inverse_flag ;are we inversing?
cmp al,0
je skip_to_line_6 ;no.
push bx
push dx
push si
call get_mark ;the mark is in inverse_flag
mov inverse_mark,si ;remember where the inverse mark is.
pop si
pop dx
pop bx
skip_to_line_6:
ret


redraw_line:
;enter with si -> line to be redrawn, bl=row of line.
;paint from firstcolumn for num_screen_cols columns.
;this routine is intense.
;preserve cx, bx
call redraw_set
mov di,0 ;start at column zero.
mov dh,0
mov dl,bl
mov bl,-1 ;start without trailing blanks.
cmp si,botbot ;are we at bottom already?
je redraw_line_9_j_1 ;yes - clear to eol.
redraw_line_2:
call redraw_pointer
cmp si,botbot ;are we at bottom already?
je redraw_line_3 ;yes - exit.
mov ax,[si]
cmp ax,LINENEW ;done with line?
je redraw_line_3 ;yes - exit.
inc si
cmp dh,num_screen_cols ;at right hand column?
jae redraw_line_d ;yes - don't print.
cmp di,w1.firstcolumn ;before first column?
jb redraw_line_4 ;yes - just compute new column.
cmp al,' ' ;possible trailing blanks.
je redraw_line_a
cmp al,HT
jne redraw_line_b ;not trailing blanks - forget.
redraw_line_a:
cmp bl,-1 ;are we already remembering?
jne redraw_line_c ;yes - don't remember again.
mov bl,dh ;found a trailing blank character,
mov bp,si ; remember where it was.
jmp short redraw_line_c
redraw_line_b:
mov bl,-1 ;printable char - forget trailing blanks.
redraw_line_c:
call xy_char_put
jmp redraw_line_2
redraw_line_d:
cmp dh,num_screen_cols ;did we just get there?
ja redraw_line_2 ;no.
dec dh
mov ax,8*256+MORE_CHAR ;yes - print the "more" symbol.
call xychrout
mov dh,81 ;say that we're in the next column.
jmp redraw_line_2
redraw_line_4:
inc di
cmp al,HT ;only tabs are special
jne redraw_line_2
mov ax,di
add ax,tab_size ;round up to next tab stop.
or ax,tab_size ;same as 'and not'.
xor ax,tab_size
mov di,ax
jmp redraw_line_2
redraw_line_9_j_1:
jmp redraw_line_9
redraw_line_3:
cmp showblanks,0 ;should we show blanks?
je redraw_line_8
cmp bl,-1 ;are there any trailing blanks?
je redraw_line_8 ;no.
mov dh,bl ;restore the column.
xchg si,bp ;save the current and restore the old.
dec si
call redraw_set
redraw_line_7:
call redraw_pointer
cmp si,botbot ;hit the bottom yet?
je redraw_line_e ;yes - we're done.
mov ax,[si] ;get the next char.
cmp ax,LINENEW
je redraw_line_e
cmp dh,num_screen_cols
jae redraw_line_e
inc si
cmp al,' ' ;it can only be a tab or a space.
je redraw_line_6 ;must be a space.
redraw_line_5:
mov ax,8*256+TRAIL_TAB ;output a trailing tab char.
call xychrout
inc dh
test dh,byte ptr tab_size ;at a tab stop yet?
jne redraw_line_5 ;no.
jmp redraw_line_7
redraw_line_6: ;output a trailing blank char.
mov ax,8*256+TRAIL_BLANK
call xychrout
inc dh
jmp redraw_line_7
redraw_line_e:
mov si,bp ;restore the text pointer.
redraw_line_8:
cmp dh,num_screen_cols ;put a newline symbol if there's room.
jae redraw_line_9
cmp inversing,0 ;only if we're inversing.
je redraw_line_9
mov ax,8*256+NEWLINE_CHAR ;newline symbol.
call xychrout
inc dh
redraw_line_9:
call clear_to_eol
mov bh,0 ;restore bx.
mov bl,dl
ret


redraw_pointer:
;adjust si from the top to the bottom if necessary, and adjust inversing.
cmp si,topbot ;at the point yet?
jne redraw_pointer_1 ;no.
mov si,bottop
cmp inverse_flag,0 ;are we inversing?
je redraw_pointer_1 ;no.
mov ax,ds
cmp ax,inverse_seg ;is this our segment?
jne redraw_pointer_1 ;no.
not inversing ;say that we've passed the point.
redraw_pointer_1:
cmp si,inverse_mark ;are we at the inverse mark?
jne redraw_pointer_2 ;yes - maybe inverse.
cmp inverse_flag,0 ;are we inversing?
je redraw_pointer_2 ;no.
mov ax,ds
cmp ax,inverse_seg ;is this our segment?
jne redraw_pointer_2 ;no.
not inversing ;say that we've passed the point.
redraw_pointer_2:
ret


redraw_set:
cmp si,topbot ;have we hit the top bottm yet?
jne redraw_set_3
mov si,bottop
redraw_set_3:
cmp inverse_flag,0 ;if we're not inversing, don't inverse.
je redraw_set_1
mov ax,ds
cmp ax,inverse_seg ;is this our segment?
jne redraw_set_1 ;no.
call redraw_compare
cmp si,inverse_mark ;are we exactly at the mark?
jne redraw_set_2 ;no - just check parity.
xor al,2 ;yes - flip the associated bit.
redraw_set_2:
mov inversing,0 ;say that we're not inversing.
or al,al ;look for 00,11 or 10,01
jpe redraw_set_1 ;go if not within point and mark.
not inversing ;say that we're inversing.
redraw_set_1:
ret


xy_char_put:
;put a char on the screen. Interpret tabs.
cmp al,HT
jne xy_char_put_1
xy_char_put_2:
mov al,' '
call xy_char_put_1
test dh,byte ptr tab_size
jnz xy_char_put_2
ret
xy_char_put_1:
mov ah,0
call xychrout
inc dh
xy_char_put_4:
ret


public prevline
prevline:
;retreat si to the previous line.
;return zr if si->beginning of file (and leave si alone)
;return nz otherwise.

;are we at the beginning of the file already?
cmp si,toptop
je prevline_beginning ;yes - exit.

;where are we in the file?
cmp si,topbot ;at, before or after the point?
jbe prevline_before
prevline_after:
dec si
cmp si,bottop ;have we reached the top of the bottom?
je prevline_at ;yes - drop down to prevline_before.
cmp [si-2].w,LINENEW ;at the beginning of a new line?
jne prevline_after ;no - keep looking.
dec si ;did we just find a non-real newline?
cmp si,bottop ;if we did, then si is now at bottop
je prevline_at ; and we need to keep searching.
inc si ;restore si and exit.
jmp short prevline_exit

prevline_at:
mov si,topbot ;start searching at the bottom
inc si ; of the top.
prevline_before:
dec si
cmp [si-2].w,LINENEW ;at the beginning of a new line?
jne prevline_before ;no - keep looking.
prevline_exit:
or si,si ;return nz
prevline_beginning:
ret


public nextline
nextline:
;advance si to the next line.
;return zr if si->end of file (and leave si alone)
;return nz otherwise.
cmp si,topbot
jne nextline_1
mov si,bottop
nextline_1:
cmp si,botbot
je nextline_2
cmp [si].w,LINENEW
je nextline_3
inc si
jmp nextline
nextline_3:
add si,2
or si,si
ret
nextline_2:
push ax
xor ax,ax
pop ax
ret


public compute_one
compute_one:
cmp al,HT
jne compute_one_1
or dl,byte ptr tab_size ;same as 'and not'
xor dl,byte ptr tab_size
add dx,tab_size
compute_one_1:
inc dx
ret


code ends

end


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