Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
TextInteractor.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4
5namespace Stroika::Frameworks::Led {
6
7#if qStroika_Frameworks_Led_SupportGDI
8 /*
9 ********************************************************************************
10 ***************************** Implementation Details ***************************
11 ********************************************************************************
12 */
13
14 // class TextInteractor::SuppressCommandBreaksContext
15 inline TextInteractor::SuppressCommandBreaksContext::SuppressCommandBreaksContext (TextInteractor& ti)
16 : fTextInteractor (ti)
17 , fOldVal (ti.fSuppressCommandBreaksContext)
18 {
19 ti.fSuppressCommandBreaksContext = true;
20 }
21 inline TextInteractor::SuppressCommandBreaksContext::~SuppressCommandBreaksContext ()
22 {
23 fTextInteractor.fSuppressCommandBreaksContext = fOldVal;
24 }
25
26 // class TextInteractor::PreScrollInfo
27 inline TextInteractor::PreScrollInfo::PreScrollInfo ()
28 : fUpdateMode (eDefaultUpdate)
29 , fOldWindowStart (0)
30 , fOldHScrollPos (0)
31 , fTryTodoScrollbits (false)
32 , fOldLastRowStart (0)
33 {
34 }
35
36 // class CommandNumberMapping<TARGET_COMMAND_NUMBER>
37 template <typename TARGET_COMMAND_NUMBER>
38 CommandNumberMapping<TARGET_COMMAND_NUMBER>* CommandNumberMapping<TARGET_COMMAND_NUMBER>::sThe = nullptr;
39 template <typename TARGET_COMMAND_NUMBER>
40 CommandNumberMapping<TARGET_COMMAND_NUMBER>::CommandNumberMapping ()
41 : fMap ()
42 , fRanges ()
43 {
44 Assert (sThe == nullptr);
45 sThe = this;
46 }
47 template <typename TARGET_COMMAND_NUMBER>
48 CommandNumberMapping<TARGET_COMMAND_NUMBER>::~CommandNumberMapping ()
49 {
50 Assert (sThe == this);
51 sThe = nullptr;
52 }
53 template <typename TARGET_COMMAND_NUMBER>
54 inline CommandNumberMapping<TARGET_COMMAND_NUMBER>& CommandNumberMapping<TARGET_COMMAND_NUMBER>::Get ()
55 {
56 AssertNotNull (sThe); // Applications using Led_MFC must instantiate a subclass of MFC_CommandNumberMapping
57 // BEFORE any access to this class
58 return *sThe;
59 }
60 template <typename TARGET_COMMAND_NUMBER>
61 inline void CommandNumberMapping<TARGET_COMMAND_NUMBER>::AddAssociation (TARGET_COMMAND_NUMBER externalCommandNumber, CommandNumber internalCommandNumber)
62 {
63 fMap.insert (MAP_TYPE::value_type (externalCommandNumber, internalCommandNumber));
64 }
65 template <typename TARGET_COMMAND_NUMBER>
66 inline void CommandNumberMapping<TARGET_COMMAND_NUMBER>::AddRangeAssociation (TARGET_COMMAND_NUMBER externalRangeStart,
67 TARGET_COMMAND_NUMBER externalRangeEnd,
68 CommandNumber internalRangeStart, CommandNumber internalRangeEnd)
69 {
70 Require (int (externalRangeEnd - externalRangeStart) == int (internalRangeEnd - internalRangeStart)); // ranges same length.
71
72 RangeElt re;
73 re.fExternalCmds.first = externalRangeStart;
74 re.fExternalCmds.second = externalRangeEnd;
75 re.fInternalCmds.first = internalRangeStart;
76 re.fInternalCmds.second = internalRangeEnd;
77 fRanges.push_back (re);
78 }
79 template <typename TARGET_COMMAND_NUMBER>
80 TextInteractor::CommandNumber CommandNumberMapping<TARGET_COMMAND_NUMBER>::Lookup (TARGET_COMMAND_NUMBER externalCommandNumber) const
81 {
82 typename MAP_TYPE::const_iterator i = fMap.find (externalCommandNumber);
83 if (i == fMap.end ()) {
84 for (typename RANGE_VEC_TYPE::const_iterator j = fRanges.begin (); j != fRanges.end (); ++j) {
85 const RangeElt& re = *j;
86 if (re.fExternalCmds.first <= externalCommandNumber and externalCommandNumber <= re.fExternalCmds.second) {
87 TARGET_COMMAND_NUMBER offset = externalCommandNumber - re.fExternalCmds.first;
88 TextInteractor::CommandNumber cmdNum = re.fInternalCmds.first + offset;
89 Assert (cmdNum <= re.fInternalCmds.second);
90 return cmdNum;
91 }
92 }
93 return TextInteractor::kNoCommand_CmdID;
94 }
95 else {
96 return (*i).second;
97 }
98 }
99 template <typename TARGET_COMMAND_NUMBER>
100 TARGET_COMMAND_NUMBER CommandNumberMapping<TARGET_COMMAND_NUMBER>::ReverseLookup (CommandNumber cmdNum) const
101 {
102 for (typename MAP_TYPE::const_iterator i = fMap.begin (); i != fMap.end (); ++i) {
103 if ((*i).second == cmdNum) {
104 return (*i).first;
105 }
106 }
107 for (auto j = fRanges.begin (); j != fRanges.end (); ++j) {
108 const RangeElt& re = *j;
109 if (re.fInternalCmds.first <= cmdNum and cmdNum <= re.fInternalCmds.second) {
110 size_t offset = cmdNum - re.fInternalCmds.first;
111 TARGET_COMMAND_NUMBER tarCmd = static_cast<TARGET_COMMAND_NUMBER> (re.fExternalCmds.first + offset);
112 Assert (tarCmd <= re.fExternalCmds.second);
113 return tarCmd;
114 }
115 }
116 // Treat a command which hasn't been registered as the special value 0 indicating 'no command'
117 return 0;
118 }
119
120 // class SimpleCommandUpdater
121 inline SimpleCommandUpdater::SimpleCommandUpdater (CommandNumber cmdNum)
122 : fCommandNumber (cmdNum)
123 , fEnabled (false)
124 , fChecked (false)
125 , fText ()
126 {
127 }
128 inline SimpleCommandUpdater::CommandNumber SimpleCommandUpdater::GetCmdID () const
129 {
130 return fCommandNumber;
131 }
132 inline bool SimpleCommandUpdater::GetEnabled () const
133 {
134 return fEnabled;
135 }
136 inline void SimpleCommandUpdater::SetEnabled (bool enabled)
137 {
138 fEnabled = enabled;
139 }
140 inline void SimpleCommandUpdater::SetChecked (bool checked)
141 {
142 fChecked = checked;
143 }
144 inline void SimpleCommandUpdater::SetText (const SDKChar* text)
145 {
146 RequireNotNull (text);
147 fText = text;
148 }
149
150 // class TextInteractor::InteractiveModeUpdater
151 inline TextInteractor::InteractiveModeUpdater::InteractiveModeUpdater (TextInteractor& ti, bool interactive)
152 : fTextInteractor (ti)
153 , fSavedMode (ti.GetInteractiveUpdateMode ())
154 {
155 InteractiveUpdadeMode newMode = interactive ? eInteractiveUpdateMode : eNonInteractiveUpdateMode;
156 if (ti.GetInteractiveUpdateMode () == eIndeterminateInteractiveUpdateMode) {
157 ti.SetInteractiveUpdateMode (newMode);
158 }
159 else {
160 /*
161 * If the original mode was already set - make sure our new mode agrees.
162 */
163 Assert (ti.GetInteractiveUpdateMode () == newMode);
164 }
165 }
166 inline TextInteractor::InteractiveModeUpdater::~InteractiveModeUpdater ()
167 {
168 fTextInteractor.SetInteractiveUpdateMode (fSavedMode);
169 }
170
171 // class TextInteractor::SmartCNPInfo
172 inline TextInteractor::SmartCNPInfo::SmartCNPInfo ()
173 : fWordBreakAtSelStart (false)
174 , fWordBreakAtSelEnd (false)
175 {
176 }
177
178 // class TextInteractor
179 /*
180 @METHOD: TextInteractor::GetCommandHandler
181 @DESCRIPTION: <p>TextInteractor's have associated an optional @'CommandHandler', used for maintaining UNDO
182 information. This can return nullptr, if no CommandHandler is currently associated (meaning no Undo is avialable).</p>
183 */
184 inline CommandHandler* TextInteractor::GetCommandHandler () const
185 {
186 return fCommandHandler;
187 }
188 /*
189 @METHOD: TextInteractor::SetCommandHandler
190 @DESCRIPTION: <p>See @'TextInteractor::GetCommandHandler'.</p>
191 */
192 inline void TextInteractor::SetCommandHandler (CommandHandler* commandHandler)
193 {
194 fCommandHandler = commandHandler;
195 }
196 /*
197 @METHOD: TextInteractor::BreakInGroupedCommands
198 @DESCRIPTION: <p>Trivial helper - delegates to @'CommandHandler::BreakInGroupedCommands' if
199 @'TextInteractor::GetCommandHandler' returns non-nullptr.
200 See also @'TextInteractor::SuppressCommandBreaksContext'</p>
201 */
202 inline void TextInteractor::BreakInGroupedCommands ()
203 {
204 if (fCommandHandler != nullptr and not fSuppressCommandBreaksContext) {
205 fCommandHandler->BreakInGroupedCommands ();
206 }
207 }
208 /*
209 @METHOD: TextInteractor::BreakInGroupedCommandsIfDifferentCommand
210 @DESCRIPTION: <p>Trivial helper - delegates to @'CommandHandler::BreakInGroupedCommandsIfDifferentCommand' if
211 @'TextInteractor::GetCommandHandler' returns non-nullptr.
212 See also @'TextInteractor::SuppressCommandBreaksContext'</p>
213 */
214 inline void TextInteractor::BreakInGroupedCommandsIfDifferentCommand (const SDKString& cmdName)
215 {
216 if (fCommandHandler != nullptr and not fSuppressCommandBreaksContext) {
217 fCommandHandler->BreakInGroupedCommandsIfDifferentCommand (cmdName);
218 }
219 }
220 /*
221 @METHOD: TextInteractor::GetDialogSupport
222 @DESCRIPTION: <p></p>
223 */
224 inline TextInteractor::DialogSupport& TextInteractor::GetDialogSupport ()
225 {
226 if (sDialogSupport == nullptr) {
227 static DialogSupport sDefSup;
228 sDialogSupport = &sDefSup;
229 }
230 return *sDialogSupport;
231 }
232 /*
233 @METHOD: TextInteractor::SetDialogSupport
234 @DESCRIPTION: <p></p>
235 */
236 inline void TextInteractor::SetDialogSupport (DialogSupport* ds)
237 {
238 sDialogSupport = ds;
239 }
240 /*
241 @METHOD: TextInteractor::GetCommandNames
242 @DESCRIPTION: <p>Returns command name for each of the user-visible commands produced by this module.
243 This name is used used in the constructed Undo command name, as
244 in, "Undo Paste". You can replace this name with whatever you like.You change this value with
245 WordProcessor::SetCommandNames.</p>
246 <p> The point of this is to allow for different UI-language localizations,
247 without having to change Led itself.</p>
248 <p>See also @'TextInteractor::CommandNames'.</p>
249 */
250 inline const TextInteractor::CommandNames& TextInteractor::GetCommandNames ()
251 {
252 return sCommandNames;
253 }
254 /*
255 @METHOD: TextInteractor::SetCommandNames
256 @DESCRIPTION: <p>See @'TextInteractor::GetCommandNames'.</p>
257 */
258 inline void TextInteractor::SetCommandNames (const TextInteractor::CommandNames& cmdNames)
259 {
260 sCommandNames = cmdNames;
261 }
262 /*
263 @METHOD: TextInteractor::GetSpellCheckEngine
264 @DESCRIPTION: <p>Return a pointer to the current @'SpellCheckEngine' if there is one. It CAN BE nullptr - meaning
265 that spellchecking is disabled. See @'TextInteractor::SetSpellCheckEngine'.</p>
266 */
267 inline SpellCheckEngine* TextInteractor::GetSpellCheckEngine () const
268 {
269 return fSpellCheckEngine;
270 }
271 /*
272 @METHOD: TextInteractor::SetSpellCheckEngine
273 @DESCRIPTION: <p>This is typically called by an application or document to associate a spellcheck engine with the
274 @'TextInteractor'. That caller still 'owns' the object and must manage its lifetime, and to reset this
275 value (in this class) to nullptr before destorying the @'SpellCheckEngine'. If you have an option to turn on/off
276 spellchecking, when you turn it off, you would typically just call this method with nullptr to disable
277 spellchecking command funcitonality. Be sure to set this property to nullptr before destruction.</p>
278 <p>See @'TextInteractor::GetSpellCheckEngine'.</p>
279 */
280 inline void TextInteractor::SetSpellCheckEngine (SpellCheckEngine* spellCheckEngine)
281 {
282 fSpellCheckEngine = spellCheckEngine;
283 }
284 /*
285 @METHOD: TextInteractor::GetDefaultUpdateMode
286 @DESCRIPTION: <p>TextInteractor's have an associated default UpdateMode. This is the update mode which is
287 used by methods which used the eDefaultUpdateMode argument (most default UpdateMode args in Led are this value).</p>
288 <p>This value should <em>not</em> be set directly. Instead, instantiate a
289 @'TextInteractor::TemporarilySetUpdateMode' object on
290 the stack to temporarily set the default update mode.</p>
291 */
292 inline TextInteractor::UpdateMode TextInteractor::GetDefaultUpdateMode () const
293 {
294 Ensure (fDefaultUpdateMode != eDefaultUpdate);
295 return fDefaultUpdateMode;
296 }
297 /*
298 @METHOD: TextInteractor::RealUpdateMode
299 @DESCRIPTION: <p>TextInteractor's have an associated default UpdateMode. This utility method takes an arbitrary
300 UpdateMode, and returns either its argument, or if it was eDefaultUpdateMode, it returns the current value
301 of the default update mode.</p>
302 */
303 inline TextInteractor::UpdateMode TextInteractor::RealUpdateMode (UpdateMode updateMode) const
304 {
305 return updateMode == eDefaultUpdate ? GetDefaultUpdateMode () : updateMode;
306 }
307 /*
308 @METHOD: TextInteractor::GetSmartCutAndPasteMode
309 @DESCRIPTION: <p>TextInteractor's support a UI feature called "smart cut & paste". Basicly, Led tries to guess
310 what a user 'really meant todo' with surrounding whitespace when dragging, and cutting and pasting text.</p>
311 <p> This can sometimes be extremely helpful. Othertimes, it can be extremely anoying. You decide. Thats
312 why its an option.</p>
313 <p>And see @'TextInteractor::OptionallyAddExtraSpaceForSmartCutAndPasteModeAdds' and
314 @'TextInteractor::OptionallyExpandSelectionForSmartCutAndPasteModeDeletes' for the implementation of
315 smart cut and paste.</p>
316 */
317 inline bool TextInteractor::GetSmartCutAndPasteMode () const
318 {
319 return fSmartCutAndPasteMode;
320 }
321 /*
322 @METHOD: TextInteractor::SetSmartCutAndPasteMode
323 @DESCRIPTION: <p>Set the 'smart cut and paste' mode. See TextInteractor::GetSmartCutAndPasteMode for more details.</p>
324 */
325 inline void TextInteractor::SetSmartCutAndPasteMode (bool smartCutAndPasteMode)
326 {
327 fSmartCutAndPasteMode = smartCutAndPasteMode;
328 }
329 /*
330 @METHOD: TextInteractor::GetCurClickCount
331 @DESCRIPTION: <p>Used to keep track of the number of clicks the user has done very recently. Used for determining
332 double and triple clicks. If the user clicks, and then clicks a long time later - it wont be considered
333 a double click - and so this value will remain one.</p>
334 */
335 inline unsigned TextInteractor::GetCurClickCount () const
336 {
337 return fClickCount;
338 }
339 /*
340 @METHOD: TextInteractor::SetCurClickCount
341 @DESCRIPTION: <p>See also @'TextInteractor::GetCurClickCount' (). This is seldom called directly - except perhaps to RESET
342 the count to zero or one. This is typically just called internally through @'TextInteractor::UpdateClickCount'.</p>
343 */
344 inline void TextInteractor::SetCurClickCount (unsigned curClickCount, Foundation::Time::TimePointSeconds lastClickAt)
345 {
346 fClickCount = curClickCount;
347 fLastClickedAt = lastClickAt;
348 }
349 /*
350 @METHOD: TextInteractor::IncrementCurClickCount
351 @DESCRIPTION: <p>See also @'TextInteractor::GetCurClickCount' () and @'TextInteractor::SetCurClickCount' ().
352 This is typically just called internally through @'TextInteractor::UpdateClickCount'.</p>
353 */
354 inline void TextInteractor::IncrementCurClickCount (Foundation::Time::TimePointSeconds lastClickAt)
355 {
356 ++fClickCount;
357 fLastClickedAt = lastClickAt;
358 }
359 /*
360 @METHOD: TextInteractor::IsWholeWindowInvalid
361 @DESCRIPTION: <p>Sometimes we can go through alot of computation to see just what minimal area of the window needs
362 to be updated. Sometimes this can be quite helpful, and allow things to run quickly. But other times,
363 like when we are making many changes to the text before ever showing anything, it would be just faster
364 to mark the whole screen as dirty, and to avoid the computation about what region needs updating.
365 Thats what these APIs here are about.</p>
366 <p>You can tell the @'TextInteractor' that the whole window is dirty explicitly by simply doing a Refresh()
367 with no arguments (really anything which causes whole window rect to become invalid).
368 You can query if the whole window is invalid. This only returns true if the whole window is KNOWN
369 to be invalid. It maybe that there is some complex update region which happens to cover the whole window
370 or that something has happened that we don't know about to make the entire window invalid. We will
371 just return false in those cases. But you can count on the fact that if IsWholeWindowInvalid() returns
372 true - this means you need not do any bookkeeping/work to compute just what region you will be
373 updating.</p>
374 <p>We OVERRIDE the Draw (const Led_Rect& subsetToDraw, bool printing) method to call
375 @'TextInteractor::NoteWindowPartiallyUpdated' ().
376 (clearning the fWholeWindowInvalid bool). If subclassers who OVERRIDE Draw(), or otherwise update the
377 screen (calling ValidRect ()) - should be sure to call NoteWindowPartiallyUpdated ();</p>
378 <p>Led supports a redraw optimization, whereby complex calculations about what region of the screen
379 needs to be invalidated can be avoided, if we keep track of, and cache the notion that the whole screen is
380 already fully invalidated. This method is called internally to avoid complex calculations. You may <em>rarely</em>
381 want to call it as well, if profiling yields a hot-spot in your code, in a calculation of something that need not
382 be done if the screen has already been marked as invalid.</p>
383 */
384 inline bool TextInteractor::IsWholeWindowInvalid () const
385 {
386 return fWholeWindowInvalid;
387 }
388 /*
389 @METHOD: TextInteractor::NoteWholeWindowIsInvalid
390 @DESCRIPTION: <p>See @'TextInteractor::IsWholeWindowInvalid'. This method marks the screen as
391 already having been invalidated. Called internally by Led. Only call this with extreme
392 caution. Should very rarely be appropriate, outside of class library wrappers.</p>
393 */
394 inline void TextInteractor::NoteWholeWindowIsInvalid ()
395 {
396 fWholeWindowInvalid = true;
397 }
398 /*
399 @METHOD: TextInteractor::NoteWindowPartiallyUpdated
400 @DESCRIPTION: <p>See @'TextInteractor::IsWholeWindowInvalid'. This method marks the screen as having been
401 at least partially redrawn, so the 'IsWholeWindowInvalid' no longer apply.</p>
402 <p>Called internally by Led. Only call this with extreme caution. Should very rarely be
403 appropriate, outside of class library wrappers.</p>
404 */
405 inline void TextInteractor::NoteWindowPartiallyUpdated ()
406 {
407 fWholeWindowInvalid = false;
408 }
409 /*
410 @METHOD: TextInteractor::Refresh
411 @DESCRIPTION: <p>Invalidate the entire window rectangle (@'TextImager::GetWindowRect') in a
412 manner dependingon the 'updateMode' (see @'TextInteractor::UpdateMode'). Delegates
413 implemantion to @'TextInteractor::Refresh_', which is generally overriden in
414 SDK-specific wrapper subclass.</p>
415 */
416 inline void TextInteractor::Refresh (UpdateMode updateMode) const
417 {
418 updateMode = RealUpdateMode (updateMode);
419 if (updateMode != eNoUpdate) {
420 if (updateMode == eDelayedUpdate and IsWholeWindowInvalid ()) {
421 return;
422 }
423 RefreshWindowRect_ (GetWindowRect (), updateMode);
424 // wrong - cuz above may not have invaled anything if ??? Hmm.. maybe under some circomstances???
425 if (updateMode == eDelayedUpdate) {
426 const_cast<TextInteractor*> (this)->NoteWholeWindowIsInvalid ();
427 }
428 }
429 }
430 /*
431 @METHOD: TextInteractor::RefreshWindowRect_
432 @DESCRIPTION: <p>Cause the given region of the edit window to be updated. The given 'windowRectArea'
433 is given in the same coordinates as the window rect
434 specified by @'TextImager::SetWindowRect': it is not relative to that rectangle.</p>
435 <p>This simply calls @'TextInteractor::RefreshWindowRect_' to delegate its implementation.</p>
436 */
437 inline void TextInteractor::RefreshWindowRect (const Led_Rect& windowRectArea, UpdateMode updateMode) const
438 {
439 updateMode = RealUpdateMode (updateMode);
440 if (updateMode != eNoUpdate) {
441 if (updateMode == eDelayedUpdate and IsWholeWindowInvalid ()) {
442 return;
443 }
444 RefreshWindowRect_ (windowRectArea, updateMode);
445 if (updateMode == eDelayedUpdate and windowRectArea.Contains (GetWindowRect ())) {
446 const_cast<TextInteractor*> (this)->NoteWholeWindowIsInvalid ();
447 }
448 }
449 }
450 /*
451 @METHOD: TextInteractor::Update
452 @DESCRIPTION: <p>Calls @'TextInteractor::UpdateWindowRect' on the entire windowrect.</p>
453 */
454 inline void TextInteractor::Update (bool ignoreCannotUpdateNowErrors) const
455 {
456 try {
457 UpdateWindowRect_ (GetWindowRect ());
458 }
459 catch (CannotUpdateNow&) {
460 if (not ignoreCannotUpdateNowErrors) {
461 throw;
462 }
463 }
464 catch (...) {
465 throw;
466 }
467 }
468 /*
469 @METHOD: TextInteractor::UpdateWindowRect
470 @DESCRIPTION: <p>Makes sure the given section of the window rect is updated (redisplayed). This MAY
471 not be possible at a given time, in whcih case, @'TextInteractor::CannotUpdateNow' maybe
472 thrown instead.</p>
473 */
474 inline void TextInteractor::UpdateWindowRect (const Led_Rect& windowRectArea, bool ignoreCannotUpdateNowErrors) const
475 {
476 try {
477 UpdateWindowRect_ (windowRectArea);
478 }
479 catch (CannotUpdateNow&) {
480 if (not ignoreCannotUpdateNowErrors) {
481 throw;
482 }
483 }
484 catch (...) {
485 throw;
486 }
487 }
488 /*
489 @METHOD: TextInteractor::GetUseSecondaryHilight
490 @DESCRIPTION: <p>See @'TextInteractor::SetUseSecondaryHilight'.</p>
491 */
492 inline bool TextInteractor::GetUseSecondaryHilight () const
493 {
494 return fUseSecondaryHilight;
495 }
496 /*
497 @METHOD: TextInteractor::SetUseSecondaryHilight
498 @DESCRIPTION: <p>If this is set true (false by default) then when a window is deactivated, it will draw
499 its selection hilight as an outline - rather than just not displaying it.</p>
500 <p>See also @'TextInteractor::GetUseSecondaryHilight'.</p>
501 */
502 inline void TextInteractor::SetUseSecondaryHilight (bool useSecondaryHilight)
503 {
504 if (fUseSecondaryHilight != useSecondaryHilight) {
505 Refresh ();
506 fUseSecondaryHilight = useSecondaryHilight;
507 }
508 }
509 inline bool TextInteractor::GetUseBitmapScrollingOptimization () const
510 {
511 return fUseBitmapScrollingOptimization;
512 }
513 inline void TextInteractor::SetUseBitmapScrollingOptimization (bool useBitmapScrollingOptimization)
514 {
515 fUseBitmapScrollingOptimization = useBitmapScrollingOptimization;
516 }
517 inline bool TextInteractor::GetSuppressTypedControlCharacters () const
518 {
519 return fSuppressTypedControlCharacters;
520 }
521 inline void TextInteractor::SetSuppressTypedControlCharacters (bool suppressTypedControlCharacters)
522 {
523 fSuppressTypedControlCharacters = suppressTypedControlCharacters;
524 }
525 /*
526 @METHOD: TextInteractor::GetInteractiveUpdateMode
527 @DESCRIPTION: <p>See also @'TextInteractor::CheckIfCurrentUpdateIsInteractive'.
528 */
529 inline TextInteractor::InteractiveUpdadeMode TextInteractor::GetInteractiveUpdateMode () const
530 {
531 return fInteractiveUpdadeMode;
532 }
533 /*
534 @METHOD: TextInteractor::SetInteractiveUpdateMode
535 @DESCRIPTION: <p>See also @'TextInteractor::CheckIfCurrentUpdateIsInteractive'.
536 */
537 inline void TextInteractor::SetInteractiveUpdateMode (InteractiveUpdadeMode interactive)
538 {
539 fInteractiveUpdadeMode = interactive;
540 }
541 /*
542 @METHOD: TextInteractor::CheckIfCurrentUpdateIsInteractive
543 @DESCRIPTION: <p>See also @'TextInteractor::InteractiveUpdadeMode' and @'TextInteractor::SetInteractiveUpdateMode' ().
544 */
545 inline bool TextInteractor::CheckIfCurrentUpdateIsInteractive () const
546 {
547 // Interpret 'indeterminate' as NOT being interactive mode
548 return fInteractiveUpdadeMode == eInteractiveUpdateMode;
549 }
550 /*
551 @METHOD: TextInteractor::GetInternalizer
552 @DESCRIPTION:
553 */
554 inline shared_ptr<FlavorPackageInternalizer> TextInteractor::GetInternalizer () const
555 {
556 return fInternalizer;
557 }
558 /*
559 @METHOD: TextInteractor::SetInternalizer
560 @DESCRIPTION: <p>Calls @'TextInteractor::HookInternalizerChanged' whenever the internalizer changes. Can be a nullptr externalizer.</p>
561 */
562 inline void TextInteractor::SetInternalizer (const shared_ptr<FlavorPackageInternalizer>& i)
563 {
564 fInternalizer = i;
565 HookInternalizerChanged ();
566 }
567 /*
568 @METHOD: TextInteractor::GetExternalizer
569 @DESCRIPTION:
570 */
571 inline shared_ptr<FlavorPackageExternalizer> TextInteractor::GetExternalizer () const
572 {
573 return fExternalizer;
574 }
575 /*
576 @METHOD: TextInteractor::SetExternalizer
577 @DESCRIPTION: <p>Calls @'TextInteractor::HookExternalizerChanged' whenever the externalizer changes. Can be a nullptr externalizer.</p>
578 */
579 inline void TextInteractor::SetExternalizer (const shared_ptr<FlavorPackageExternalizer>& e)
580 {
581 fExternalizer = e;
582 HookExternalizerChanged ();
583 }
584 inline void TextInteractor::InvalidateScrollBarParameters_ ()
585 {
586 fScrollBarParamsValid = false;
587 }
588 inline void TextInteractor::UpdateScrollBars_ ()
589 {
590 fScrollBarParamsValid = true;
591 }
592 /*
593 @METHOD: TextInteractor::GetCaretShown
594 @DESCRIPTION: <p>Flag to control whether or not blinking caret is shown for this editor.
595 Typically it will be turned on when this widget gets the focus, and off when it
596 loses it. But that is the responsability of higher level software (subclasses).
597 </p>
598 <p>See also @'TextInteractor::GetCaretShownSituation' and @'TextInteractor::SetCaretShown'.</p>
599 */
600 inline bool TextInteractor::GetCaretShown () const
601 {
602 return (fCaretShown);
603 }
604 /*
605 @METHOD: TextInteractor::GetCaretShownAfterPos
606 @DESCRIPTION: <p>Given an empty selection, it seems pretty obvious where to place
607 the caret - right? NOT!!!</p>
608 <p>Remember that a selection position falls BETWEEN two characters. One
609 plausible definition is to use the RIGHT edge of the preceeding character.
610 Yet - ANOTHER plausible definition is to use the LEFT edge of the following
611 character. For some particular positions (notable the beginning and ends of
612 the text) or or the other of these definitions might not quite make sense.
613 But there are obvious definitions to take care of these special cases.</p>
614 <p>And - luckily - for the most part - these definitions coincide. But there
615 is at least one place which comes up (in normal editor usage - more in
616 fancy Led subclasses like LVEJ's side-by-side mode). In particular, when
617 the preceeding and following characters fall on different rows. In this
618 case, a hint is helpful in deciding which of the two approaches to use.</p>
619 <p>Many editors simply pick one approach or the other. Led did this for a while.
620 It always picked the leading edge of the following character. But now Led
621 has a option. When users change the selection by clicking, this option is
622 is automaticly set. And similarly when they use the arrow keys, or do other
623 editing operations. The set-method for this field is virtual, so subclassers
624 who prefer one definition over the other can OVERRIDE the set method to simply
625 force a particular value.</p>
626 <p>If GetCaretShownAfterPos is true, use the use the LHS of following character,
627 and if false, then the RHS of the preceeding character. So the after refers to which
628 character to use - the one before or after the given marker POS. The side of the charater is the opposite
629 of this value.</p>
630 */
631 inline bool TextInteractor::GetCaretShownAfterPos () const
632 {
633 return (fCaretShownAfterPos);
634 }
635 /*
636 @METHOD: TextInteractor::GetScrollBarType
637 @DESCRIPTION:
638 <p>See also 'TextInteractor::SetScrollBarType'</p>
639 */
640 inline TextInteractor::ScrollBarType TextInteractor::GetScrollBarType (VHSelect vh) const
641 {
642 return fScrollBarType[vh];
643 }
644 inline void TextInteractor::SetScrollBarType_ (VHSelect vh, ScrollBarType scrollBarType)
645 {
646 fScrollBarType[vh] = scrollBarType;
647 }
648 inline void TextInteractor::UpdateIfNoKeysPending ()
649 {
650 if (QueryInputKeyStrokesPending ()) {
651 // Note - this is NOT strictly necesary todo. But rather - its a performance hack. This call takes
652 // very little time, and it allows LATER optimizations (see TextInteractor::IsWholeWindowInvalid ());
653 // This was done in response to SPR#0659. I never measured exactly how much of a speedup it produced,
654 // but it eliminated stuff from my profiles so I went on to bigger things... LGP 991214
655 Refresh ();
656 }
657 else {
658 Update ();
659 }
660 }
661
662 // class TextInteractor::SearchParameters
663 inline TextInteractor::SearchParameters::SearchParameters ()
664 : fRecentFindStrings{}
665 {
666 }
667
668 // class TextInteractor::ReplaceParameters
669 inline TextInteractor::ReplaceParameters::ReplaceParameters ()
670 : fReplaceWith{}
671 {
672 }
673
674 // class TextInteractor::UndoableContextHelper
675 /*
676 @METHOD: TextInteractor::UndoableContextHelper::GetUndoRegionStart
677 @DESCRIPTION: <p>This method was formerly called 'GetSelStart'. However - this value - though originally based on the selection -
678 can be slightly different - especially in light of smart-cut-and-paste. It is the area that is being changed,
679 based on the users original selection.</p>
680 */
681 inline size_t TextInteractor::UndoableContextHelper::GetUndoRegionStart () const
682 {
683 return fSelStart;
684 }
685 /*
686 @METHOD: TextInteractor::UndoableContextHelper::GetUndoRegionEnd
687 @DESCRIPTION: <p>@'See @'TextInteractor::UndoableContextHelper::GetUndoRegionStart'</p>
688 */
689 inline size_t TextInteractor::UndoableContextHelper::GetUndoRegionEnd () const
690 {
691 return fSelEnd;
692 }
693 /*
694 @METHOD: TextInteractor::UndoableContextHelper::GetSimplePlainTextInsertOptimization
695 @DESCRIPTION: <p>@'See @'TextInteractor::UndoableContextHelper::SetSimplePlainTextInsertOptimization'</p>
696 */
697 inline bool TextInteractor::UndoableContextHelper::GetSimplePlainTextInsertOptimization () const
698 {
699 return fSimplePlainTextInsertOptimization;
700 }
701 /*
702 @METHOD: TextInteractor::UndoableContextHelper::SetSimplePlainTextInsertOptimization
703 @DESCRIPTION: <p>This should rarely be called. Its called internally just in the context where we are doing a special
704 form of text insert to create an optimized representation for undo information (in a common context).
705 </p>
706 <p>If this is to be called - it <em>must</em> be called before calling @'TextInteractor::UndoableContextHelper::CommandComplete'.</p>
707 <p>@'See also @'TextInteractor::UndoableContextHelper::GetSimplePlainTextInsertOptimization'</p>
708 */
709 inline void TextInteractor::UndoableContextHelper::SetSimplePlainTextInsertOptimization (bool simplePlainTextInsertOptimizationFlag)
710 {
711 fSimplePlainTextInsertOptimization = simplePlainTextInsertOptimizationFlag;
712 }
713
714 // class TextInteractor::TemporarilySetUpdateMode
715 inline TextInteractor::TemporarilySetUpdateMode::TemporarilySetUpdateMode (TextInteractor& ti, UpdateMode tmpUpdateMode)
716 : fTextInteractor (ti)
717 , fOldValue (ti.GetDefaultUpdateMode ())
718 {
719 fTextInteractor.SetDefaultUpdateMode (tmpUpdateMode);
720 }
721 inline TextInteractor::TemporarilySetUpdateMode::~TemporarilySetUpdateMode ()
722 {
723 fTextInteractor.SetDefaultUpdateMode (fOldValue);
724 }
725#endif
726
727}
#define AssertNotNull(p)
Definition Assertions.h:333
#define RequireNotNull(p)
Definition Assertions.h:347