home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / cpm86 / fmacs86.ark / BUFFERS.A86 next >
Encoding:
Text File  |  1989-02-10  |  8.3 KB  |  396 lines

  1.     pagesize    86
  2. v30        equ    0    
  3. test_device    equ    0
  4. cr        equ    0dh
  5. lf        equ    0ah
  6.  
  7.     if v30
  8. ;macros for NEC V20/V30 or Intel 80186/286
  9.     codemacro SHRW parm:ew,count:db        ;shift word right by
  10.         db 0c1h                ;immediate count
  11.         modrm 5,parm
  12.         db count
  13.         endm
  14.     endif
  15.  
  16. ;CCPM function EQUs
  17. mc_max        equ    35h
  18. mc_free        equ    39h
  19.  
  20.     codemacro CCPM parm:db            ;call CCPM
  21.         db 0b1h ! db parm            ;mov cl,parm
  22.         db 0cdh ! db 0e0h            ;int 0E0H
  23.         endm
  24.  
  25.     include    bufseg.a86        ;buffer definitions
  26.  
  27. data    dseg    word public
  28.  
  29.     public    textseg
  30. textseg        dw    0ffffh        ;segment of current buffer
  31.  
  32. first_buffer    dw    0ffffh        ;segment of first buffer
  33.  
  34.     extrn    inverse_flag: byte
  35.  
  36. mcb        rb    5        ;memory control block
  37. mcb_base    equ     word ptr mcb
  38. mcb_length    equ    word ptr mcb+2
  39. mcb_ext        equ    byte ptr mcb+4
  40.  
  41. ;data    ends
  42.  
  43.  
  44. code    cseg    byte public
  45. ;all the routines in this segment are entered with ds=data, es=data
  46.     ;*** assume    cs:code, ds:data, es:data, ss:data
  47.  
  48. ;the following externs are in 'memory'
  49.     extrn    read_mark: near
  50.     extrn    del_to_mark: near
  51.  
  52. ;the following externs are in 'redisplay'
  53.     extrn    redisplay: near
  54.     extrn    paint_screen: near
  55.  
  56.     extrn    init_entry: near
  57.     extrn    uninit_exit: near
  58.  
  59.     extrn    abort_fatal: near    ;fatal error handler
  60.  
  61.  
  62.     public    get_next_buffer
  63. get_next_buffer:
  64.     push    ds
  65.     mov    ds,textseg
  66.     ;*** assume    ds:bufseg
  67.     mov    ax,next_buffer
  68.     pop    ds
  69.     ;*** assume    ds:data
  70.     ret
  71.  
  72.     public    buffer_allocate
  73. buffer_allocate:
  74. ;entry:
  75. ;  case cx of
  76. ;    -1..-32768: report the current buffer number.
  77. ;      exit: ax=current buffer number.
  78. ;    0: create a new buffer.
  79. ;      exit: ax=new buffer number if enough memory, ax=0 otherwise.
  80. ;    1..32767:
  81. ;      entry: cx=buffer number to select, ax=0 for read/write buffer.
  82. ;      exit: ax=buffer number if it exists, ax=0 otherwise.
  83.     jcxz    buffer_allocate_2
  84.     or cx,cx ! jns $+5        ;if cx<0, return buffer number.
  85.     jmp buffer_allocate_7
  86.                 ;****** select buffer ******
  87.     push    cx
  88.     push    ax
  89.     call    find_buffer
  90.     jc    buffer_allocate_1    ;buffer not found.
  91.  
  92.     push    ds
  93.     push    dx
  94.     mov    ds,dx            ;get the current buffer back.
  95.     call    select_buffer
  96.     pop    dx
  97.     pop    ds
  98.  
  99.     pop    cx            ;pushed as ax =0 if read/write buffer.
  100.     pop    ax            ;pushed as cx (buffer number).
  101.     ret
  102.  
  103. buffer_allocate_1:
  104.     add    sp,4            ;conserve the stack.
  105.     mov    ax,0            ;buffer not found.
  106.     ret
  107.  
  108. buffer_allocate_2:        ;****** create a new buffer ******
  109.     mov mcb_length,1000h        ;max. = 64K
  110.     xor ax,ax ! mov mcb_base,ax
  111.     mov mcb_ext,al
  112.     mov dx,offset mcb
  113.     ccpm mc_max            ;allocate memory
  114.     or al,al ! jnz buffer_allocate_3;no memory
  115.     mov ax,bufseg_size+0fh
  116.     if v30
  117.     shrw ax,4
  118.     else
  119.     shl ax,1 ! shl ax,1 ! shl ax,1 ! shl ax,1
  120.     endif 
  121.     cmp mcb_length,ax
  122.     ja buffer_allocate_4        ;there is enough memory
  123.     mov mcb_ext,0
  124.     mov dx,offset mcb
  125.     ccpm mc_free            ;free this small memory block
  126. buffer_allocate_3:
  127.     xor ax,ax ! ret            ;error return
  128. buffer_allocate_4:
  129.     mov ax,1 ! push es
  130.     mov dx,first_buffer
  131.     cmp dx,0ffffh
  132.     jne buffer_allocate_5
  133.     mov cx,mcb_base
  134.     mov first_buffer,cx
  135.     jmps buffer_allocate_6
  136. buffer_allocate_5:    inc ax
  137.     mov es,dx ! mov dx,es:next_buffer
  138.     cmp dx,0ffffh ! jne buffer_allocate_5
  139.     mov cx,mcb_base
  140.     mov es:next_buffer,cx
  141. buffer_allocate_6:
  142.     mov cx,mcb_length
  143.     mov es,mcb_base
  144.     mov es:buffer_length,cx
  145.     mov es:next_buffer,0ffffh
  146.     pop es ! push ds ! push ax
  147.     mov ds,mcb_base
  148.     call init_vars?
  149.     call init_marks
  150.     call open_buffer
  151.     pop ax ! pop ds ! ret
  152.  
  153. buffer_allocate_7:        ;****** return current buffer number ******
  154.     mov    bx,ss:textseg
  155.     call    buffer_number        ;return number in ax.
  156.     ret
  157.  
  158.  
  159.     public    buffer_insert
  160. buffer_insert:
  161. ;enter with al=mark, cx=buffer number.
  162. ;insert the text between point and mark from the given buffer.
  163. ;exit with nc if ok, cy if the given buffer doesn't exist, or the specified
  164. ;  text won't fit.
  165.     push    textseg
  166.     push    ax
  167.     call    find_buffer        ;find their buffer.
  168.     ;*** assume    ds:bufseg
  169.     jc    buffer_insert_1        ;not found.
  170.  
  171.     push    ds
  172.     push    dx
  173.     mov    ds,dx            ;get the current buffer back.
  174.     call    select_buffer
  175.     pop    dx
  176.     pop    ds
  177.  
  178.     pop    ax
  179.  
  180.     push    dx
  181.     call    read_mark
  182.     pop    dx
  183.  
  184.     pop    ds            ;make ds->our buffer.
  185.     push    dx            ;save ->their buffer.
  186.     push    cx
  187.     call    select_buffer
  188.     pop    cx
  189.     pop    ax            ;pushed as dx.
  190.     call    insert_string?
  191.     jmps buffer_insert_2
  192. buffer_insert_1:
  193.     add    sp,4            ;get rid of mark, textseg.
  194.     stc
  195. buffer_insert_2:
  196.     push    es            ;restore ds.
  197.     pop    ds
  198.     ;*** assume    ds:data
  199.     ret
  200.  
  201.  
  202.     public    buffer_number
  203. buffer_number:
  204. ;enter with bx=paragraph of buffer.
  205. ;exit with ax=number of buffer.
  206.     push    ds
  207.     ;*** assume    ds:bufseg
  208.     mov    dx,ss:first_buffer
  209.     xor    ax,ax
  210. buffer_number_1:
  211.     inc    ax
  212.     mov    ds,dx
  213.     cmp    dx,bx            ;is this the one we're looking for.
  214.     mov    dx,next_buffer        ;in any case, get the next buffer
  215.     jne    buffer_number_1
  216. buffer_number_2:
  217.     pop    ds
  218.     ;*** assume    ds:data
  219.     ret
  220.  
  221.  
  222.     public    succ_buffer
  223. succ_buffer:
  224. ;enter with bx=buffer number.
  225. ;exit with nc, bx=next nonempty buffer, dx=segment of next buffer,
  226. ;  cy if no other buffers or all other buffers are empty.
  227.     push    ds
  228.     mov    cx,bx
  229.     mov    ax,bx
  230.     mov    dx,first_buffer
  231.     ;*** assume    ds:bufseg
  232. succ_buffer_2:
  233.     cmp    dx,0FFFh        ;at the end?
  234.     stc
  235.     je    succ_buffer_3        ;yes - don't change the buffer number.
  236.     mov    ds,dx
  237.     mov    dx,next_buffer
  238.     loop    succ_buffer_2
  239. succ_buffer_0:
  240.     cmp    dx,0FFFFh        ;are we at the end?
  241.     jne    succ_buffer_1
  242.     mov    ds,first_buffer        ;yes - start from the beginning again.
  243.     mov    dx,next_buffer        ;skip the first buffer.
  244.     mov    ax,1
  245. succ_buffer_1:
  246.     inc    ax            ;preincrement.
  247.     cmp    ax,bx            ;have we wrapped around?
  248.     stc
  249.     je    succ_buffer_3        ;yes - exit.
  250.     mov    ds,dx            ;get the new segment to try.
  251.     mov    dx,topbot        ;is the next buffer empty?
  252.     sub    dx,toptop
  253.     add    dx,botbot
  254.     sub    dx,bottop
  255.     mov    dx,next_buffer
  256.     je    succ_buffer_0        ;yes - keep looking.
  257.     mov    bx,ax            ;return the new buffer number.
  258.     clc
  259. succ_buffer_3:
  260.     mov    dx,ds            ;remember the segment.
  261.     ;*** assume    ds:data
  262.     pop    ds
  263.     ret
  264.  
  265.  
  266.     public    find_buffer
  267. find_buffer:
  268. ;enter with cx=buffer number.
  269. ;exit with nc, dx set to that buffer if it exists, cy otherwise.
  270.     mov    dx,first_buffer
  271.     ;*** assume    ds:bufseg
  272. find_buffer_1:
  273.     cmp    dx,0FFFFh        ;at the end?
  274.     je    find_buffer_2
  275.     mov    ds,dx
  276.     mov    dx,next_buffer
  277.     loop    find_buffer_1
  278.     mov    dx,ds            ;get the current buffer back.
  279.     push    es
  280.     pop    ds
  281.     clc
  282.     ret
  283. find_buffer_2:
  284.     push    es            ;restore the data segment.
  285.     pop    ds
  286.     ;*** assume    ds:data
  287.     stc
  288.     ret
  289.  
  290.  
  291. ;code    ends
  292.  
  293.  
  294. code    cseg    byte public
  295. ;all the code in this segment is entered with ds=bufseg, es=data
  296.     ;*** assume    cs:code, ds:bufseg, es:data
  297.  
  298. ;the following externs are in 'memory'
  299.     extrn    init_vars?: near
  300.     extrn    insert_string?: near
  301.  
  302. ;the following externs are in 'marks'
  303.     extrn    init_marks: near
  304.  
  305. ;the following externs are in 'redisp'
  306.     extrn    adjust_buffers: near
  307.  
  308.  
  309. select_buffer:
  310. ;enter with ds=buffer to select.
  311.     mov    ss:textseg,ds        ;save the new current buffer.
  312.     mov    ax,botbot
  313.     sub    ax,toptop
  314.     mov    dx,0
  315.     mov    cx,100
  316.     div    cx
  317.     mov    memsize,ax
  318.     ret
  319.  
  320. close_buffer:
  321. ;close the buffer in ds.
  322.     mov    ax,topbot        ;if topbot<>bottop, then it's open.
  323.     cmp    ax,bottop
  324.     je    close_buffer_1        ;if it's already closed, we're done.
  325.     mov    di,topbot
  326.   if 1
  327.     mov    ax,ds            ;if it's open and it's not the first
  328.     cmp    ax,ss:first_buffer    ;  buffer, close it.
  329.     jne    close_buffer_2
  330.     add    di,2000            ;leave at most this many free bytes 
  331.     cmp    di,bottop        ;  in buffer one.
  332.     jae    close_buffer_1        ;but if we can't leave that many, don't bother
  333. close_buffer_2:
  334.   endif
  335.     mov    si,bottop
  336.     mov    bottop,di        ;save the new bottop.
  337.     mov    cx,botbot
  338.     sub    cx,si            ;same as sub cx,bottop
  339.     add    cx,2            ;include the trailing newline.
  340.     push    es
  341.     push    ds
  342.     pop    es
  343.     rep    movsb
  344.     pop    es
  345.     sub    di,2            ;don't include the newline in botbot.
  346.     mov    botbot,di
  347. close_buffer_1:
  348.     ret
  349.  
  350.  
  351. open_buffer:
  352. ;select the buffer in ds.
  353. ;enter with ds=buffer to open.
  354.     mov    bx,buffer_length
  355.     mov    ax,ds
  356.     mov    di,bx
  357.     add    bx,ax            ;make bx=first unused para.
  358.     mov    cl,04            ;change di from paras into bytes
  359.     shl    di,cl
  360.     push    es
  361.     push    ds
  362.     pop    es
  363.     mov    si,botbot
  364.     std
  365.     mov    cx,botbot
  366.     sub    cx,bottop
  367.     inc    si
  368.     dec    di
  369.     movsb                ;move the LF
  370.     mov    botbot,di
  371.     movsb                ;move the CR
  372.     rep    movsb
  373.     inc    di
  374.     mov    bottop,di
  375.     cld
  376.     pop    es
  377.     call    select_buffer
  378.     ret
  379.  
  380. buffer_paragraphs:
  381. ;compute the number of paragraphs used by a buffer.
  382. ;enter with ds=buffer
  383. ;exit with cx=number of paragraphs.
  384.     mov    cx,botbot
  385.     add    cx,0fh+2        ;round up to next paragraph plus two for newline
  386.     rcr    cx,1            ;ensure that 65536 bytes becomes  
  387.     shr    cx,1            ; 1000h paragraphs.
  388.     shr    cx,1
  389.     shr    cx,1
  390.     ret
  391.  
  392.  
  393. ;code    ends
  394.  
  395.     end
  396.