home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / FREEMACS / EMAC16AS.ZIP / MARKS.ASM < prev    next >
Assembly Source File  |  1989-12-19  |  14KB  |  622 lines

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