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
pictval.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1993, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of TPXPictureValidator, Paradox-picture 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 <ctype.h>
16#include <stdio.h>
17
18namespace owl {
19
21
22
23//
24/// Constructs a picture validator object by first calling the constructor inherited
25/// from TValidator and setting pic to point to it. Then sets the voFill bit in
26/// Options if AutoFill is true and sets Options to voOnAppend. Throws a TXValidator
27/// exception if the picture is invalid.
28//
36
37//
38/// String-aware overload
39//
41:
42 TValidator(),
43 Pic(pic)
44{
45 Init(autoFill);
46}
47
48//
49/// Shared initialization
50//
51void TPXPictureValidator::Init(bool autoFill)
52{
54 if (autoFill)
55 Options |= voFill;
56 if (!SyntaxCheck())
58}
59
60//
61/// Overrides TValidator's virtual function and displays a message box that indicates
62/// an error in the picture format and displays the string pointed to by Pic.
63//
64void
66{
68 owner->FormatMessageBox(owner->LoadString(IDS_VALPXPCONFORM), owner->LoadString(IDS_VALCAPTION), MB_ICONERROR | MB_OK, Pic.c_str());
69}
70
71//
72/// IsValidInput overrides TValidator's virtual function and checks the string
73/// passed in str against the format picture specified in Pic. IsValid returns true
74/// if Pic is NULL or Picture does not return Error for str; otherwise, it returns
75/// false. The suppressFill parameter overrides the value in voFill for the duration
76/// of the call to IsValidInput.
77/// If suppressFill is false and voFill is set, the call to Picture returns a filled
78/// string based on str, so the image in the edit control automatically reflects the
79/// format specified in Pic.
80//
81bool
88
89//
90/// IsValid overrides TValidator's virtual function and compares the string passed
91/// in str with the format picture specified in Pic. IsValid returns true if Pic is
92/// NULL or if Picture returns Complete for str, indicating that str needs no
93/// further input to meet the specified format; otherwise, it returns false.
94//
95bool
97{
98 if (Pic.empty())
99 return true;
100
102 return rslt == prComplete || rslt == prEmpty;
103}
104
105//
106/// Adjusts the 'value' of the text, given a cursor position and an amount. Returns
107/// the actual amount adjusted.
108//
109int
110TPXPictureValidator::Adjust(tstring& /*text*/, int& /*begPos*/, int& /*endPos*/, int /*amount*/)
111{
112 return 0;
113}
114
115//
116//
117//
118inline bool
119TPXPictureValidator::IsComplete(TPicResult rslt)
120{
121 return rslt == prComplete || rslt == prAmbiguous;
122}
123
124//
125//
126//
127inline bool
128TPXPictureValidator::IsIncomplete(TPicResult rslt)
129{
130 return rslt == prIncomplete || rslt == prIncompNoFill;
131}
132
133//
134// Skip a character or a picture group
135//
136void
137TPXPictureValidator::ToGroupEnd(uint termCh, uint& i)
138{
139 int brkLevel = 0;
140 int brcLevel = 0;
141
142 do {
143 if (i == termCh)
144 return;
145 switch (Pic[i]) {
146 case _T('['): brkLevel++; break;
147 case _T(']'): brkLevel--; break;
148 case _T('{'): brcLevel++; break;
149 case _T('}'): brcLevel--; break;
150 case _T(';'): i++; break;
151 case _T('*'):
152 i++;
153 while (_istdigit((tchar)Pic[i]))
154 i++;
155 ToGroupEnd(termCh, i);
156 continue;
157 }
158 i += CharSize((LPCTSTR)Pic.c_str() + i) / sizeof(tchar);
159 } while (brkLevel || brcLevel);
160}
161
162//
163/// Find the next comma separator
164//
165bool
166TPXPictureValidator::SkipToComma(uint termCh, uint& i)
167{
168 for (;;) {
169 ToGroupEnd(termCh, i);
170 if (i == termCh)
171 return false;
172 if (Pic[i] == _T(',')) {
173 i++;
174 return i < termCh;
175 }
176 }
177}
178
179//
180/// Calculate the end of a group (does not modify i)
181//
182uint
183TPXPictureValidator::CalcTerm(uint termCh, uint i)
184{
185 ToGroupEnd(termCh, i);
186 return i;
187}
188
189//
190/// The next group is repeated X times
191//
193TPXPictureValidator::Iteration(LPTSTR input, uint termCh, uint& i, uint& j)
194{
197
198 i++; // Skip '*'
199
200 // Retrieve number
201
202 uint itr = 0;
203 for (; _istdigit((tchar)Pic[i]); i++)
204 itr = itr * 10 + Pic[i] - _T('0');
205
206 if (i >= termCh)
207 return prSyntax;
208
209 newTermCh = CalcTerm(termCh, i);
210
211 //
212 // if itr is 0 allow any number, otherwise enforce the number
213 //
214 uint k = i;
215 if (itr) {
216 for (uint m = 0; m < itr; m++) {
217 i = k;
218 rslt = Process(input, newTermCh, i, j);
219 if (!IsComplete(rslt)) {
220 if (rslt == prEmpty) // Empty means incomplete since all are required
222 return rslt;
223 }
224 }
225 }
226 else {
227 do {
228 i = k;
229 rslt = Process(input, newTermCh, i, j);
230 } while (IsComplete(rslt));
231 if (rslt == prEmpty || rslt == prError) {
232 i++;
234 }
235 }
236 i = newTermCh;
237 return rslt;
238}
239
240//
241/// Process a picture group
242//
244TPXPictureValidator::Group(LPTSTR input, uint termCh, uint& i, uint& j)
245{
246 uint groupTermCh = CalcTerm(termCh, i);
247 i++;
248 TPicResult rslt = Process(input, groupTermCh - 1, i, j);
249 if (!IsIncomplete(rslt))
250 i = groupTermCh;
251 return rslt;
252}
253
254//
255//
256//
258TPXPictureValidator::CheckComplete(uint termCh, uint& i, TPicResult rslt)
259{
260 uint j = i;
261 if (IsIncomplete(rslt)) {
262 // Skip optional pieces
263 for (;;) {
264 if (Pic[j] == _T('['))
265 ToGroupEnd(termCh, j);
266
267 else if (Pic[j] == _T('*')) {
268 if (!isdigit((tchar)Pic[j+1])) {
269 j++;
270 ToGroupEnd(termCh, j);
271 }
272 else
273 break;
274 }
275 else
276 break;
277
278 if (j == termCh)
279 return prAmbiguous; // end of the string, don't know if complete
280 }
281 }
282 return rslt;
283}
284
285//
286// Check for UNICODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
287//
288#if !defined(__GNUC__)
289#pragma warn -aus
290#endif
291
293TPXPictureValidator::Scan(LPTSTR input, uint termCh, uint& i, uint& j)
294{
295 tchar ch;
297
298 uint len = static_cast<uint>(::_tcslen(input));
299 while (i != termCh && Pic[i] != _T(',')) {
300 if (j >= len)
301 return CheckComplete(termCh, i, rslt);
302
303 ch = input[j];
304 switch (Pic[i]) {
305 case _T('#'):
306 if (!_istdigit((tchar)ch))
308 else {
309 input[j++] = ch;
310 i++;
311 }
312 break;
313 case _T('?'):
314 if (!_istalpha((tchar)ch))
316 else {
317 input[j++] = ch;
318 i++;
319 }
320 break;
321 case _T('&'):
322 if (!_istalpha((tchar)ch))
324 else {
325 input[j++] = (tchar)_totupper(ch);
326 i++;
327 }
328 break;
329 case _T('!'): {
330#if defined(BI_DBCS_SUPPORT)
331 uint n = CharSize(&input[j]) / sizeof(tchar);
332 if (j + n >= len)
333 j = len;
334 else{
335 if (n == 1)
336 input[j++] = (tchar)_totupper((tchar)ch);
337 else
338 j += n;
339 }
340#else
341 input[j++] = (tchar)_totupper(ch);
342#endif
343 i++;
344 break;
345 }
346 case _T('@'): {
347#if defined(BI_DBCS_SUPPORT)
348 uint n = CharSize(&input[j]) / sizeof(tchar);
349 if (j + n >= len)
350 j = len;
351 else
352 j += n;
353#else
354 input[j++] = ch;
355#endif
356 i++;
357 break;
358 }
359 case _T('*'):
360 rslt = Iteration(input, termCh, i, j);
361 if (!IsComplete(rslt))
362 return rslt;
363 if (rslt == prError)
365 break;
366 case _T('{'):
367 rslt = Group(input, termCh, i, j);
368 if (!IsComplete(rslt))
369 return rslt;
370 break;
371 case _T('['):
372 rslt = Group(input, termCh, i, j);
373 if (IsIncomplete(rslt))
374 return rslt;
375 if (rslt == prError)
377 break;
378 default: {
379#if defined(BI_DBCS_SUPPORT)
380#if defined(BI_PDOXWINJ_SUPPORT)
381 // Paradox for Windows/J database program has two special picture to
382 // support Japanese characters in CodePage 932
383 //
384 // '��' 0x81+0x93 - (2 byte '%' symbol)
385 // 1 byte KATAKANA and KATAKANA symbols (0xA1 - 0xDF)
386 // '��' 0x81+0x97 - (2 byte '@' symbol)
387 // any 2 byte characters except 2 byte space (0x81+0x40)
388 //
389 // This is hard coded, because we don't know how to get current
390 // code page in Windows 3.1
391 //
392 uint n = CharSize(&input[j]) / sizeof(tchar);
393 uint n2 = CharSize(((const char *))Pic.c_str() + i) / sizeof(tchar);
394 if (n2 == 2) {
395 utchar uc1, uc2;
396 uc1 = (utchar)Pic[i];
397 uc2 = (utchar)Pic[i+1];
398 if (uc1 == 0x81 && uc2 == 0x93) {
399 if ((utchar)ch >= 0xA1 && (utchar)ch <= 0xDF){
400 i += n2;
401 j += n;
402 break;
403 }
404 else
405 return prError;
406 }
407 else if (uc1 == 0x81 && uc2 == 0x97){
408 if (n == 2 && j + n < len &&
409 ((utchar)ch != 0x81 || (utchar)input[j+1] != 0x40)) {
410 i += n2;
411 j += n;
412 break;
413 } else
414 return prError;
415 }
416 }
417 if (n2 == 1 && Pic[i] == ';'){
418 i++;
419 n2 = CharSize((const char *)Pic.c_str() + i) / sizeof(tchar);
420 }
421#else
422 if (Pic[i] == _T(';'))
423 i++;
424 uint n = CharSize(&input[j]) / sizeof(tchar);
425 uint n2 = CharSize((LPCTSTR)Pic.c_str() + i) / sizeof(tchar);
426#endif
427 if (j + n >= len)
428 n = len - j;
429 if (n == 1) {
430 if (ch == _T(' ')) {
431#if defined(BI_AUTO_COMPLETION_DBCS_BY_SPACE)
432// But, couldn't expand input buffer TValidator classes.
433//
434 if (n < n2) {
435 memmove(input+n2, input+n, len-n+1);
436 len += n2 - n;
437 n = n2;
438 }
439 while (n-- > 0)
440 input[j++] = Pic[i++];
441#else
442 if (n != n2)
443 return prError;
444 input[j++] = Pic[i++];
445#endif
446 }
447 else {
448 if (n != n2)
449 return prError;
450 if (_totupper((tchar)Pic[i]) != _totupper((tchar)ch))
451 return prError;
452 input[j++] = Pic[i++];
453 }
454 }
455 else {
456 if (n > n2)
457 return prError;
458 for (uint i1 = 0; i1 < n; i1++)
459 if (input[j+i1] != Pic[i+i1])
460 return prError;
461 while (n-- > 0)
462 input[j++] = Pic[i++];
463 }
464#else
465 if (Pic[i] == _T(';'))
466 i++;
467 if (_totupper(Pic[i]) != _totupper(ch))
468 {
469 if (ch == _T(' '))
470 ch = Pic[i];
471 else
472 return prError;
473 }
474 input[j++] = Pic[i];
475 i++;
476#endif
477 }
478 }
479 if (rslt == prAmbiguous)
481 else
483 }
484
486}
487#if !defined(__GNUC__)
488#pragma warn .aus
489#endif
490
491//
492//
493//
495TPXPictureValidator::Process(LPTSTR input, uint termCh, uint& i, uint& j)
496{
499 incompJ = incompI = 0;
500
501 bool incomp = false;
502 uint oldI = i;
503 uint oldJ = j;
504 do {
505 rslt = Scan(input, termCh, i, j);
506
507 //
508 // Only accept completes if they make it farther in the input
509 // stream from the last incomplete
510 //
511 if ((rslt==prComplete || rslt==prAmbiguous) && incomp && j < incompJ) {
513 j = incompJ;
514 }
515
516 if (rslt == prError || rslt == prIncomplete) {
517 if (!incomp && rslt == prIncomplete) {
518 incomp = true;
519 incompI = i;
520 incompJ = j;
521 }
522 i = oldI;
523 j = oldJ;
524 if (!SkipToComma(termCh, i)) {
525 if (incomp) {
526 i = incompI;
527 j = incompJ;
528 return prIncomplete;
529 }
530 return rslt;
531 }
532 oldI = i;
533 }
534 } while (rslt == prError || rslt == prIncomplete);
535
536 return (rslt == prComplete && incomp) ? prAmbiguous : rslt;
537}
538
539//
540//
541//
542bool
543TPXPictureValidator::SyntaxCheck()
544{
545 const auto n = static_cast<int>(Pic.length());
546 if (Pic.empty() ||
547 (Pic.back() == _T(';')) ||
548 (Pic.back() == _T('*') && Pic[n - 2] != _T(';')))
549 {
550 return false;
551 }
552
553 auto brkLevel = 0;
554 auto brcLevel = 0;
555 auto next = [&](int& i) { i += CharSize(&Pic[i]) / sizeof(tchar); };
556 for (auto i = 0; i < n; next(i))
557 {
558 switch (Pic[i])
559 {
560 case _T('['): ++brkLevel; break;
561 case _T(']'): --brkLevel; break;
562 case _T('{'): ++brcLevel; break;
563 case _T('}'): --brcLevel; break;
564 case _T(';'): next(i); break;
565 case _T('*'):
566 next(i);
567 if (!_istdigit(Pic[i]))
568 return false;
569 break;
570 }
571 }
572 return brkLevel == 0 && brcLevel == 0;
573}
574
575
576#if defined(BI_DBCS_SUPPORT)
577#if defined(BI_PDOXWINJ_SUPPORT)
578namespace {
580 {
581 uint n2 = CharSize(s2) / sizeof(tchar);
582 do {
583 uint n1 = CharSize(s1) / sizeof(tchar);
584 if (n1 == n2 && memcmp(s1, s2, n1) == 0)
585 return (char *)s1;
586 for ( ; n1-- > 0; s1++)
587 if( !*s1 )
588 break;
589 } while (*s1) ;
590 return (char *)NULL;
591 }
592}
593#endif
594#endif
595
596//
597/// Checks the validity of the input according to the format specified by the
598/// picture string, possibly adding fill characters to the end of the input.
599//
600/// Formats the string passed in input according to the format specified by the
601/// picture string pointed to by Pic. Picture returns prError if there is an error
602/// in the picture string or if input contains data that cannot fit the specified
603/// picture. Returns prComplete if input can fully satisfy the specified picture.
604/// Returns prIncomplete if input contains data that incompletely fits the specified
605/// picture.
606//
607/// The following characters are used in creating format pictures:
608///
609/// Special
610/// - \b # Accept only a digit
611/// - \b ? Accept only a letter (case_insensitive)
612/// - \b & Accept only a letter, force to uppercase
613/// - \b @ Accept any character
614/// - \b ! Accept any character, force to uppercase
615/// Match
616/// - \b ; Take next character literally
617/// - \b * Repetition count
618/// - \b [] Option
619/// - \b {} Grouping operators
620/// - \b , Set of alternatives
621/// - All others Taken literally
622//
625{
626 // Check if any input data.
627 //
628 if (!input || !*input)
629 return prEmpty;
630
631 // Indexes for Pic[] and input[].
632 //
633 uint iPic = 0;
634 uint iInput = 0;
635
636 // Process the given input to check for an error.
637 //
638 TPicResult rslt = Process(input, static_cast<uint>(Pic.length()), iPic, iInput);
639
640 if ((rslt != prError) && (rslt != prSyntax) && (iInput < ::_tcslen(input)))
641 rslt = prError;
642
643 // If the result is incomplete and autofill is requested, then copy literal
644 // characters from the picture over to the input.
645 //
646 if ((rslt == prIncomplete) && autoFill) {
647 bool reprocess = false;
648
649#if defined(BI_PDOXWINJ_SUPPORT)
650 // "����"
651 while (iPic < Pic.length() && !lstrchrp("#?&!@*{}[],\x81\x93\x81\x97", (LPCSTR)Pic.c_str() + iPic))
652#else
653 while (iPic < Pic.length() && !_tcschr(_T("#?&!@*{}[],"), Pic[iPic]))
654#endif
655 {
656 if (Pic[iPic] == _T(';'))
657 iPic++;
658#if defined(BI_DBCS_SUPPORT)
659 uint k = static_cast<uint>(::_tcslen(input));
660 uint n = CharSize((LPCTSTR)Pic.c_str() + iPic) / sizeof(tchar);
661 memmove(input + k, Pic.c_str() + iPic, n);
662 input[k + n] = _T('\0');
663 iPic += n;
664 iInput += n;
665#else
666 input[iInput++] = Pic[iPic++];
667#endif
668 reprocess = true;
669 }
670 if (reprocess)
671 {
672 input[iInput] = _T('\0'); // Terminate the copy, since we are probably appending
673 iInput = iPic = 0;
674 rslt = Process(input, static_cast<uint>(Pic.length()), iPic, iInput);
675 }
676 }
677
678 // We perform an additional check here because SyntaxCheck may not catch them
679 // all with it using different logic.
680 //
681 if (rslt == prSyntax)
683
685
686}
687
688
690
691#if OWL_PERSISTENT_STREAMS
692
693//
694//
695//
696void*
697TPXPictureValidator::Streamer::Read(ipstream& is, uint32 /*version*/) const
698{
699 ReadBaseObject((TValidator*)GetObject(), is);
700 is >> GetObject()->Pic;
701 return GetObject();
702}
703
704//
705//
706//
707void
708TPXPictureValidator::Streamer::Write(opstream& os) const
709{
710 WriteBaseObject((TValidator*)GetObject(), os);
711 os << GetObject()->Pic;
712}
713
714#endif
715
716} // OWL namespace
Definition of class TAppDictionary.
Definition of class TApplication.
#define PRECONDITION(condition)
Definition checks.h:227
TPXPictureValidator objects compare user input with a picture of a data format to determine the valid...
Definition validate.h:145
int Adjust(tstring &text, int &begPos, int &endPos, int amount)
Adjusts the 'value' of the text, given a cursor position and an amount.
Definition pictval.cpp:110
virtual TPicResult Picture(TCHAR *input, bool autoFill=false)
Checks the validity of the input according to the format specified by the picture string,...
Definition pictval.cpp:624
TPXPictureValidator(LPCTSTR pic, bool autoFill=false)
Constructs a picture validator object by first calling the constructor inherited from TValidator and ...
Definition pictval.cpp:29
bool IsValid(LPCTSTR str)
IsValid overrides TValidator's virtual function and compares the string passed in str with the format...
Definition pictval.cpp:96
void Error(TWindow *owner)
Overrides TValidator's virtual function and displays a message box that indicates an error in the pic...
Definition pictval.cpp:65
bool IsValidInput(TCHAR *str, bool suppressFill)
IsValidInput overrides TValidator's virtual function and checks the string passed in str against the ...
Definition pictval.cpp:82
A streamable class, TValidator defines an abstract data validation object.
Definition validate.h:71
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
static void Raise()
Creates an instance of TXValidator and throws it.
Definition validate.cpp:165
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition objstrm.h:391
#define _istdigit
Definition cygwin.h:70
#define _istalpha
Definition cygwin.h:71
#define _totupper
Definition cygwin.h:73
#define _tcslen
Definition cygwin.h:74
#define _T(x)
Definition cygwin.h:51
#define _tcschr
Definition cygwin.h:85
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
TPicResult
Validation result type.
Definition validate.h:128
@ voOnAppend
Option to only validate input on appending.
Definition validate.h:43
@ voFill
Option to fill in chars on IsValidInput checks.
Definition validate.h:35
@ prEmpty
Definition validate.h:131
@ prAmbiguous
Definition validate.h:134
@ prError
Definition validate.h:132
@ prComplete
Definition validate.h:129
@ prIncomplete
Definition validate.h:130
@ prSyntax
Definition validate.h:133
@ prIncompNoFill
Definition validate.h:135
UINT CharSize(const TCHAR *s)
Return the number of bytes of the first character of the passed string.
Definition memory.h:56
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
unsigned long uint32
Definition number.h:34
char tchar
Definition defs.h:77
OWL_DIAGINFO
Definition animctrl.cpp:14
std::string tstring
Definition defs.h:79
unsigned int uint
Definition number.h:25
unsigned char utchar
Definition defs.h:78
#define CONST_CAST(targetType, object)
Definition defs.h:273