home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / cpm86 / fmacs86.ark / MEMORY.A86 < prev    next >
Text File  |  1989-02-09  |  12KB  |  472 lines

  1. sequential_read    equ    0
  2. debugging    equ    0
  3.  
  4.     pagesize    86
  5.  
  6. HT    equ    09h
  7. LF    equ    0ah
  8. CR    equ    0dh
  9. LINENEW    equ    CR+LF*256    ;the way a newline is stored in memory.
  10.  
  11.     include    bufseg.a86    ;buffer definitions
  12.  
  13. data    dseg    byte public
  14.  
  15. ;the following externs are in 'buffers'
  16.     extrn    textseg:word
  17.  
  18. insert_ds    rw    1
  19.  
  20.   if sequential_read
  21. read_pointer    rw    1
  22.   endif
  23.  
  24. ;data    ends
  25.  
  26. code    cseg    byte public
  27. ;all the routines in this segment are entered with ds=data, es=data
  28.     ;assume ###    cs:code, ds:data, es:data
  29.  
  30. ;the following externs are in 'marks'
  31.     extrn    init_marks:near,get_mark:near
  32.     extrn    adjust_marks_del:near,adjust_marks_ins:near
  33.  
  34. ;the following externs are in 'redisp'
  35.     extrn    prevline:near,nextline:near,compute_one:near
  36.  
  37.  
  38.     public    count_lines
  39. count_lines:    push ds ! mov ds,textseg
  40.         call count_lines?
  41.         pop ds ! ret
  42.  
  43.     public    del_to_mark
  44. del_to_mark:    push ds ! mov ds,textseg
  45.         call del_to_mark?
  46.         pop ds ! ret
  47.  
  48.     public    read_mark
  49. read_mark:    mov ds,textseg
  50.         call read_mark?
  51.         ret
  52.  
  53.     public    goto_mark
  54. goto_mark:    push ds ! mov ds,textseg
  55.         call goto_mark?
  56.         pop ds ! ret
  57.  
  58.     public    insert_string
  59. insert_string:    push ds ! mov ax,es    ;use data for insert_ds.
  60.         mov ds,textseg
  61.         call insert_string?
  62.         pop ds ! ret
  63.  
  64.     public    set_column
  65. set_column:    push ds ! mov ds,textseg
  66.         call set_column?
  67.         pop ds ! ret
  68.  
  69.     public    set_line
  70. set_line:    push ds ! mov ds,textseg
  71.         call set_line?
  72.         pop ds ! ret
  73.  
  74.     public    compute_cursor
  75. compute_cursor:    push ds ! mov ds,textseg
  76.         call compute_cursor?    ;exit with dx=column.
  77.         pop ds ! ret
  78.  
  79.     public    store_buffer_modified
  80. store_buffer_modified:
  81.         push ds ! mov ds,textseg
  82.         ;assume ### ds:bufseg
  83.         mov buffer_modified,al
  84.         pop ds
  85.         ;assume ### ds:data
  86.         ret
  87.  
  88.     public    read_linecount
  89. read_linecount:    mov bx,offset linecount
  90.         jmps read_variable
  91.  
  92.     public read_linesbefore
  93. read_linesbefore:
  94.         mov bx,offset linesbefore
  95.         jmps read_variable
  96.  
  97.     public    read_buffer_modified
  98. read_buffer_modified:
  99.         mov bx,offset buffer_modified
  100. read_variable:    push ds ! mov ds,textseg
  101.         ;assume ### ds:bufseg
  102.         mov ax,[bx] ! pop ds
  103.         ;assume ### ds:data
  104.         ret
  105.  
  106.     public    file_size
  107. file_size:    mov ds,textseg        ;exit with ax=size of the
  108.         ;assume ### ds:bufseg    ; current buffer in bytes.
  109.         mov ax,topbot
  110.         sub ax,toptop
  111.         add ax,botbot
  112.         sub ax,bottop
  113.         push es ! pop ds
  114.         ;assume ### ds:data
  115.         ret
  116.  
  117.     public    percent_full
  118. percent_full:    push ds ! mov ds,textseg    ;return the percent full
  119.         ;assume ### ds:bufseg        ; amount in ax.
  120.         mov ax,100 ! mov cx,memsize    ;destroy ax,cx,dx.
  121.         jcxz percent_full_1
  122.         mov ax,botbot ! sub ax,bottop    ;compute the size
  123.         add ax,topbot ! sub ax,toptop    ; of the buffer
  124.         mov dx,0 ! div cx
  125.         or dx,dx ! jz $+3
  126.         inc ax ! pop ds
  127. percent_full_1:    ;assume ### ds:data
  128.         ret
  129.  
  130.   if sequential_read
  131.     public    reset_to_top
  132. reset_to_top:    push es ! mov es,textseg
  133.         ;assume ### es:bufseg
  134.         mov ax,toptop
  135.         mov read_pointer,ax
  136.         pop es
  137.         ;assume ### es:data
  138.         ret
  139.  
  140.     public    read_next
  141. read_next:    mov bx,read_pointer
  142.         push es ! mov es,textseg
  143.         ;assume ### es:bufseg
  144.         cmp bx,topbot        ;time to switch to bottom?
  145.         jb read_next_1        ;no.
  146.         mov bx,bottop
  147. read_next_1:    cmp bx,botbot        ;end of file?
  148.         jb read_next_2        ;no.
  149.         stc ! jmps read_next_3
  150. read_next_2:    mov al,[bx] ! inc bx
  151.         mov read_pointer,bx
  152.         clc
  153. read_next_3:    pop es
  154.         ;assume ### es:data
  155.         ret
  156.  
  157.     public    goto_read
  158. goto_read:    ;remember not to go to the LF part of a newline!
  159.         ret            ;for now, do nothing.
  160.   endif
  161.  
  162. if debugging
  163.     extrn    chrout:near,get_next_buffer:near
  164.  
  165.     public    dump_bufseg
  166. dump_bufseg:    mov ds,textseg
  167.         ;assume ### ds:bufseg
  168.         push linesbefore ! push linecount
  169.         push botbot ! push bottop
  170.         push topbot ! push toptop
  171.         mov ax,es ! mov ds,ax
  172.         ;assume ### ds:data
  173.         mov ax,textseg ! call hexout
  174.         pop ax ! call hexout    ;toptop
  175.         pop ax ! call hexout    ;topbot
  176.         pop ax ! call hexout    ;bottop
  177.         pop ax ! call hexout    ;botbot
  178.         pop ax ! call hexout    ;linecount
  179.         pop ax ! call hexout    ;linesbefore
  180.         call get_next_buffer
  181. ;        call hexout
  182. ;        ret
  183. ;        fall through
  184. hexout:        push ax ! mov ax,' '    ;print a leading space.
  185.         call chrout
  186.         pop ax ! push ax
  187.         mov al,ah ! call byteout
  188.         pop ax
  189. byteout:    push ax ! shrb al,4
  190.         call nibout ! pop ax
  191. nibout:        and al,0fh ! add al,90h
  192.         daa ! adc al,40h
  193.         daa ! mov ah,0
  194.         jmp chrout
  195.   endif
  196.  
  197. ;code    ends
  198.  
  199. code    cseg    ;ment    byte public
  200. ;all the code in this segment is entered with ds=bufseg, es=data
  201.     ;assume ###    cs:code, ds:bufseg, es:data
  202.  
  203. ;the following externs are in 'redisp'
  204.     extrn    paint_window:near,trash_line:near
  205.     extrn    window_insert:near,window_delete:near
  206.     extrn    up_lines:near,down_lines:near
  207.  
  208.     public    init_vars?
  209. init_vars?:    mov bx,bufseg_size+2
  210.         mov word ptr 0fffeh[bx],LINENEW
  211.         mov toptop,bx ! mov topbot,bx
  212.         mov bottop,bx ! mov botbot,bx
  213.         mov word ptr [bx],LINENEW
  214.         mov linecount,0
  215.         mov linesbefore,0
  216.         mov buffer_modified,0
  217.         ret
  218.  
  219.     public    insert_string?
  220. insert_string?:
  221. ;enter with si,cx describing the string to insert, ax=segment of string.
  222. ;exit with cy if there isn't enough room to insert the entire string.
  223.         mov es:insert_ds,ax
  224.         jcxz insert_string_1
  225.         mov ax,bottop ! sub ax,topbot    ;compute the free space.
  226.         cmp ax,cx        ;is there enough room for this string?
  227.         jb insert_string_4        ;no - give error.
  228.         mov buffer_modified,1
  229. insert_string_2:push ds ! mov ds,es:insert_ds    ;get an entire word, even
  230.         mov ax,ds:[si]        ;though we might use only the low byte.
  231.         pop ds
  232.         cmp ax,LINENEW         ;newline?
  233.         jne insert_string_3    ;no.
  234.         cmp cx,2        ;must be at least two chars left.
  235.         jb insert_string_3    ;no - can't be newline.
  236.         push cx ! push si
  237.         call inscrlf
  238.         pop si ! pop cx
  239.         inc si ! inc si ! dec cx
  240.         loop insert_string_2
  241.         jmps insert_string_1
  242. insert_string_3:push cx ! push si
  243.         call insone
  244.         pop si ! pop cx
  245.         inc si ! loop insert_string_2
  246. insert_string_1:clc ! ret
  247. insert_string_4:stc ! ret
  248.  
  249. insone:        cmp al,CR ! jne insone_1
  250.         mov bx,bottop
  251.         cmp byte ptr [bx],LF
  252.         jne inschar
  253.         inc bottop
  254.         jmps insone_2
  255. insone_1:    cmp al,LF ! jne inschar
  256.         mov bx,topbot
  257.         cmp byte ptr 0ffffh[bx],CR
  258.         jne inschar
  259.         dec topbot
  260. insone_2:    mov ax,1
  261.         call adjust_marks_del
  262.         call inscrlf
  263.         ret
  264.  
  265. inschar:
  266. ;insert the character in al at the point.
  267. ;unless there is no room.
  268.         mov bx,topbot ! cmp bx,bottop
  269.         jae inschar_1
  270.         push ax ! mov ax,1
  271.         call adjust_marks_ins
  272.         pop ax
  273.         mov di,topbot ! mov [di],al
  274.         inc di
  275.         mov topbot,di
  276.         call trash_line
  277. inschar_1:    ret
  278.  
  279. inscrlf:    mov bx,topbot ! inc bx
  280.         cmp bx,bottop
  281.         jae inscrlf_3
  282.         mov ax,2
  283.         call adjust_marks_ins
  284.         mov di,topbot
  285.         mov word ptr [di],LINENEW
  286.         inc di ! inc di ! mov topbot,di
  287.         inc linesbefore ! inc linecount
  288.         call window_insert    ;say that we inserted a line here.
  289. inscrlf_3:    ret
  290.  
  291. del_to_mark?:    call get_mark
  292.         jcxz del_to_mark_4_j_1
  293.         mov buffer_modified,1
  294.         jc del_to_mark_2        ;go if point>mark
  295.         push bottop
  296.         call move_point_backward    ;swap point and mark (sort of).
  297.         pop si                ;pushed as bottop.
  298. del_to_mark_2:    mov di,toptop ! cmp di,topbot    ;are we at the beginning of the file?
  299.         jne del_to_mark_1        ;no
  300.         cmp si,botbot        ;deleting to the end of the file?
  301.         jne del_to_mark_1    ;no
  302.         mov ax,si ! sub ax,bottop;compute the number of chars deleted.
  303.         mov bottop,si        ;no characters left.
  304.         call adjust_marks_del
  305.         mov linecount,0        ;no lines left.
  306.         call paint_window        ;trash the window.
  307. del_to_mark_4_j_1:jmps del_to_mark_4    ;now exit.
  308. del_to_mark_1:    mov bp,si        ;save the char that we delete to.
  309.         mov ax,si        ;compute the number of chars.
  310.         sub ax,bottop
  311.         call adjust_marks_del    ;fix up the marks first.
  312.         mov si,bottop        ;get the -> first char to delete.
  313. del_to_mark_3:    cmp word ptr [si],LINENEW    ;a newline?
  314.         jne del1_1        ;no - just skip this char.
  315.         inc si            ;extra inc to skip past the CR.
  316.         dec linecount        ;one less line.
  317.         call window_delete    ;fix up the window.
  318. del1_1:        inc si ! cmp bp,si
  319.         jne del_to_mark_3
  320.         mov bottop,si
  321.         call trash_line
  322. ;now check for a newly created newline.
  323.         mov bx,topbot ! cmp byte ptr 0ffffh[bx],CR
  324.         jne del_to_mark_4
  325.         mov bx,bottop ! cmp byte ptr [bx],LF
  326.         jne del_to_mark_4
  327. ;get rid of the LF and CR seperately so that any mark that points to either
  328. ;  one will point to the newline.
  329.         inc bottop        ;get rid of the LF
  330.         mov ax,1
  331.         call adjust_marks_del
  332.         dec topbot        ;get rid of the CR
  333.         mov ax,1
  334.         call adjust_marks_del
  335.         call inscrlf        ;now insert a newline.
  336. del_to_mark_4:    ret
  337.  
  338.     public    goto_mark?
  339. goto_mark?:    call get_mark
  340.         jcxz goto_mark_1
  341.         jnc goto_mark_2
  342.         call move_point_forward
  343.         jmps goto_mark_1
  344. goto_mark_2:    call move_point_backward
  345. goto_mark_1:    ret
  346.  
  347.     public    read_mark?
  348. read_mark?:    call get_mark
  349.         jnc read_mark_1
  350.         mov si,bottop
  351. read_mark_1:    ret
  352.  
  353. move_point_backward:
  354.         mov si,topbot ! mov di,bottop
  355.         push es ! push ds ! pop es
  356.         std ! dec si ! dec di
  357.         push cx ! rep movsb ! pop cx
  358.         inc si ! inc di ! cld ! pop es
  359.         mov topbot,si ! mov bottop,di
  360.         call count_lines?
  361.         sub linesbefore,bx
  362.         call up_lines
  363.         ret
  364.  
  365. move_point_forward:
  366.         mov si,bottop ! mov di,topbot
  367.         push di ! push cx ! push es
  368.         push ds ! pop es
  369.         rep movsb ! pop    es
  370.         mov bottop,si ! mov topbot,di
  371.         pop cx ! pop di
  372.         call count_lines?
  373.         add linesbefore,bx
  374.         call down_lines
  375.         ret
  376.  
  377. count_lines?:
  378. ;count the number of newlines contained in the text described by ds:di,cx.
  379.         push es ! push ds ! pop es
  380.         mov bx,0
  381. count_lines_1:    mov al,CR ! repnz scasb
  382.         jcxz count_lines_2
  383.         cmp byte ptr [di],LF
  384.         jne count_lines_1
  385.         inc bx ! jmps count_lines_1
  386. count_lines_2:    pop es ! ret
  387.  
  388.     public    set_line?
  389. set_line?:
  390. ;given a line number in ax, move to that line.
  391.         dec ax            ;linesbefore is zero based.
  392.         or ax,ax        ;if negative, use zero.
  393.         jns set_line_0
  394.         xor ax,ax
  395. set_line_0:    sub ax,linesbefore
  396.         je set_line_1        ;go if we're already on that line.
  397.         jb set_line_2        ;go if we're after that line.
  398.         mov cx,ax
  399.         mov si,bottop
  400. set_line_4:    call nextline
  401.         loopne set_line_4
  402.         mov cx,si        ;compute the number of characters.
  403.         sub cx,bottop
  404.         call move_point_forward
  405.         jmps set_line_1
  406. set_line_2:    neg ax ! mov cx,ax    ;ax is the number of lines to move.
  407.         mov si,topbot
  408.         cmp word ptr 0fffeh[si],LINENEW;are we at the beginning of a line?
  409.         je set_line_3        ;yes.
  410.         call prevline        ;no, go to the beginning of the line.
  411. set_line_3:    call prevline
  412.         loopne    set_line_3
  413.         mov cx,topbot        ;compute the number of characters.
  414.         sub cx,si
  415.         call move_point_backward
  416. set_line_1:    ret
  417.  
  418. set_column?:
  419. ;given a column number in ax, move to that column.
  420.         mov bx,ax        ;save the column number in bx.
  421.         dec bx        ;columns are zero based.
  422.         mov si,topbot
  423.         jmps set_column?_2
  424. set_column?_1:    dec si
  425. set_column?_2:    cmp word ptr 0fffeh[si],LINENEW
  426.         jne set_column?_1
  427. ;now move over to the point, counting the size of characters on the way.
  428.         mov dx,0
  429.         mov cx,topbot
  430.         sub cx,si
  431.         jcxz set_column?_3
  432. set_column?_4:    cmp dx,bx    ;are we at or past the desired column?
  433.         jae set_column?_6    ;yes - move the point backward.
  434.         lodsb
  435.         call compute_one
  436.         loop set_column?_4
  437. set_column?_3: ;the desired column is somewhere after the point.
  438.         mov si,bottop
  439. set_column?_7:    cmp dx,bx    ;are we at or past the desired column?
  440.         jae set_column?_5    ;yes - go to the column.
  441.         cmp word ptr [si],LINENEW;are we at the end of the line?
  442.         je set_column?_5    ;yes - this is as close as we can get.
  443.         lodsb            ;compute the next character.
  444.         call compute_one
  445.         jmps set_column?_7
  446. set_column?_5:    mov cx,si ! sub cx,bottop
  447.         call move_point_forward
  448.         ret
  449. set_column?_6:    call move_point_backward
  450.         ret
  451.  
  452.     public    compute_cursor?
  453. compute_cursor?: ;return the column in dx.
  454.         mov    si,topbot    ;find the beginning of this line.
  455.         jmps compute_cursor?_2
  456. compute_cursor?_1:
  457.         dec si
  458. compute_cursor?_2:
  459.         cmp word ptr 0fffeh[si],LINENEW
  460.         jne compute_cursor?_1
  461. ;now move over to the point, counting the size of characters on the way.
  462.         mov dx,0 ! mov cx,topbot
  463.         sub cx,si ! jcxz compute_cursor?_3
  464. compute_cursor?_4:
  465.         lodsb ! call compute_one
  466.         loop compute_cursor?_4
  467. compute_cursor?_3:    ret
  468.  
  469. ;code    ends
  470.  
  471.     end
  472.