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

  1.     pagesize    86
  2.     include mintdefs.a86
  3. cr    equ    0dh
  4. lf    equ    0ah
  5. linenew    equ    0a0dh
  6.  
  7.     include    bufseg.a86    ;buffer definitions
  8.  
  9. data    dseg    byte public
  10.     extrn    syntax_table: word
  11.     extrn    textseg: word
  12.  
  13. ;Marks are referred to by a single ASCII character.  If the mark is a digit,
  14. ;  it is a user-defined mark.
  15. mark_first_temp    equ    '0'    ;first temp mark
  16. mark_last_temp    equ    '9'    ;last temp mark
  17. mark_first_perm    equ    '@'    ;first permanent mark.
  18. mark_last_perm    equ    'Z'    ;last permanent mark.
  19. mark_split    equ    '*'    ;split mark
  20.  
  21. ;If the mark is one of the following characters, it is a system-defined mark.
  22. mark_list    rb    0
  23.     db    '>'        ;character to the right of the point
  24.     dw    mark_right
  25.     db    '<'        ;character to the left of the point.
  26.     dw    mark_left
  27.     db    '['        ;first character in the file.
  28.     dw    mark_top
  29.     db    ']'        ;last character in the file.
  30.     dw    mark_bot
  31.     db    '^'        ;beginning of this line.
  32.     dw    mark_begin
  33.     db    '$'        ;end of this line.
  34.     dw    mark_end
  35.     db    '-'        ;blanks to the left.
  36.     dw    mark_lblanks
  37.     db    '+'        ;blanks to the right.
  38.     dw    mark_rblanks
  39.     db    '}'        ;word to the right of this one.
  40.     dw    mark_word_right
  41.     db    '{'        ;word to the left of this one.
  42.     dw    mark_word_left
  43.     db    '.'        ;point or anything else no in the list.
  44.     dw    mark_point
  45. mark_list_size    equ    ((offset $)-(offset mark_list))/3
  46.  
  47.  
  48. ;data    ends
  49.  
  50. code    cseg    byte public
  51.     ;*** assume    cs:code, ds:data, es:data
  52.  
  53.     public    set_mark
  54. set_mark:    
  55.     push ds ! mov ds,textseg
  56.     call set_mark?
  57.     pop ds ! ret
  58.  
  59.  
  60.     public    stack_marks
  61. stack_marks:
  62.     push ds ! mov ds,textseg
  63.     call stack_marks?
  64.     pop ds ! ret
  65.  
  66. ;code    ends
  67.  
  68. code    cseg    byte public
  69.     ;*** assume    cs:code, ds:bufseg, es:data
  70.  
  71.     public    init_marks
  72.     public    set_mark_si
  73.     public    get_mark
  74.     public    adjust_marks_del
  75.     public    adjust_marks_ins
  76.  
  77.  
  78. init_marks:
  79.     mov    temp_mark_base,1
  80.     mov    temp_mark_count,1
  81.     mov    perm_mark_count,1
  82.     mov    bx,offset marks_sp+2
  83.     mov    byte ptr [bx],0        ;initial stack frame is empty.
  84.     mov    marks_sp,bx
  85.     mov    mark_offset,0        ;init the only mark.
  86.     mov    split_mark,0        ;set the mark to the beginning.
  87.     ret
  88.  
  89.  
  90. user_mark:
  91. ;enter with al=mark.
  92. ;if user mark, exit with bx->proper marks array entry, nc.
  93. ;if sytem mark, exit with cy.
  94.     cmp    al,mark_first_perm    ;permanent user mark?
  95.     jb    user_mark_3
  96.     cmp    al,mark_last_perm
  97.     ja    user_mark_3
  98.     mov    bl,al
  99.     sub    bl,mark_first_perm
  100.     cmp    bl,perm_mark_count
  101.     jae    user_mark_1        ;too bit, can't be user mark.
  102.     jmps user_mark_2
  103. user_mark_3:
  104.     cmp    al,mark_first_temp
  105.     jb    user_mark_1
  106.     cmp    al,mark_last_temp
  107.     ja    user_mark_1
  108.     mov    bl,al
  109.     sub    bl,mark_first_temp
  110.     mov    bh,temp_mark_count    ;compute the number of temporary marks.
  111.     sub    bh,temp_mark_base
  112.     cmp    bl,bh
  113.     jae    user_mark_1        ;too big, can't be user mark.
  114.     add    bl,temp_mark_base
  115. user_mark_2:
  116.     add    bl,bl
  117.     mov    bh,0
  118.     lea    bx,mark_offset[bx]
  119.     ret                ;cy was cleared by previous operation
  120. user_mark_1:
  121.     cmp    al,mark_split        ;split is a settable mark.
  122.     jne    user_mark_4
  123.     mov    bx,offset split_mark
  124.     ret
  125. user_mark_4:
  126.     stc
  127.     ret
  128.  
  129.  
  130. stack_marks?:
  131. ;enter with ax>0=number of temporary marks to stack or
  132. ;  ax<0=number of permanent marks to create (temporary marks are destroyed) or
  133. ;  ax=0 to unstack.
  134. ;exit with cy if overflow/underflow.
  135.     cmp    ax,0
  136.     jg    stack_marks_1    ;stack
  137.     jl    stack_marks_4    ;create perms.
  138.     mov    bx,marks_sp
  139.     mov    al,[bx]        ;get the current frame size
  140.     or    al,al
  141.     je    stack_marks_2    ;nothing to unstack.
  142.     sub    temp_mark_count,al    ;reduce count by this frame size
  143.     dec    bx
  144.     mov    al,[bx]        ;get the previous frame size
  145.     sub    temp_mark_base,al
  146.     mov    marks_sp,bx
  147.     clc
  148.     ret
  149. stack_marks_4:
  150.     neg    ax
  151.     cmp    al,MAX_MARKS        ;stack overflow?
  152.     jae    stack_marks_2        ;  yes.
  153.     mov    temp_mark_base,al
  154.     mov    temp_mark_count,al
  155.     mov    perm_mark_count,al
  156.     mov    bx,offset marks_sp    ;find the new tos.
  157.     add    bx,ax
  158.     mov    byte ptr [bx],0        ;initial stack frame is empty.
  159.     mov    marks_sp,bx
  160.     mov    ax,'.'*256+mark_first_perm
  161.     mov    cl,perm_mark_count
  162.     mov    ch,0
  163.     jmps stack_marks_3
  164. stack_marks_1:
  165.     mov    ah,temp_mark_count    ;get number of marks.
  166.     add    ah,al            ;add desired number
  167.     cmp    ah,MAX_MARKS        ;stack overflow?
  168.     jae    stack_marks_2        ;  yes.
  169.     mov    bx,marks_sp
  170.     inc    bx            ;bump stack pointer
  171.     mov    [bx],al            ;save the frame size
  172.     mov    marks_sp,bx
  173.     mov    al,temp_mark_count
  174.     mov    temp_mark_base,al    ;new base is old max.
  175.     mov    temp_mark_count,ah    ;new max is old+count of new marks
  176. ;set all the new temp marks to the point.
  177.     sub    ah,al            ;ah=temp_mark_count-temp_mark_base
  178.     mov    cl,ah
  179.     mov    ch,0
  180.     mov    ax,'.'*256+mark_first_temp
  181. stack_marks_3:
  182.     push    ax
  183.     push    cx
  184.     call    set_mark?
  185.     pop    cx
  186.     pop    ax
  187.     inc    al
  188.     loop    stack_marks_3
  189.     clc
  190.     ret
  191. stack_marks_2:
  192.     stc
  193.     ret
  194.  
  195.  
  196. set_mark_si:
  197. ;enter with al=number of dest mark, si->text.
  198. ;note that system marks cannot be set.
  199.     call    user_mark
  200.     jc    set_mark_si_1    ;not a user mark.
  201.     cmp    si,topbot    ;is new mark above point?
  202.     jb    set_mark_si_2    ;no, make it relative to toptop
  203.     sub    si,bottop
  204.     add    si,topbot
  205.     sub    si,toptop
  206.     jmps set_mark_si_3
  207. set_mark_si_2:
  208.     sub    si,toptop
  209. set_mark_si_3:
  210.     mov    [bx],si
  211. set_mark_si_1:
  212.     ret
  213.  
  214.  
  215. set_mark?:
  216. ;enter with al=dest mark, ah=source mark.
  217.     push    ax
  218.     mov    al,ah
  219.     call    get_mark_count
  220.     pop    ax
  221.     call    user_mark
  222.     jc    set_mark_1
  223.     mov    [bx],cx        ;store the mark.
  224. set_mark_1:
  225.     ret
  226.  
  227.  
  228.     ;*** assume    es:nothing, ss:data
  229.  
  230. get_mark_count:
  231. ;enter with al=number of mark to get.
  232. ;exit with cx=number of characters before the mark.
  233.     call    user_mark
  234.     jc    get_mark_count_1    ;anything larger (or negative)
  235.     mov    cx,[bx]
  236.     ret
  237. get_mark_count_1:
  238.     mov    bx,offset mark_list-3    ;get the mark list.
  239.     mov    cx,mark_list_size
  240. get_mark_count_2:            ;scan the list for the mark.
  241.     add    bx,3            ;preincrement
  242.     cmp    al,ss:[bx]        ;is it this one?
  243.     loopne    get_mark_count_2    ;continue if not.
  244.     jmp    ss:word ptr 1[bx]    ;go to the correct mark.
  245.  
  246.  
  247. mark_right:
  248.     mov    cx,botbot    ;compute the number of characters after the
  249.     sub    cx,bottop    ;  point.
  250.     je    mark_bot    ;  return the mark at the end of the file.
  251.     mov    cx,topbot    ;compute the number of characters before the
  252.     sub    cx,toptop    ;  point.
  253.     inc    cx        ;because we want the character to the right.
  254.     mov    bx,bottop    ;check for breaking up a NEWLINE
  255.     cmp    word ptr [bx],LINENEW
  256.     jne    mark_right_1    ;not NEWLINE.
  257.     inc    cx        ;because we don't want to split a newline.
  258. mark_right_1:
  259.     ret
  260.  
  261.  
  262. mark_left:
  263.     mov    cx,topbot
  264.     sub    cx,toptop
  265.     jz    mark_left_1    ;if no characters, mark is at beginning of file.
  266.     dec    cx        ;because we want the character to the left.
  267.     mov    bx,topbot
  268.     cmp    word ptr 0fffeh[bx],LINENEW
  269.     jne    mark_left_1
  270.     dec    cx        ;because we don't want to split a newline.
  271. mark_left_1:
  272.     ret
  273.  
  274.  
  275. mark_top:
  276.     mov    cx,0        ;zero characters before beginning of file.
  277.     ret
  278.  
  279.  
  280. mark_bot:
  281.     mov    cx,topbot    ;size of text before point +
  282.     sub    cx,toptop
  283.     add    cx,botbot    ;size of text after point.
  284.     sub    cx,bottop
  285.     ret
  286.  
  287.  
  288. mark_point:
  289.     mov    cx,topbot    ;size of text before point.
  290.     sub    cx,toptop
  291.     ret
  292.  
  293.  
  294. mark_begin:
  295.     mov    cx,topbot
  296.     mov    bx,cx
  297.     sub    cx,toptop
  298. mark_begin_1:
  299.     cmp    word ptr 0fffeh[bx],LINENEW    ;at beginning?
  300.     je    mark_begin_2        ;yes.
  301.     dec    bx
  302.     dec    cx
  303.     jmp    mark_begin_1
  304. mark_begin_2:
  305.     ret
  306.  
  307.  
  308. mark_end:
  309.     mov    cx,topbot        ;start at point
  310.     sub    cx,toptop
  311.     mov    bx,bottop
  312. mark_end_1:
  313.     cmp    word ptr [bx],LINENEW    ;at end?
  314.     je    mark_end_2    ;yes.
  315.     inc    bx
  316.     inc    cx
  317.     jmp    mark_end_1
  318. mark_end_2:
  319.     ret
  320.  
  321.  
  322. mark_word_right:
  323.     mov    cx,topbot        ;start at point
  324.     sub    cx,toptop
  325.     mov    bx,bottop
  326. mark_word_right_1:
  327.     cmp    bx,botbot        ;end of buffer is end of word.
  328.     je    mark_word_right_2
  329.     mov    al,[bx]            ;is this character a blank?
  330.     call    get_syntax
  331.     test    al,1
  332.     je    mark_word_right_2    ;yes - we're done.
  333.     inc    bx
  334.     inc    cx
  335.     jmp    mark_word_right_1
  336. mark_word_right_2:
  337.     ret
  338.  
  339.  
  340. mark_word_left:
  341.     mov    cx,topbot        ;start at point
  342.     mov    bx,cx
  343.     sub    cx,toptop
  344.     jcxz    mark_word_left_1    ;if nothing to the left, leave.
  345.     dec    bx
  346. mark_word_left_2:
  347.     mov    al,[bx]            ;is this character a blank?
  348.     call    get_syntax
  349.     test    al,1
  350.     je    mark_word_left_1    ;yes - exit now.
  351.     dec    bx
  352.     dec    cx
  353.     jne    mark_word_left_2
  354. mark_word_left_1:
  355.     ret
  356.  
  357.  
  358. mark_lblanks:
  359.     mov    cx,topbot        ;start at point
  360.     mov    bx,cx
  361.     sub    cx,toptop
  362.     jcxz    mark_lblanks_1        ;if nothing to left, leave.
  363.     dec    bx
  364.     cmp    word ptr 0ffffh[bx],LINENEW    ;starting at newline?
  365.     jne    mark_lblanks_2        ;no.
  366.     sub    cx,2            ;yes - move back over it.
  367.     sub    bx,2
  368.     jcxz    mark_lblanks_1        ;if nothing more to left, leave.
  369. mark_lblanks_2:
  370.     mov    al,[bx]            ;is this char a blank?
  371.     call    get_syntax
  372.     test    al,3            ;non-blank or line break?
  373.     jne    mark_lblanks_1    ;yes - exit now.
  374.     dec    bx
  375.     dec    cx
  376.     jne    mark_lblanks_2
  377. mark_lblanks_1:
  378.     ret
  379.  
  380.  
  381. mark_rblanks:
  382.     mov    cx,topbot        ;start at point
  383.     sub    cx,toptop
  384.     mov    bx,bottop
  385.     cmp    word ptr [bx],LINENEW        ;starting at newline?
  386.     jne    mark_rblanks_1        ;no.
  387.     cmp    bx,botbot        ;starting at end of buffer?
  388.     je    mark_rblanks_2        ;yes - end.
  389.     add    bx,2            ;start by skipping the newline.
  390.     add    cx,2
  391. mark_rblanks_1:
  392.     cmp    bx,botbot        ;end of buffer is end of word.
  393.     je    mark_rblanks_2        ;yes - end.
  394.     mov    al,[bx]
  395.     call    get_syntax
  396.     test    al,3            ;non-blank or line break?
  397.     jne    mark_rblanks_2        ;yes - exit now.
  398.     inc    bx
  399.     inc    cx
  400.     jmp    mark_rblanks_1
  401. mark_rblanks_2:
  402.     ret
  403.  
  404.  
  405.     public    split_at_point
  406. split_at_point:
  407. ;return cy if the split mark is at or after the point.
  408.     mov    cx,split_mark
  409.     mov    ax,topbot
  410.     sub    ax,toptop
  411.     cmp    split_mark,ax        ;is the split mark at or after the point?
  412.     jae    split_at_point_1    ;yes - return cy.
  413.     clc
  414.     ret
  415. split_at_point_1:
  416.     stc
  417.     ret
  418.  
  419.  
  420.     public    get_split_mark
  421. get_split_mark:
  422. ;same as get_mark('*'), only faster.
  423.     mov    cx,split_mark
  424.     jmps compute_mark
  425. get_mark:
  426. ;enter with al=number of mark to get.
  427.     call    get_mark_count
  428. compute_mark:
  429. ;enter with cx=the number of characters before the point.
  430. ;exit with cx=count of chars between the mark and the point, si->text at mark,
  431. ;cy=1 if mark is after the point.
  432.     mov    si,topbot
  433.     sub    si,toptop
  434.     sub    cx,si
  435.     jb    compute_mark_1
  436.     mov    si,bottop    ;make si->bottom
  437.     add    si,cx        ;make si->text.
  438.     stc
  439.     ret
  440. compute_mark_1:
  441.     mov    si,topbot    ;Compute pointer to text.
  442.     add    si,cx        ;  cx is difference between topbot and mark,
  443.     neg    cx        ;  which is negative.  make it positive.
  444.     clc
  445.     ret
  446.  
  447.  
  448.     ;*** assume    es:data
  449.  
  450.  
  451. adjust_marks_ins:
  452. ;enter with ax=number of characters inserted
  453. ;exit with all marks adjusted accordingly.
  454. ;if a mark is at or after the point, move it up or down.
  455. ;if a mark is before the point, leave it alone.
  456.     mov    cl,temp_mark_count
  457.     mov    ch,0
  458.     inc    cx
  459.     mov    bx,offset mark_offset-2
  460.     mov    dx,topbot
  461.     sub    dx,toptop
  462. adjust_marks_ins_1:
  463.     mov    si,[bx]            ;get a mark
  464.     cmp    si,dx            ;is it before the point?
  465.     jb    adjust_marks_ins_2    ;yes.
  466. adjust_marks_ins_3:
  467.     add    si,ax            ;no - adjust it and store it back.
  468.     mov    [bx],si
  469. adjust_marks_ins_2:
  470.     add    bx,2            ;go to the next mark.
  471.     loop    adjust_marks_ins_1
  472.     ret
  473.  
  474.  
  475. adjust_marks_del:
  476. ;enter with ax=number of characters deleted.
  477. ;exit with all marks adjusted accordingly.
  478. ;if a mark is after the point, move it up or down.
  479. ;if a mark is at or before the point, leave it alone.
  480. ;Adjusting for deletion is more complex than adjusting for insertion,
  481. ;  because we have to adjust all the marks that fall in the range of
  482. ;  the characters deleted.
  483.     mov    cl,temp_mark_count
  484.     mov    ch,0
  485.     inc    cx
  486.     mov    bx,offset mark_offset-2
  487.     mov    dx,topbot
  488.     sub    dx,toptop        ;make dx -> before first mark to adjust
  489.     mov    di,dx
  490.     add    di,ax            ;make di -> last mark to adjust.
  491. adjust_marks_del_1:
  492.     mov    si,[bx]            ;get a mark
  493.     cmp    si,dx            ;is it at or before the point?
  494.     jbe    adjust_marks_del_2    ;yes.
  495.     cmp    si,di            ;does it mark a deleted character?
  496.     ja    adjust_marks_del_3    ;no - adjust it down.
  497.     mov    [bx],dx            ;all deleted marks will mark the point.
  498.     jmps adjust_marks_del_2
  499. adjust_marks_del_3:
  500.     sub    si,ax            ;no - adjust it and store it back.
  501.     mov    [bx],si
  502. adjust_marks_del_2:
  503.     add    bx,2            ;go to the next mark.
  504.     loop    adjust_marks_del_1
  505.     ret
  506.  
  507.     ;*** assume    es:nothing
  508.  
  509.     public    get_syntax
  510. get_syntax:
  511. ;enter with al=character.
  512. ;don't change any other registers.
  513. ;exit with al=syntax of that character.
  514.     push    bx
  515.     mov    bx,ss:syntax_table
  516.     cmp    bx,NIL
  517.     je    get_syntax_3
  518.     push    ax
  519.     mov    ax,ss:name_length[bx]
  520.     lea    bx,size_form[bx]    ;make bx->name.
  521.     add    bx,ax            ;make bx->data.
  522.     pop    ax
  523.     xlat    ss:byte ptr .0
  524.     pop    bx
  525.     ret
  526. get_syntax_3:
  527.     pop    bx
  528.     cmp    al,'_'
  529.     je    get_syntax_1
  530.     cmp    al,cr
  531.     je    get_syntax_2
  532.     cmp    al,lf
  533.     je    get_syntax_2
  534.     cmp    al,'0'
  535.     jb    get_syntax_0
  536.     cmp    al,'9'
  537.     jbe    get_syntax_1
  538.     cmp    al,'A'
  539.     jb    get_syntax_0
  540.     cmp    al,'Z'
  541.     jbe    get_syntax_1
  542.     cmp    al,'a'
  543.     jb    get_syntax_0
  544.     cmp    al,'z'
  545.     jbe    get_syntax_1
  546. get_syntax_0:
  547.     mov    al,0
  548.     ret
  549. get_syntax_1:
  550.     mov    al,1
  551.     ret
  552. get_syntax_2:
  553.     mov    al,2
  554.     ret
  555.  
  556. ;code    ends
  557.  
  558.     end
  559.  
  560.