OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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