home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol164 / mkv86.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  18.6 KB  |  637 lines

  1.  
  2. ;    =======================================================
  3. ;
  4. ;
  5. ;    Module composed of workspace operators for REC/MARKOV.
  6. ;    These are specialized subroutines for manipulating a
  7. ;    "workspace,"  which is an array together with five
  8. ;    pointers.  The workspace will probably (but not always)
  9. ;    hold text, subdivisions of which are marked off by the
  10. ;    pointers.  They in turn are:
  11. ;
  12. ;        p0  the beginning of both space and text
  13. ;        p1  the beginning of a specific segment
  14. ;        p2  the end of a specific segment
  15. ;        p3  the end of the entire text
  16. ;        p4  the physical end of the available space
  17. ;
  18. ;    The uniform method to designate intervals is that the
  19. ;    beginning is inclusive, while the end is exclusive.  In
  20. ;    that way a null interval can be represented through two
  21. ;    equal pointers.  The workspace operators and predicates
  22. ;    move data around and compare it with the help of these
  23. ;    pointers.  Other operators move data between the work-
  24. ;    space and the pushdown list.
  25. ;
  26. ;    The complete list of operators and predicates is:
  27. ;
  28. ;        A    advance pointer 1 if possible
  29. ;        B    retract pointer 1 if possible
  30. ;        D    delete interval between p1 and p2
  31. ;        E    test equality between workspace and PDL
  32. ;        F    find a specified segment in the workspace
  33. ;        I    insert in the workspacve following p2
  34. ;        J    move p1 to beginning
  35. ;        M    test workspace for lexicographically larger
  36. ;        Q    move interval between p1 and p2 to PDL
  37. ;        U    find segment between delimiters
  38. ;        V    find segment including delimiters
  39. ;        Y   restore pointer 1 to previous value
  40. ;        Z    move p2 to end
  41. ;        a    extend interval from p1 if possible
  42. ;        b    extend interval to p2 if possiblle
  43. ;        e    extend limit of text if possible
  44. ;        f    fill if space is available
  45. ;        h    fetch workspace header for PDL
  46. ;        j    null interval at front of segment
  47. ;        q    place p1, p2-p1 on PDL
  48. ;        w    store (or possibly exchange) workspace header
  49. ;        z    null interval at end of segment
  50. ;        <    restrict workspace to segment p1-p2
  51. ;        >    open workspace to previous span
  52. ;
  53. ;    Version released during the Summer School, 1980.
  54. ;
  55. ;          MKV86 - Copyright (C) 1980
  56. ;        Universidad Autonoma de Puebla
  57. ;             All Rights Reserved
  58. ;
  59. ;         [Harold V. McIntosh, 25 April 1982]
  60. ;
  61. ;    May 1, 1982 - M tests for an interval rather than making
  62. ;        a simple comparison.  <a,'',M> should be used
  63. ;        where <a,M> was formerly written.  In general,
  64. ;        <a,b,M> tests for a .LE. WS .LE. b and leaves
  65. ;        P1 and P2 surrounding such a segment.  Both a
  66. ;        and b are always lifted.
  67. ;    May 29, 1983 - h discontinued; use ''w instead
  68. ;    =======================================================
  69.  
  70. ;    =======================================================
  71. ;    Workspace subroutines for REC/MARKOV.
  72. ;    =======================================================
  73.  
  74. ;    (a)  Generate a segment of length n forward from p1 if
  75. ;    possible.  A predicate which, when FALSE, leaves the
  76. ;    deficit by which the segment could not be formed on the
  77. ;    pushdown list.
  78.  
  79. LCA:    call    CXLD        ;load n into (cx)
  80.     add    cx,P1
  81.     cmp    P3,cx
  82.     jc    LAF
  83.     sto    cx,P2
  84.     jmp    SKP        ;return with the value TRUE
  85. LAF:    sub    cx,P3
  86.     push    cx        ;argument to putw must be on 8080 stack
  87.     call    PUTW        ;record deficit
  88.     ret            ;FALSE return: <jmp putw> won't do
  89.  
  90. ;    (A)  Pointer 1 advances by one byte, if possible.
  91.  
  92. UCA:    ld    ax,P1        ;fetch pointer 1
  93.     inc    ax        ;advance by 1
  94.     cmp    P3,ax
  95.     jc    UAF        ;forget it, return FALSE if past limit
  96.     sto    ax,P1        ;we can safely store pointer 1
  97.     cmp    P2,ax        ;but it still must not pass pointer 2
  98.     jnc    UA2        ;but it still must not pass pointer 2
  99.     sto    ax,P2        ;if it did, pointer 2 = pointer 1
  100. UA2:    jmp    SKP        ;but in either event, return TRUE
  101. UAF:    ret
  102.  
  103. ;    (b)  Generate a segment of length n backward from p2,
  104. ;    if possible.
  105.  
  106. LCB:    call    CXLD        ;load top argument into (cx), erase it
  107.     ld    ax,P2        ;fetch pointer 2 into (HL)
  108.     sub    ax,cx        ;calculate difference
  109.     cmp    ax,P0
  110.     jc    LBF        ;low limit passed, abandon the attempt
  111.     sto    ax,P1        ;record it
  112.     jmp    SKP        ;generate TRUE return for the predicate
  113. LBF:    ret
  114.  
  115. ;    (B)  Pointer 1 retreats by one byte, if possible.
  116.  
  117. UCB:    ld    ax,P1        ;fetch pointer
  118.     dec    ax        ;move backwards one byte
  119.     cmp    ax,P0        ;
  120.     jc    UBF
  121.     sto    ax,P1        ;otherwise store new position
  122.     jmp    SKP        ;and return with value TRUE
  123. UBF:    ret            ;return false as NOP if passed
  124.  
  125. ;    (D) Delete text between pointers 1 and 2.
  126.  
  127. UCD:    ld    si,P2        ;fetch end of deleted text
  128.     ld    di,P1        ;fetch beginning of deleted text
  129.     cmp    si,di
  130.     jz    UD2        ;null interval to delete
  131.     sto    di,P2        ;after deletion, interval is null
  132.     ld    cx,P3
  133.     sub    cx,si        ;length of string to move
  134.     jz    UD1
  135.     cld
  136.     mov    ax,ds
  137.     mov    es,ax
  138.     rep
  139.     movsb
  140. UD1:    sto    di,P3        ;destination limit is new end of text
  141. UD2:    ret
  142.  
  143. ;    (e)  Attempt to move pointer 3 forward. If insufficient
  144. ;    space remains, this predicate is false and places the
  145. ;    amount of remaining space [p4-p3] on the pushdown list.
  146. ;    If the extension is possible, P1 and P2 will surround it.
  147.  
  148. LCE:    call    CXLD        ;load argument into (cx), pop it
  149.     add    cx,P3
  150.     cmp    P4,cx
  151.     jc    LEF        ;skip if increment not greater
  152.     ld    ax,P3
  153.     sto    cx,P2
  154.     sto    cx,P3
  155.     sto    ax,P1        ;make it the beginning of new interval
  156.     jmp    SKP        ;TRUE return
  157. LEF:    sub    cx,P4
  158.     push    cx        ;putw requires argument on 8080 stack
  159.     call    PUTW        ;insert balance on pushdown list
  160.     ret            ;TRUE return: <jmp putw> won't work
  161.  
  162. ;    (E) Check equality between the pushdown list and the
  163. ;    workspace.  The top argument will be erased whatever
  164. ;    the outcome of the test, a characteristic common to
  165. ;    E, F, M, U, and V.  If there is a segment originating
  166. ;    at p1 which is equal to the argument, p2 will move to
  167. ;    delimit it, otherwise p2 remains unchanged.
  168.  
  169. UCE:    ld    cx,PY        ;end of top argument
  170.     ld    si,PX        ;beginning of top argument
  171.     ld    di,P1        ;beginning of workspace segment in (HL)
  172.     sub    cx,si
  173.     jcxz    UEN        ;''E is TRUE, sets P2=P1
  174.     cld
  175.     mov    ax,ds
  176.     mov    es,ax
  177.     repz
  178.     cmpsb
  179.     jnz    UEF        ;mismatch terminated scan
  180.     cmp    P3,di        ;see whether we've run over
  181.     jc    UEF
  182. UEN:    sto    di,P2
  183.     jmp    CUCL        ;skip for TRUE
  184. UEF:    jmp    UCL        ;FALSE for one reason or another
  185.  
  186. ;    (f)  Fill. <'XXX' f> will replace the text following
  187. ;    pointer 1 by XXX if pointer 2 does not conflict,
  188. ;    whereupon pointers 1 and 2 delimit what remains of
  189. ;    the interval they originally encompassed, making this
  190. ;    predicate TRUE.  Otherwise it will be FALSE, with the
  191. ;    pointers unaltered.  When f fails, its argument is
  192. ;    erased, otherwise the insert is conserved for repeated
  193. ;    use in a block fill.  f is true even if its argument
  194. ;    completely fills the available space, since it reports
  195. ;    whether or not an insertion took place rather than
  196. ;    whether any space remains.
  197.  
  198. LCF:    ld    si,PX
  199.     ld    cx,PY
  200.     sub    cx,si
  201.     ld    di,P1        ;load p2
  202.     ld    dx,P2        ;now load p1
  203.     sub    dx,di
  204.     cmp    dx,cx        ;compare this to p2
  205.     jnc    LFT
  206.     jmp    UCL        ;insert too big, FALSE and erase insert
  207. LFT:    cld
  208.     mov    ax,ds
  209.     mov    es,ax
  210.     rep
  211.     movsb
  212.     sto    di,P1        ;final destination location is new p1
  213.     jmp    SKP        ;keep insert, generate TRUE return
  214.  
  215. ;    (F)  Search for text.  The text in the workspace is
  216. ;    examined from left to right beginning at pointer 1 to
  217. ;    see if the object of comparison on the pushdown list
  218. ;    can be found.  If so, its replica in the workspace is
  219. ;    bracketed by pointers 1 and 2, while the model itself
  220. ;    is discarded.  Even if no replica is found, the model
  221. ;    is still discarded, but then the value is FALSE and the
  222. ;    pointers 1 and 2 retain their original sites.  Should
  223. ;    several replicas exist, only the first is taken; if
  224. ;    consecutive searches for the same object are made, the
  225. ;    same replica will be found repeatedly.  This permits
  226. ;    nested fragments of the same object to be found on
  227. ;    successive searches, but requires an intermediate
  228. ;    collapse of the interval p1-p2 in favor of p2 [say by
  229. ;    using ''I] to scan multiple occurrences of the same
  230. ;    object.
  231.  
  232. UCF:    ld    dx,PY
  233.     ld    bx,PX
  234.     ld    di,P1
  235.     sub    dx,bx        ;length of comparison object
  236.     jz    UFX        ;fast exit for null object
  237.     ld    cx,P3
  238.     sub    cx,di        ;length of search field
  239.     cmp    cx,dx
  240.     jc    UFF        ;useless to even try
  241.     cld            ;searches go forward
  242.     mov    ax,ds
  243.     mov    es,ax        ;CP/M might derange ES
  244.     dec    dx
  245.     jz    UFS        ;look for single byte
  246. UF1:    mov    si,bx
  247.     lodsb
  248.     repnz            ;search by increment until limit
  249.     scasb
  250.     jnz    UFF        ;end without even 1st word
  251.     cmp    cx,dx        ;are there enough chars left
  252.     jc    UFF        ;can't possibly fit it in
  253.     push    cx
  254.     push    di
  255.     mov    cx,dx
  256.     repz
  257.     cmpsb
  258.     jz    UFT
  259.     pop    di        ;comparison failed
  260.     pop    cx
  261.     jmp    UF1        ;go on where we left off
  262. UFT:    pop    ax        ;comparison accomplished
  263.     pop    cx
  264. UFV:    dec    ax
  265.     sto    ax,P1
  266. UFX:    sto    di,p2
  267.     jmp    CUCL
  268. UFS:    ld    al,[bx]
  269.     repnz
  270.     scasb
  271.     jnz    UFF
  272.     mov    ax,di
  273.     jmp    UFV
  274. UFF:    jmp    UCL
  275.  
  276. ;    (I)  Insert text following pointer 2; upon completion
  277. ;    pointers bracket inserted material.  If the proposed
  278. ;    insertion will not fit, an error indicator is generated
  279. ;    and the attempt is abandoned.  An F followed by an I
  280. ;    will insert material after the found text, but if an
  281. ;    intermediate ''F is given, insertion will be made at
  282. ;    the front of the text.  A ''I may be used to form null
  283. ;    intervals, if they are desired at the end of a segment.
  284.  
  285. UCI:    ld    ax,P2        ;point where insertion will be made
  286.     sto    ax,P1        ;pointer 1 to precede inserted material
  287.     ld    dx,PY        ;source origin
  288.     sub    dx,PX        ;source end
  289.     jz    UIN        ;null insert
  290.     ld    si,P3
  291.     ld    cx,P4
  292.     sub    cx,si
  293.     cmp    cx,dx
  294.     jc    UIE        ;insufficient space for insert
  295.     mov    cx,si
  296.     sub    cx,P2
  297.     add    P2,dx
  298.     add    P3,dx
  299.     mov    ax,ds
  300.     mov    es,ax
  301.     jcxz    UIA
  302.     ld    di,P3
  303.     dec    si
  304.     dec    di
  305.     std
  306.     rep
  307.     movsb
  308. UIA:    mov    cx,dx
  309.     ld    si,PX        ;source origin into (DE)
  310.     ld    di,P1        ;new p1 is destination origin, in (HL)
  311.     cld
  312.     rep
  313.     movsb
  314. UIN:    jmp    UCL        ;I removes its argument upon completion
  315. UIE:    call    RER
  316.  
  317. ;    (j)  Null interval at p1.  Equivalent to ''F or ''E.
  318.  
  319. LCJ:    ld    ax,P1        ;pointer to beginning of interval
  320.     sto    ax,P2        ;make end of interval the same
  321.     ret
  322.  
  323. ;    (J) Back to beginning of workspace.  Extends whatsoever
  324. ;     interval back to the beginning of the entire text.
  325.  
  326. UCJ:    ld    ax,P0        ;fetch pointer to beginning of text
  327.     sto    ax,P1        ;make it the beginning of the interval
  328.     ret
  329.  
  330. ;    (M)  Compare inequality between the pushdown list and
  331. ;    the workspace.  M is TRUE if there is a segment in the
  332. ;    workspace beginning at p1 which is lexicographically
  333. ;    larger than the argument on the pushdown list.  In that
  334. ;    event, p2 marks the "larger" interval, which terminates
  335. ;    after the first byte in the workspace which is larger -
  336. ;    by unsigned integer comparison - than the argument.  M
  337. ;    is also TRUE if an equal segment lies in the workspace.
  338. ;    According to the common style of E, F, I, M, U, and V,
  339. ;    the argument is erased whatever might be the outcome of
  340. ;    the comparison.  Likewise, FALSE results in no pointer
  341. ;    changes.
  342.  
  343. UCM:    ld    cx,PY
  344.     ld    si,PX
  345.     sub    cx,si
  346.     push    cx
  347.     push    si
  348.     call    UCL
  349.     ld    cx,PY        ;pointer to argument to be compared
  350.     ld    si,PX        ;pointer to workspace under comparison
  351.     sub    cx,si
  352.     call    UCL
  353.     ld    bp,P1
  354.     jcxz    UMT        ;trivial comparison to be made
  355.     cld
  356.     mov    ax,ds
  357.     mov    es,ax
  358.     mov    di,bp
  359. UML:    cmpsb            ;(SI) - (DI) sets flags
  360.     jc    UMM        ;decided if WS > PD
  361.     jnz    UMF        ;failure if WS < PD
  362.     loop    UML        ;repeat for WS = PD
  363. UMM:    xchg    di,bp
  364.     cmp    P3,bp
  365.     jc    UMF        ;fail if we run over
  366.     pop    si
  367.     pop    cx
  368.     jcxz    UMT        ;treat '' as 'no comparison'
  369.     mov    ax,cx
  370.     mov    cx,bp
  371.     sub    cx,di
  372.     cmp    ax,cx        ;set flags by l(PD) - l(WS)
  373.     sbb    dx,dx        ;(nc) when l(WS) .LE. l(PD)
  374.     jz    UMN        ;(z): workspace is shorter, equal
  375.     xchg    ax,cx        ;check only common segment
  376. UMN:    cmpsb            ;set flags from PD - WS
  377.     jc    UMG        ;WS > PD means outside inclusive bound
  378.     jnz    UMT        ;WS < PD means bound is satisfied
  379.     loop    UMN        ;WS = PD means keep testing
  380.     or    dx,dx
  381.     jnz    UMG        ;(z): workspace fulfils 'short before long'
  382. UMT:    sto    bp,P2
  383.     jmp    SKP
  384. UMF:    add    sp,#4
  385. UMG:    ret
  386.  
  387. ;    (q)  Put p1, p2-p1 on PDL.
  388.  
  389. LCQ:    ld    ax,P2
  390.     sub    ax,P1
  391.     push    ax        ;stash P2-P1 on 8086's PDK
  392.     push    P1        ;and then P1 on top of that
  393.     call    PUTW        ;one argument from top of 8080 stack
  394.     call    PUTW        ;then another so we've got both
  395.     ret            ;cannot use jmp putw for call putw, ret
  396.  
  397. ;    (Q)  Copy workspace to pushdown.  The interval between
  398. ;    p1 and p2 is placed on the pushdown list.
  399.  
  400. UCQ:    ld    si,P1        ;fetch beginning of interval
  401.     ld    cx,P2        ;fetch end of interval
  402.     sub    cx,si        ;length of interval into (cx)
  403.     call    NARG        ;close old arg, check space, def new
  404.     ld    di,PX        ;fetch destination origin for (HL)
  405.     cld
  406.     mov    ax,ds
  407.     mov    es,ax
  408.     rep
  409.     movsb
  410.     sto    di,PY        ;destination end is argument end
  411.     ret
  412.  
  413. ;    (w)  Store workspace header.  There are two forms of
  414. ;    this operator which are available: the argument may be
  415. ;    either a single block of ten bytes, or else the pair
  416. ;    <org, siz>.  The distinction is implicit, according to
  417. ;    whether the top argument has two bytes or ten bytes.
  418. ;    The first case arises from a previous usage of h (or
  419. ;    perhaps deliberate construction), while the second is
  420. ;    more likely in the initial allocation of a workspace. A
  421. ;    single block is erased after use, while it is supposed
  422. ;    that a previous definition existed when the pair form
  423. ;    is used.  In such a case, the old block of bytes would
  424. ;    be substituted for the two arguments in case it needed
  425. ;    to be restored later.  When a workspace is generated
  426. ;    from its specifications, pointers 1 and 2 as well as 3
  427. ;    are set to encompass the entire space. Many other forms
  428. ;    can be arranged by a subsequent use of j, D, and so on.
  429.  
  430. LCW:    ld    si,PX
  431.     ld    cx,PY
  432.     sub    cx,si        ;determine size of argument
  433.     cmp    cx,#10        ;ten for comparison
  434.     jnz    LWW        ;if length not 10, suppose it was 2
  435.     cmp    cx,#0
  436.     jnz    LWX
  437.     call    UCL
  438. LWH:    ld    cx,#10        ;10 bytes required from PDL
  439.     call    NARG        ;verify space, new px into (HL)
  440.     ld    si,#P0        ;source is pointer block itself
  441.     cld
  442.     mov    di,bx
  443.     mov    ax,ds
  444.     mov    es,ax
  445.     rep
  446.     movsb
  447.     sto    di,PY        ;final destination is arg end
  448.     ret
  449. LWX:    ld    di,#P0        ;p0 is destination origin
  450.     cld
  451.     mov    ax,ds
  452.     mov    es,ax
  453.     rep
  454.     movsb
  455.     jmp    UCL        ;erase the argument
  456. LWW:    ld    bx,PX        ;create p0...p4 from org,siz
  457.     call    TWOL        ;trnsfr two args from PDL to 8080 stack
  458.     call    LWH        ;place existing header on PDL
  459.     pop    bx        ;recover under arg, namely org
  460.     pop    cx        ;recover upper arg, namely siz
  461.     sto    bx,P0        ;origin of workspace
  462.     sto    bx,P1        ;segment at front of workspace
  463.     add    bx,cx        ;add size
  464.     sto    bx,P2        ;segment traverses whole workspace
  465.     sto    bx,P3        ;which defines end of occupied text
  466.     sto    bx,P4        ;as well as physical end
  467.     ret
  468.  
  469. ;    (U)  Search for interval, excluding limits.  The object
  470. ;    of the search is defined by its delimiters: thus if the
  471. ;    text YYY is to be found, it must be specified as the
  472. ;    one sandwiched between XXX and ZZZ.  Then by executing
  473. ;    'XXX'F followed by 'ZZZ'U pointers 1 and 2 will bracket
  474. ;    YYY.  U erases its argument, whether TRUE or FALSE, by
  475. ;    a custom common to all search or comparison predicates.
  476. ;    By the same custom, pointers 1 and 2 remain unmoved if
  477. ;    the search fails. ''U generates a null interval at the
  478. ;    end of the last interval that was created.
  479.  
  480. UCU:    push    P1        ;fetch beginning of last interval
  481.     ld    ax,P2        ;fetch end of last interval
  482.     sto    ax,P1        ;search begins at end of p1-p2 interval
  483.     push    ax
  484.     call    UCF        ;use the search subroutine
  485.     jmp    UUF        ;search failed [MUST be 3-byte jmp] <===
  486.     ld    ax,P1        ;beginning of found interval
  487.     sto    ax,P2        ;is end of result interval
  488.     pop    P1        ;recover end of last interval
  489.     pop    ax        ;discard beginning of last interval
  490.     jmp    SKP        ;TRUE return from predicate
  491. UUF:    pop    ax        ;discard end of last interval-it's same
  492.     pop    P1        ;recover beginning of last interval
  493.     ret            ;FALSE return from predicate
  494.  
  495. ;    (V)  Search for interval, including limits.  This
  496. ;    predicate is similar to U, the difference being that
  497. ;    after a successful search, p1 and p2 bracket both the
  498. ;    delimiters as well as the text which they define,
  499. ;    whereas U merely brackets the intervening text.
  500.  
  501. UCV:    push    P1        ;pointer to beginning of last interval
  502.     ld    ax,P2
  503.     sto    ax,P1        ;pointer to end of last interval
  504.     call    UCF        ;predicate F always makes the search
  505.     jmp    UVF        ;search failed, F was FALSE
  506.     pop    P1        ;recover the old p1
  507.     jmp    SKP        ;TRUE return with old p1, new p2
  508. UVF:    pop    P1        ;recover original p1
  509.     ret            ;FALSE return with p1 and p2 unchanged
  510.  
  511. ;    (Y)  Recover pointer 1.  There are those times when it
  512. ;    is desirable to note a spot in the workspace, through
  513. ;    qL for example, and then be able to return to it later
  514. ;    on.  However intervening deletions, insertions or even
  515. ;    workspace openings and closings may have rendered it
  516. ;    invalid so a check is made to ensure the preservation
  517. ;    of the relative order of p0, p1, and p3.  If p2 lies
  518. ;    in an acceptable range, it is untouched; otherwise it
  519. ;    is set to define a null interval at p1.
  520.  
  521. UCY:    ld    bx,PX
  522.     ld    cx,PY
  523.     sub    cx,bx
  524.     cmp    cx,#4
  525.     jz    UYI
  526.     ld    bx,[bx]        ;fetch low byte of pointer
  527.     cmp    bx,P0        ;check that p1 will be greater or equal
  528.     jnc    UYM        ;if less, store p0 instead
  529.     ld    bx,P0
  530.     jmp    UYZ
  531. UYM:    cmp    P3,bx        ;check that p1 will be less or equal
  532.     jnc    UYN        ;if not, make p2 = p1 = p3
  533.     ld    bx,P3
  534.     jmp    UYY
  535. UYN:    cmp    P2,bx        ;check that p1 less or equal to p2
  536.     jnc    UYZ
  537. UYY:    sto    bx,P2        ;record null interval between p1 and p2
  538. UYZ:    sto    bx,P1        ;give p1 whatever value it'll have
  539.     jmp    CUCL        ;pop the argument
  540. UYI:    ld    cx,[bx]
  541.     ld    bx,[bx+2]
  542.     cmp    cx,P0
  543.     jc    UYF
  544.     add    bx,cx
  545.     cmp    P3,bx
  546.     jc    UYF
  547.     sto    cx,P1
  548.     sto    bx,P2
  549.     jmp    CUCL
  550. UYF:    jmp    UCL
  551.  
  552. ;    (z)  Null interval at end of segment.  Equivalent to
  553. ;    ''I, ''U, or 0b.
  554.  
  555. LCZ:    ld    ax,P2        ;pointer to end of interval
  556.     sto    ax,P1        ;make beginning of interval the same
  557.     ret
  558.  
  559. ;    (Z)  Move p2 to the end of the workspace, thereby
  560. ;    extending whatever interval on to the end of the text.
  561.  
  562. UCZ:    ld    ax,P3        ;pointer to the end of text
  563.     sto    ax,P2        ;make end of interval the same
  564.     ret
  565.  
  566. ;    (<)  Close down workspace. The workspace is confined to
  567. ;    the interval between pointers 1 and 2.  The reason for
  568. ;    this could be to restrict the editing operations to a
  569. ;    smaller range, or it could be to have absolute freedom
  570. ;    to work over some material before incorporating it into
  571. ;    the main text.  As a practical matter, the text between
  572. ;    pointers 2 and 3 is displaced to the far end of the
  573. ;    workspace and the original values of pointers 0 and 4
  574. ;    are recorded before setting up the new values of the
  575. ;    pointers. Subsequent insertions and deletions then have
  576. ;    much less material to move.
  577.  
  578. BRA:    ld    di,P4
  579.     ld    si,P3
  580.     mov    cx,di
  581.     sub    cx,si
  582.     sub    cx,#4
  583.     jc    BRE
  584.     mov    cx,si
  585.     sub    cx,P2
  586.     dec    di
  587.     dec    si
  588.     std
  589.     mov    ax,ds
  590.     mov    es,ax
  591.     rep
  592.     movsb
  593.     dec    di
  594.     ld    ax,P4
  595.     stos
  596.     sto    di,P4
  597.     ld    ax,P0
  598.     stos
  599.     ld    ax,P2
  600.     sto    ax,P3
  601.     ld    ax,P1
  602.     sto    ax,P0        ;store it as new beginning of text
  603.     ret            ;p2 remains at end of newly made text
  604. BRE:    call    RER
  605.  
  606. ;    (>)  Open up the workspace.  This is the complementary
  607. ;    operator to <, which is used to return the scope of the
  608. ;    pointers p0 and p4 to their original range.  The text
  609. ;    forming the restricted workspace is incorporated in its
  610. ;    entirity in place of the material originally lying in
  611. ;    the interval p1-p2.  An error condition can arise from
  612. ;    opening a workspace that was never closed, but it will
  613. ;    be anulled if a zero address was placed at the pointer
  614. ;    4 during initialization of the workspace.
  615.  
  616. KET:    ld    bx,P4        ;load the end of the universe
  617.     ld    cx,[bx]
  618.     jcxz    KEE        ;zero means opening too many times
  619.     sto    cx,P0        ;restore it
  620.     ld    cx,[bx+2]
  621.     sto    cx,P4
  622.     add    bx,#4
  623.     sub    cx,bx
  624.     mov    si,bx
  625.     ld    di,P3        ;end of txt is dest to replace old tail
  626.     cld
  627.     mov    ax,ds
  628.     mov    es,ax
  629.     rep
  630.     movsb
  631.     sto    di,P3        ;destination end is new end of text
  632.     ret
  633. KEE:    call    RER        ;note error and abandon attempt
  634.  
  635.     LINK    FXT86.ASM
  636.  
  637.