InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
RangeData.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: sheridan
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //
23 // Purpose:
24 //
25 //========================================================================================
26 
27 #ifndef __RangeData__
28 #define __RangeData__
29 
30 
31 #include "BaseType.h"
32 #include "K2Assert.h"
33 #include <algorithm> //for std::min, std::max, std::swap
34 
35 //forward declarations
36 class RangeData;
37 inline RangeData Join( const RangeData& x, const RangeData& y, const RangeData* clip = nil);
38 inline RangeData SlideForward( const RangeData& x, int32 y, const RangeData* clip = nil);
39 inline RangeData AdvanceEnd( const RangeData& x, int32 y, const RangeData* clip = nil);
40 inline RangeData RecedeStart( const RangeData& x, int32 y, const RangeData* clip = nil);
41 inline bool16 operator==(const RangeData& lhs, const RangeData& rhs);
42 inline RangeData EndLocation( const RangeData& x);
43 inline RangeData StartLocation( const RangeData& x);
44 
45 
46 class RangeData
47 {
48 public:
49  //types
50  typedef base_type data_type; //K2Vector requirement
51  enum Lean { kLeanForward = 0, kLeanForth = kLeanForward, kLeanBack = 1, kLeanBackward = kLeanBack};
52  enum {kDontConsiderLean = 0, kIgnoreLean = kDontConsiderLean, kConsiderLean = 1};
53 
54  //Constructors
55  RangeData( const RangeData& r) noexcept = default;
56  RangeData( RangeData&& r) noexcept = default;
57  RangeData( const RangeData& r, const RangeData* clip);
58  RangeData( TextIndex start, TextIndex end, const RangeData* clip = nil);
59  RangeData( TextIndex caret, Lean lean, const RangeData* clip = nil);
60  RangeData( TextIndex start, TextIndex end, Lean lean, const RangeData* clip = nil);
61 
62  RangeData &operator =(const RangeData &) noexcept = default;
63  RangeData &operator =(RangeData &&) noexcept = default;
64 
65  //Accessors
66  TextIndex Start(Lean* lean) const { if(lean) *lean = fLean; return fStart;}
67  TextIndex End() const { return fEnd;}
68  int32 Length() const { return fEnd - fStart;}
69 
70  //Predicates
71  int32 OverlapWith( const RangeData& other) const;
72  bool16 StartsBefore( const RangeData& other, bool16 consideringLean = kIgnoreLean) const;
73  bool16 EndsAfter( const RangeData& other, bool16 consideringLean = kIgnoreLean) const;
74  bool16 Precedes( const RangeData& other) const;
75  bool16 Leads( const RangeData& other) const;
76  bool16 Succeeds( const RangeData& other) const;
77  bool16 Follows( const RangeData& other) const;
78  bool16 CompletelyPrecedes( const RangeData& other) const { return fEnd <= other.fStart;}
79  bool16 Contains( const RangeData& other, bool16 consideringLean = kIgnoreLean) const;
80  bool16 Contains(TextIndex index) const;
81  bool16 Matches( const RangeData& other, bool16 consideringLean = kConsiderLean) const;
82  bool16 Begins( const RangeData& other) const;
83  bool16 Ends( const RangeData& other) const;
84  bool16 Anchors( const RangeData& other) const;
85 
86 
87 private:
88  TextIndex fStart;
89  TextIndex fEnd;
90  Lean fLean;
91 
92  enum {kLeanTowardOriginal = 0, kLeanIntoClip = 1};
93  void Check()
94  {
95  ASSERT_MSG( 0 <= fStart && fStart <= fEnd && (fLean == kLeanForward || fEnd > 0),
96  FORMAT_ARGS("Bad RangeData(%d,%d,%s) constructed", fStart, fEnd, fLean == kLeanForward ? "kLeanForward" : "kLeanBack"));
97  //repair after assert with the hope that we can proceed
98  if( fStart < 0) fStart = 0;
99  if( fEnd < fStart) fEnd = fStart;
100  if( fLean == kLeanBackward && fEnd == 0) fLean = kLeanForward;
101  }
102  void ClipTo( const RangeData* clip, bool16 leanInside){ if( clip) ClipTo_( *clip, leanInside); else Check();}
103  void ClipTo_( const RangeData& clip, bool16 leanInside); //only non-inlined member function
104  friend RangeData Join( const RangeData& x, const RangeData& y, const RangeData* clip);
105  friend RangeData SlideForward( const RangeData& x, int32 y, const RangeData* clip);
106  friend RangeData AdvanceEnd( const RangeData& x, int32 y, const RangeData* clip);
107  friend RangeData RecedeStart( const RangeData& x, int32 y, const RangeData* clip);
108 };
109 
110 
111 
112 //inline constructors
127 inline RangeData::RangeData( const RangeData& r, const RangeData* clip)
128  : fStart(r.fStart), fEnd(r.fEnd), fLean(r.fLean)
129 {
130  ClipTo(clip, kLeanIntoClip);
131 }
132 
147 inline RangeData::RangeData( TextIndex start, TextIndex end, const RangeData* clip)
148  : fStart(start), fEnd(end), fLean(kLeanForward)
149 {
150  // should zero width clip mean RangeData( clip.fStart, std::numeric_limits<TextIndex>::max()) or
151  // RangeData( std::numeric_limits<TextIndex>::max(), clip.fStart) depending on clip.fLean??
152  ASSERT( fStart < fEnd); //wait for clip before Check()
153  ClipTo( clip, kLeanIntoClip);
154 }
155 
156 inline RangeData::RangeData( TextIndex caret, Lean lean, const RangeData* clip)
157  : fStart(caret), fEnd(caret), fLean(lean)
158 {
159  ClipTo( clip, kLeanIntoClip);
160 }
161 
176 inline RangeData::RangeData( TextIndex start, TextIndex end, Lean lean, const RangeData* clip)
177  : fStart(start), fEnd(end), fLean(start == end ? lean : kLeanForward)
178 {
179  ClipTo( clip, kLeanIntoClip);
180 }
181 
182 
183 //inlines member functions
184 inline int32 RangeData::OverlapWith( const RangeData& other) const
185 {
186  // OverlapWith returns zero if ranges are juxtaposed, positive if
187  // they overlap, negative if separated by at least one character.
188  return other.Length() + Length() - Join(other,*this).Length();
189 }
190 
191 inline bool16 RangeData::StartsBefore( const RangeData& other, bool16 consideringLean) const
192 {
193  return fStart < other.fStart
194  || (consideringLean && fStart == other.fStart && fLean == kLeanBack && other.fLean == kLeanForward);
195 }
196 
197 inline bool16 RangeData::EndsAfter( const RangeData& other, bool16 consideringLean ) const
198 {
199  return fEnd > other.fEnd
200  || (consideringLean && fStart == other.fEnd && fLean == kLeanForward
201  && (other.fLean == kLeanBack || other.fStart < other.fEnd));
202 }
203 
204 inline bool16 RangeData::Precedes( const RangeData& other) const
205 {
206  RangeData::Lean myLean, otherLean;
207  int32 myEnd = EndLocation(*this).Start( &myLean);
208  int32 otherStart = StartLocation(other).Start( &otherLean);
209 
210  if( myEnd < otherStart)
211  return kTrue;
212  else if( myEnd > otherStart)
213  return kFalse;
214  else
215  return myLean == RangeData::kLeanBack && otherLean == RangeData::kLeanForward;
216 }
217 
218 inline bool16 RangeData::Leads( const RangeData& other) const
219 {
220  return Precedes( other);
221 }
222 
223 inline bool16 RangeData::Succeeds( const RangeData& other) const
224 {
225  return EndLocation( other).Precedes( StartLocation( *this));
226 }
227 
228 inline bool16 RangeData::Follows( const RangeData& other) const
229 {
230  return Succeeds( other);
231 }
232 
233 
234 inline bool16 RangeData::Matches( const RangeData& other, bool16 consideringLean) const
235 {
236  return fStart == other.fStart && fEnd == other.fEnd && (!consideringLean || fLean == other.fLean);
237 }
238 
239 inline bool16 RangeData::Begins( const RangeData& other) const
240 {
241  return fStart == other.fStart && fEnd <= other.fEnd;
242 }
243 
244 inline bool16 RangeData::Ends( const RangeData& other) const
245 {
246  return fEnd == other.fEnd && fStart >= other.fStart;
247 }
248 
249 inline bool16 RangeData::Anchors( const RangeData& other) const
250 {
251  return Begins(other) || Ends(other);
252 }
253 
254 inline bool16 RangeData::Contains( const RangeData& other, bool16 consideringLean) const
255 {
256  if( consideringLean){
257  if( fStart == fEnd) //if I'm a caret
258  return *this == other; //checks if fLean matches
259  if( other.fStart == other.fEnd){ //if other is a caret
260  if( other.fStart == fStart)
261  return other.fLean == kLeanForward;
262  else if( other.fEnd == fEnd)
263  return other.fLean == kLeanBack;
264  //else fall through
265  }
266  }
267  return fStart <= other.fStart && other.fEnd <= fEnd;
268 }
269 
270 inline bool16 RangeData::Contains(TextIndex index) const
271 {
272  return RangeData::Contains( RangeData(index, index + 1), kDontConsiderLean);
273 }
274 
275 
276 
277 
278 //operators with friend access
279 
280 inline RangeData Join( const RangeData& x, const RangeData& y, const RangeData* clip) //union
281 {
282  return RangeData(
283  std::min(x.fStart, y.fStart),
284  std::max(x.fEnd, y.fEnd),
285  x.fLean || y.fLean ? RangeData::kLeanBack : RangeData::kLeanForward,
286  clip);
287 }
288 
289 inline RangeData AdvanceEnd( const RangeData& x, int32 y, const RangeData* clip) //move end forward by
290 {
291  TextIndex end = x.End() + y;
292  TextIndex start = x.Start(nil);
293  return RangeData( std::min( start, end), std::max( start, end), x.fLean, clip);
294 }
295 
296 inline RangeData RecedeStart( const RangeData& x, int32 y, const RangeData* clip) //move start back by
297 {
298  TextIndex end = x.End();
299  TextIndex start = x.Start(nil) - y;
300  return RangeData( std::min( start, end), std::max( start, end), x.fLean, clip);
301 }
302 
303 inline RangeData SlideForward( const RangeData& x, int32 y, const RangeData* clip)
304 {
305  return RangeData( x.fStart + y, x.fEnd + y, x.fLean, clip);
306 }
307 
308 
309 
310 //operators using public access
311 
312  void Disjoin( RangeData& lhs, RangeData& rhs); //return two ranges that are the XOR of the originals
313  //only non-inlined operator
314 
315 inline bool16 operator<( const RangeData& x, const RangeData& y) //an ordering for sorting
316 {
317  return x.Start(nil) < y.Start(nil) || (x.Start(nil) == y.Start(nil) && x.End() < y.End());
318 }
319 
320 inline RangeData operator+( const RangeData& x, const RangeData& y) //union
321 {
322  return Join(x, y);
323 }
324 
325 inline RangeData SlideBackward( const RangeData& x, int32 y, const RangeData* clip = nil)
326 {
327  return SlideForward( x, -y, clip);
328 }
329 
330 inline RangeData operator>>( const RangeData& x, int32 y)
331 {
332  return SlideForward( x, y);
333 }
334 
335 inline RangeData operator<<( const RangeData& x, int32 y)
336 {
337  return SlideBackward( x, y);
338 }
339 
340 inline RangeData EndLocation( const RangeData& x)
341 {
342  return x.Length() == 0 ? x : RangeData( x.End(), RangeData::kLeanBack);
343 }
344 
345 inline RangeData StartLocation( const RangeData& x)
346 {
347  return x.Length() == 0 ? x : RangeData( x.Start(nil), RangeData::kLeanForward);
348 }
349 
350 inline RangeData NewEndLocation(const RangeData& x, TextIndex end, const RangeData* clip = nil)
351 {
352  return AdvanceEnd(x, end-x.End(), clip);
353 }
354 
355 inline RangeData NewStartLocation(const RangeData& x, TextIndex start, const RangeData* clip = nil)
356 {
357  return RecedeStart(x, x.Start(nil)-start, clip);
358 }
359 
360 inline RangeData RecedeEnd( const RangeData& x, int32 y, const RangeData* clip = nil) //move end backward by
361 {
362  return AdvanceEnd( x, -y, clip);
363 }
364 
365 inline RangeData operator+( const RangeData& x, int32 y) //move end forward by
366 {
367  return AdvanceEnd( x, y);
368 }
369 
370 inline RangeData MidPoint( const RangeData& x)
371 {
372  return x.Length() == 0 ? x : RangeData( (x.Start(nil) + x.End())/2, RangeData::kLeanForward);
373 }
374 
375 inline RangeData AdvanceStart( const RangeData& x, int32 y, const RangeData* clip = nil)
376 {
377  return RecedeStart( x, -y, clip);
378 }
379 
380 inline RangeData operator-( const RangeData& x, int32 y) //move start back by
381 {
382  return RecedeStart( x, y);
383 }
384 
385 inline RangeData Clip( const RangeData& r, const RangeData& clip) //like intersection but with specific behavior when the intersection is empty
386 {
387  return RangeData( r, &clip);
388 }
389 
390 inline bool16 operator==(const RangeData& lhs, const RangeData& rhs)
391 {
392  return lhs.Matches(rhs, RangeData::kConsiderLean);
393 }
394 
395 inline bool16 operator!=(const RangeData& lhs, const RangeData& rhs)
396 {
397  return !(lhs == rhs);
398 }
399 
400 inline RangeData NewLean( const RangeData& r, RangeData::Lean lean)
401 {
402  return RangeData( r.Start(nil), r.End(), lean);
403 }
404 
405 inline RangeData NewLean( const RangeData& r, const RangeData& copyLean)
406 {
407  RangeData::Lean lean;
408  (void)copyLean.Start(&lean);
409  return NewLean( r, lean);
410 }
411 
412 inline RangeData LeanForward( const RangeData& r)
413 {
414  return NewLean( r, RangeData::kLeanForward);
415 }
416 
417 inline RangeData LeanBack( const RangeData& r)
418 {
419  return NewLean( r, RangeData::kLeanBack);
420 }
421 
422 
423 
424 //temporary adaptor--StoryRange shouldn't be used for new code
425 
426 namespace Text {
427  class StoryRange : public RangeData //adaptor for now
428  {
429  public:
430  StoryRange( const StoryRange& r) noexcept = default;
431  StoryRange( StoryRange&& r) noexcept = default;
432  StoryRange( const RangeData& r) : RangeData(r) {}
433  StoryRange( TextIndex start, TextIndex end, Lean lean = kLeanForward) : RangeData(start, end, lean) {}
434  StoryRange &operator =( const StoryRange& r) noexcept = default;
435  StoryRange &operator =( StoryRange&& r) noexcept = default;
436  TextIndex GetEnd() const { return End();}
437  TextIndex GetStart( RangeData::Lean* lean = nil) const { return Start(lean);}
438  };
439 
441 }
442 
443 using Text::StoryRange;
445 
446 class UIDRef;
447 
450 {
451 public:
452  typedef object_type data_type;
453 
455  ModelRange(const UIDRef& s, const RangeData& r) : storyRef(s), range(r)
456  { }
457 
459  ModelRange(const UIDRef& s, TextIndex b, TextIndex e, RangeData::Lean lean = RangeData::kLeanForward) : storyRef(s), range(b, e, lean)
460  { }
461 
463  ModelRange(const UIDRef& s, TextIndex o) : storyRef(s), range(o, o, RangeData::kLeanForward)
464  { }
465 
467  ModelRange() : range(0, 0, RangeData::kLeanForward)
468  { }
469 
471  TextIndex GetEnd() const { return range.End();}
473  TextIndex GetStart( RangeData::Lean* lean = nil) const { return range.Start(lean);}
474 
479 };
480 
481 
482 #endif