INTERFACEMTextRd ; IMPORT Rd, MText, Thread; TYPE T <: Public; Public = Rd.T OBJECT METHODS init (m : MText.T := NIL; start : CARDINAL := 0; rangeStart: CARDINAL := 0; rangeEnd : CARDINAL := LAST (CARDINAL); reverse : BOOLEAN := FALSE ): T RAISES {Rd.Failure, Thread.Alerted} END;
rd.init(m, ...) initializes a seekable, non-intermittent reader for the
   MText m.
   It is intended that this method be called more than once, to re-initialize
   a reader (and avoid re-allocating storage for rd.buff); in this case, it
   is permitted for m to be NIL, and the default value is the MText that
   was previously used by the reader.
   The reader's source may be a proper subsequence of the underlying MText,
   and the reader can be initialized to read in reverse order.
   src(rd) comprises the characters of m that are contained in the
   interval
       [first(rd) .. last(rd)]
   
where
       first(rd)) = rangeStart
   
and
       last(rd) = MIN (rangeEnd, MText.Length(m)) - 1]
       len(rd) = MAX (last(rd) - first(rd) + 1, 0)
   In a forward reader (reverse = FALSE), Rd.GetChar delivers characters
   from start to last(rd).  Rd.Index returns the index relative to
   first(rd).  Hence just after a forward reader rd is initialized,
       cur(rd) = start - first(rd)
   In a reverse reader, Rd.GetChar delivers characters from start-1 (not
   start) to first(rd).  Rd.Index returns the index relative to
   last(rd)+1.  Hence just after a reverse reader rd is initialized,
       cur(rd) = last(rd) + 1 - start
   Thus the value returned by Rd.Index increases by 1 with each call to
   Rd.GetChar, regardless of the reader's direction.
   The coordinate system used by Rd.Seek is consistent with Rd.Index.
   If the underlying MText is modified, the reader is invalid and should be
   re-initialized.
   rd.init calls Rd.Seek(rd, rd.cur), which can raise Rd.Failure or
   Thread.Alerted.
Synchronization: it is not possible to have several readers reading the mtext concurrently. The reason is that a read to a file node causes the mtext data structure to change. If you don't use file nodes, then it's safe. (JRM doesn't believe this.)
PROCEDURE New (m         : MText.T;
               start     : CARDINAL  := 0;
               rangeStart: CARDINAL  := 0;
               rangeEnd  : CARDINAL  := LAST (CARDINAL);
               reverse   : BOOLEAN   := FALSE            ): T
  RAISES {Rd.Failure, Thread.Alerted};
 This is equivalent to
      NEW (T).init (m, start, rangeStart, rangeEnd, reverse, alertable)
END MTextRd.