<> <> <> <> <<>> <> <> <> <<>> DIRECTORY CD USING [Design, Number, ObPtr, Rect], Rope USING [ROPE]; PWStretch: CEDAR DEFINITIONS = BEGIN <<>> <<-- Data structures>> <<>> <<-- Easi!>> ROPE: TYPE = Rope.ROPE; <<-- PosRange describe the projection of some rectangles on an edge. Attention, contrary to what Christian does to rectangles, min is included and max excluded. It is an unchecked error to create a PosRange with min>=max.>> PosRange: TYPE = RECORD [min, max: CD.Number]; <<-- Segment is PosRange plus additionnal information>> Segment: TYPE = REF SegmentRec; SegmentRec: TYPE = RECORD [ pos: PosRange, info: REF ANY _ NIL -- All other information ]; <<>> <<-- Sorted (in increasing pos order) list of Segments. Two Segments in a SortedSegments cannot intersect.>> SortedSegments: TYPE = LIST OF Segment _ NIL; <<>> <> worldSegment: READONLY Segment; <> worldSortedSegments: READONLY SortedSegments; <> <> StretchInfo: TYPE = REF StretchInfoRec; StretchInfoRec: TYPE = RECORD [ value: CD.Number _ 0 -- Wanted value of stretch ]; <> StretchSegment: TYPE = Segment; SortedStretchSegments: TYPE = SortedSegments; <<-- Operations on those data structures>> <<>> <<-- Operations on PosRange>> <<>> PosRangeXFromRect: PROC [rect: CD.Rect] RETURNS [posrange: PosRange]; PosRangeYFromRect: PROC [rect: CD.Rect] RETURNS [posrange: PosRange]; RectFromPosRangeX: PROC [pos: PosRange, y: CD.Number] RETURNS [rect: CD.Rect]; RectFromPosRangeY: PROC [pos: PosRange, x: CD.Number] RETURNS [rect: CD.Rect]; <<>> <<-- Predicate telling if 2 PosRanges Intersects>> IntersectPos: PROC [pos1, pos2: PosRange] RETURNS [intersect: BOOL]; <<>> <<-- Offsets a PosRange by an INT amount>> OffsetPosRange: PROC [pos: PosRange, offset: INT] RETURNS [posrange: PosRange]; <<-- Intersects 2 PosRange>> IntersectPosRange: PROC [pos1, pos2: PosRange] RETURNS [posrange: PosRange]; <<-- Union of 2 PosRange>> UnionPosRange: PROC [pos1, pos2: PosRange] RETURNS [posrange: PosRange]; <<-- Operations on Segment>> <<>> <<-- Creates a new Segment>> MakeNewSegment: PROC [pos: PosRange, info: REF _ NIL] RETURNS [seg: Segment]; <<>> <<-- Tells whether 2 segments do intersect>> IntersectSeg: PROC [s1, s2: Segment] RETURNS [intersect: BOOL]; <<-- Creates a new Segment at the intersection of 2>> IntersectSegment: PROC [s1, s2: Segment, info: REF _ NIL] RETURNS [seg: Segment]; <<-- Creates a new Segment at the reunion of 2>> UnionSegment: PROC [s1, s2: Segment, info: REF _ NIL] RETURNS [seg: Segment]; <<-- Copies a segment with displacing it>> CopySegment: PROC [s: Segment, offset: INT _ 0] RETURNS [seg: Segment]; <<-- Operations on SortedSegments>> <<>> <<-- Returns the sorted list of all segments which intersect some given PosRange>> IntersectPosSegs: PROC [pos: PosRange, segments: SortedSegments] RETURNS [inter: SortedSegments]; <<-- Appends a SortedSegments to an existing one, with copying and displacing the Segments. With only first argument, returns a top-level copy of it.>> Append: PROC [s1: SortedSegments, s2: SortedSegments _ NIL, offset: INT _ 0] RETURNS [SortedSegments]; <<-- Reverse a SortedSegments, as Lisp's reverse! In fact list is not really a SortedSegments before the call to reverse.>> Reverse: PROC [list: SortedSegments] RETURNS [new: SortedSegments]; <<-- Makes a new SortedSegments with all segments that appear in both lists>> Intersect: PROC [list1, list2: SortedSegments] RETURNS [list: SortedSegments]; <<-- Makes a new SortedSegments with all segments that appear in either lists>> Union: PUBLIC PROC [list1, list2: SortedSegments] RETURNS [list: SortedSegments]; <<-- Inserts a new Segment >> Insert: PROC [pos: PosRange, info: REF, list: SortedSegments _ NIL] RETURNS [SortedSegments]; <<-- Makes a list with all segments in range that are excluded by list>> Complement: PROC [list: SortedSegments, range: PosRange] RETURNS [SortedSegments]; <<>> <<-- Operations on StretchSegment>> <<>> GetStretchValue: PROC [s: StretchSegment] RETURNS [CD.Number]; <> InsertStretchSegment: PROC [pos: PosRange, value: CD.Number, s: SortedStretchSegments] RETURNS [SortedStretchSegments]; <<-- Computes the new location of a Rect once composed with the given SortedStretchSegments>> ComposeRectStretches: PROC [rect: CD.Rect, hor, ver: SortedStretchSegments] RETURNS [CD.Rect]; <<-- Stretch related operations>> <<>> <> ParseStretchProc: TYPE = PROC [design: CD.Design, obj: CD.ObPtr] RETURNS [hor, ver: SortedSegments]; <> <<-- design is the design into the new object should be entered. It is the same design in which the object comes from. >> <<-- obj is the object to be stretched>> <<-- hor and ver are a list of segments telling where we want to do the stretch. The info field of segments contains an integer which is the amount of stretch desired.>> <<-- newObj is a new obj or NIL if something went wrong (in that case errMsg is a rope telling what went wrong).>> DoStretchProc: TYPE = PROC [design: CD.Design, obj: CD.ObPtr, hor, ver: SortedSegments] RETURNS [newObj: CD.ObPtr, errMsg: ROPE _ NIL]; <<>> <<-- Given any cell, tells where the stretch areas are>> ParseStretch: ParseStretchProc; <<-- Given cell and wanted stretches, return a new cell>> DoStretch: DoStretchProc; <<>> <<-- Used for telling that an object is not stretchable>> HardObjParseStretch: ParseStretchProc; END.