OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
rangeval.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1992, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of TRangeValidator, integer numeric range input validator
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9
10#include <owl/validate.h>
11#include <owl/validate.rh>
12#include <owl/applicat.h>
13#include <owl/appdict.h>
14#include <owl/framewin.h>
15#include <algorithm>
16
17namespace owl {
18
20
21//
22/// Constructs a range validator object by first calling the constructor inherited
23/// from TFilterValidator, passing a set of characters containing the digits
24/// '0'..'9' and the characters '+' and '-'. Sets Range establishing the range of
25/// acceptable long integer values.
26//
28:
29 TFilterValidator(_T("0-9+-"))
30{
31 SetRange(range);
32}
33
34//
35/// Overrides TValidator's virtual function and displays a message box indicating
36/// that the entered value does not fall within the specified range.
37//
38void
40{
42 owner->FormatMessageBox(owner->LoadString(IDS_VALNOTINRANGE), owner->LoadString(IDS_VALCAPTION), MB_ICONERROR | MB_OK, Range.Min, Range.Max);
43}
44
45//
46// Hide the internal helper functions so they are excluded from public view by
47// using an unnamed namespace.
48//
49namespace
50{
51
52 //
53 // Parses the given stream, expecting it to contain only a single valid integer value.
54 // On success, returns the converted integer value. On failure, sets the `failbit` state of the
55 // given stream and returns 0, unless exceptions are enabled for the stream, in which case an
56 // exception will be thrown (see std::ios_base::exceptions).
57 //
59 {
61 is >> value;
62
63 // Allow trailing whitespace, but no other trailing content.
64 //
65 if (!is.fail() && !is.eof())
66 {
67 is >> std::ws;
68 if (!is.eof())
69 {
70 value = 0;
71 is.setstate(is.failbit);
72 }
73 }
74 return value;
75 }
76
77}
78
79namespace
80{
81
82 //
83 // Ensures that proper magnitude signs are allowed/disallowed based on the range.
84 //
85 void ValidateMagnitudeFilter_(const TRangeValidator::TRange& range, TCharSet& validChars)
86 {
87 auto minus = _T('-');
88 auto plus = _T('+');
89 auto hasMinus = validChars.Has(minus);
90 auto hasPlus = validChars.Has(plus);
91
92 // Add or remove minus sign as needed based on range.Min value.
93 //
94 if ((range.Min < 0) != hasMinus)
95 {
96 if (hasMinus)
98 else
100 }
101
102 // Add or remove plus sign as needed based on range.Max value.
103 //
104 if ((range.Max > 0) != hasPlus)
105 {
106 if (hasPlus)
107 validChars -= plus;
108 else
109 validChars += plus;
110 }
111 }
112
113 //
114 // Ensures that `range.Min` is less than `range.Max`; if not, swaps the values.
115 // Calls ValidateMagnitudeFilter_ to ensure necessary magnitude signs are
116 // available characters.
117 //
118 void ValidateRange_(TRangeValidator::TRange& range, TCharSet& validChars)
119 {
120 WARN(range.Min > range.Max, _T("TRangeValidator has a minimum value of ") << range.Min
121 << _T(" that is greater than the maximum value of ") << range.Max
122 << _T("; swapped values will be used."));
123 std::sort(&range.Min, &range.Max + 1);
125 }
126
127} // namespace
128
129//
130/// Sets the minimum number the validator can accept.
131//
132/// We can't validate the range here, because of the asynchronous manner in
133/// which SetMin and SetMax could be called might have Range.Min greater
134/// than Range.Max.
135//
137{
138 Range.Min = minValue;
139 ValidateMagnitudeFilter_(Range, ValidChars);
140}
141
142//
143/// Sets the maximum number the validator can accept.
144//
145/// We can't validate the range here, because of the asynchronous manner in
146/// which SetMin and SetMax could be called might have Range.Min greater
147/// than Range.Max.
148//
150{
151 Range.Max = maxValue;
152 ValidateMagnitudeFilter_(Range, ValidChars);
153}
154
155//
156/// Sets the minimum and maximum number the validator can accept.
157//
159{
160 Range = range;
161 ValidateRange_(Range, ValidChars);
162}
163
164//
165/// We first validate the range, because of the asynchronous manner in which SetMin
166/// and SetMax could be called might have Min greater than Max.
167//
168/// If the given string is empty or blank (all white-space), returns true.
169/// Otherwise, converts the string str into an integer number and returns true if the result
170/// meets all three of these conditions:
171/// - It is a valid integer number.
172/// - Its value is greater than or equal to Min.
173/// - Its value is less than or equal to Max.
174/// If any of those tests fails, IsValid returns false.
175//
176bool
178{
179 PRECONDITION(s);
181 return false;
182
183 ValidateRange_(Range, ValidChars);
184 auto is = tistringstream{s};
185 is >> std::ws;
186 if (is.eof())
187 return true; // Empty/blank input is allowed.
188
189 const auto value = ParseInteger_(is);
190 return !is.fail() && value >= Range.Min && value <= Range.Max;
191}
192
193//
194/// Incorporates the three types, tdSizeData, tdGetData, and tdSetData, that a range
195/// validator can handle for its associated edit control. The parameter str is the
196/// edit control's string value, and buffer is the data passed to the edit control.
197/// Depending on the value of direction, Transfer either sets str from the number in
198/// buffer or sets the number at buffer to the value of the string str. If direction
199/// is tdSetData, Transfer sets str from buffer. If direction is tdGetData, Transfer
200/// sets buffer from str. If direction is tdSizeData, Transfer neither sets nor
201/// reads data.
202/// Transfer always returns the size of the data transferred.
203//
204uint
206{
207 if (Options & voTransfer) {
208 if (!buffer && direction != tdSizeData) return 0;
209 if (direction == tdGetData) {
210 auto is = tistringstream{s};
211 const auto value = ParseInteger_(is);
212 WARN(is.fail(), _T("ParseInteger_ failed"));
213 *(TExtent*)buffer = value;
214 }
215 else if (direction == tdSetData) {
216 wsprintf(s, _T("%ld"), *(TExtent*)buffer); // need wsprintf for char *
217 }
218 return sizeof(TExtent);
219 }
220 else
221 return 0;
222}
223
224//
225/// We first validate the range, because of the asynchronous manner in which SetMin
226/// and SetMax could be called might have Min greater than Max.
227//
228/// Adjusts the 'value' of the text, given a cursor position and an amount. Returns
229/// the actual amount adjusted.
230//
231int
232TRangeValidator::Adjust(tstring& text, int& /*begPos*/, int& /*endPos*/, int amount)
233{
234 auto clamp = [](TExtent e, const TRange& r)
235 { return e < r.Min ? r.Min : e > r.Max ? r.Max : e; };
236
237 ValidateRange_(Range, ValidChars);
238 auto is = tistringstream{text};
239 const auto value = ParseInteger_(is);
240 WARN(is.fail(), _T("ParseInteger_ failed"));
241 const auto newValue = clamp(value + amount, Range);
243 return newValue - value;
244}
245
247
248#if OWL_PERSISTENT_STREAMS
249
250//
251/// Reads an instance of TRangeValidator from the given ipstream.
252//
253void*
254TRangeValidator::Streamer::Read(ipstream& is, uint32 /*version*/) const
255{
256 ReadBaseObject((TFilterValidator*)GetObject(), is);
257 is >> GetObject()->Range.Min >> GetObject()->Range.Max;
258 return GetObject();
259}
260
261//
262/// Writes the TRangeValidator to the given opstream.
263//
264void
265TRangeValidator::Streamer::Write(opstream& os) const
266{
267 WriteBaseObject((TFilterValidator*)GetObject(), os);
268 os << GetObject()->Range.Min << GetObject()->Range.Max;
269}
270
271#endif
272
273} // OWL namespace
Definition of class TAppDictionary.
Definition of class TApplication.
#define WARN(condition, message)
Definition checks.h:273
#define PRECONDITION(condition)
Definition checks.h:227
A streamable class, TFilterValidator checks an input field as the user types into it.
Definition validate.h:194
bool IsValid(LPCTSTR str)
IsValid overrides TValidator's virtuals and returns true if all characters in str are in the set of a...
Definition filtval.cpp:59
Determines whether the data typed by a user falls within a designated range of integers.
Definition validate.h:225
void SetMax(TExtent maxValue)
Sets the maximum number the validator can accept.
Definition rangeval.cpp:149
bool IsValid(LPCTSTR str)
We first validate the range, because of the asynchronous manner in which SetMin and SetMax could be c...
Definition rangeval.cpp:177
void Error(TWindow *owner)
Overrides TValidator's virtual function and displays a message box indicating that the entered value ...
Definition rangeval.cpp:39
int Adjust(tstring &text, int &begPos, int &endPos, int amount)
We first validate the range, because of the asynchronous manner in which SetMin and SetMax could be c...
Definition rangeval.cpp:232
TRangeValidator(TExtent minValue, TExtent maxValue)
Constructs a range validator object using minValue and maxValue as the range of possible values.
Definition validate.h:415
void SetRange(const TRange &range)
Sets the minimum and maximum number the validator can accept.
Definition rangeval.cpp:158
uint Transfer(TCHAR *str, void *buffer, TTransferDirection direction)
Incorporates the three types, tdSizeData, tdGetData, and tdSetData, that a range validator can handle...
Definition rangeval.cpp:205
void SetMin(TExtent minValue)
Sets the minimum number the validator can accept.
Definition rangeval.cpp:136
uint16 Options
A bitmap member used to control options for various descendants of TValidator.
Definition validate.h:94
TWindow, derived from TEventHandler and TStreamableBase, provides window-specific behavior and encaps...
Definition window.h:414
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition objstrm.h:391
#define _T(x)
Definition cygwin.h:51
Definition of class TFrameWindow.
void ReadBaseObject(Base *base, ipstream &in)
Definition objstrm.h:1159
#define IMPLEMENT_STREAMABLE1(cls, base1)
Definition objstrm.h:1725
void WriteBaseObject(Base *base, opstream &out)
Definition objstrm.h:1150
@ voTransfer
Option to perform conversion & transfer.
Definition validate.h:39
TTransferDirection
The TTransferDirection enum describes the constants that the transfer function uses to determine how ...
Definition window.h:92
@ tdSizeData
Return the size of data transferred by the class.
Definition window.h:95
@ tdSetData
Set data from the buffer into the window.
Definition window.h:94
@ tdGetData
Get data from the window into the buffer.
Definition window.h:93
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
unsigned long uint32
Definition number.h:34
char tchar
Definition defs.h:77
std::istringstream tistringstream
Definition strmdefs.h:37
OWL_DIAGINFO
Definition animctrl.cpp:14
std::istream tistream
Definition strmdefs.h:39
std::string tstring
Definition defs.h:79
unsigned int uint
Definition number.h:25
auto to_tstring(const T &v) -> tstring
Definition defs.h:82