home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / PICTVAL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  9.8 KB  |  436 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1993, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of TPXPictureValidator, Paradox-picture input validator
  6. //----------------------------------------------------------------------------
  7. #pragma hdrignore SECTION
  8. #include <owl/owlpch.h>
  9. #include <owl/validate.h>
  10. #include <owl/applicat.h>
  11. #include <owl/appdict.h>
  12. #include <owl/framewin.h>
  13. #include <ctype.h>
  14.  
  15. #if !defined(SECTION) || SECTION == 1
  16.  
  17. TPXPictureValidator::TPXPictureValidator(const char far* pic, bool autoFill)
  18. :
  19.   TValidator(),
  20.   Pic(pic)
  21. {
  22.   Options = voOnAppend;
  23.   if (autoFill)
  24.     Options |= voFill;
  25.   if (Picture(0, false) != prEmpty)
  26.     THROW( TValidator::TXValidator() );
  27. }
  28.  
  29. void
  30. TPXPictureValidator::Error()
  31. {
  32.   TApplication* app = GetApplicationObject();
  33.   string msgTmpl = app->LoadString(IDS_VALPXPCONFORM).c_str();
  34.   char* msg = new char[msgTmpl.length() + Pic.length() + 1];
  35.   wsprintf(msg, msgTmpl.c_str(), (const char far*)Pic.c_str());
  36.   TWindow* w = GetWindowPtr(app->GetMainWindow()->GetLastActivePopup());
  37.   if (w)
  38.     w->MessageBox(msg, app->GetName(), MB_ICONEXCLAMATION|MB_OK);
  39.   else
  40.     ::MessageBox(0, msg, app->GetName(), MB_ICONEXCLAMATION|MB_OK|MB_TASKMODAL);
  41.   delete [] msg;
  42. }
  43.  
  44. bool
  45. TPXPictureValidator::IsValidInput(char far* str, bool suppressFill)
  46. {
  47.   bool autoFill = (Options&voFill) && !suppressFill;
  48.   return Pic.is_null() || Picture(str, autoFill) != prError;
  49. }
  50.  
  51. bool
  52. TPXPictureValidator::IsValid(const char far* str)
  53. {
  54.   if (Pic.is_null())
  55.     return true;
  56.   TPicResult rslt = Picture((char far*)str, false);
  57.   return rslt == prComplete || rslt == prEmpty;
  58. }
  59.  
  60. inline bool
  61. TPXPictureValidator::IsComplete(TPicResult rslt)
  62. {
  63.   return rslt == prComplete || rslt == prAmbiguous;
  64. }
  65.  
  66. inline bool
  67. TPXPictureValidator::IsIncomplete(TPicResult rslt)
  68. {
  69.   return rslt == prIncomplete || rslt == prIncompNoFill;
  70. }
  71.  
  72. //
  73. // Skip a character or a picture group
  74. //
  75. void
  76. TPXPictureValidator::ToGroupEnd(uint termCh, uint& i)
  77. {
  78.   int brkLevel = 0;
  79.   int brcLevel = 0;
  80.  
  81.   do {
  82.     if (i == termCh)
  83.       return;
  84.     switch (Pic[i]) {
  85.       case '[': brkLevel++; break;
  86.       case ']': brkLevel--; break;
  87.       case '{': brcLevel++; break;
  88.       case '}': brcLevel--; break;
  89.       case ';': i++; break;
  90.       case '*':
  91.         i++;
  92.         while (isdigit(Pic[i]))
  93.           i++;
  94.         ToGroupEnd(termCh, i);
  95.         continue;
  96.     }
  97.     i++;
  98.   } while (brkLevel || brcLevel);
  99. }
  100.  
  101. //
  102. // Find the next comma separator
  103. //
  104. bool
  105. TPXPictureValidator::SkipToComma(uint termCh, uint& i)
  106. {
  107.   for (;;) {
  108.     ToGroupEnd(termCh, i);
  109.     if (i == termCh)
  110.       return false;
  111.     if (Pic[i] == ',') {
  112.       i++;
  113.       return i < termCh;
  114.     }
  115.   }
  116. }
  117.  
  118. //
  119. // Calculate the end of a group (does not modify i)
  120. //
  121. uint
  122. TPXPictureValidator::CalcTerm(uint termCh, uint i)
  123. {
  124.   ToGroupEnd(termCh, i);
  125.   return i;
  126. }
  127.  
  128. //
  129. // The next group is repeated X times
  130. //
  131. TPicResult
  132. TPXPictureValidator::Iteration(char far* input, uint termCh, uint& i, uint& j)
  133. {
  134.   TPicResult rslt;
  135.   uint newTermCh;
  136.  
  137.   i++;  // Skip '*'
  138.  
  139.   // Retrieve number
  140.  
  141.   uint itr = 0;
  142.   for (; isdigit(Pic[i]); i++)
  143.     itr = itr * 10 + Pic[i] - '0';
  144.  
  145.   if (i >= termCh)
  146.     return prSyntax;
  147.  
  148.   newTermCh = CalcTerm(termCh, i);
  149.  
  150.   //
  151.   // if itr is 0 allow any number, otherwise enforce the number
  152.   //
  153.   uint k = i;
  154.   if (itr) {
  155.     for (int m = 0; m < itr; m++) {
  156.       i = k;
  157.       rslt = Process(input, newTermCh, i, j);
  158.       if (!IsComplete(rslt)) {
  159.         if (rslt == prEmpty)  // Empty means incomplete since all are required
  160.           rslt = prIncomplete;
  161.         return rslt;
  162.       }
  163.     }
  164.   }
  165.   else {
  166.     do {
  167.       i = k;
  168.       rslt = Process(input, newTermCh, i, j);
  169.     } while (IsComplete(rslt));
  170.     if (rslt == prEmpty || rslt == prError) {
  171.       i++;
  172.       rslt = prAmbiguous;
  173.     }
  174.   }
  175.   i = newTermCh;
  176.   return rslt;
  177. }
  178.  
  179. //
  180. // Process a picture group
  181. //
  182. TPicResult
  183. TPXPictureValidator::Group(char far* input, uint termCh, uint& i, uint& j)
  184. {
  185.   uint groupTermCh = CalcTerm(termCh, i);
  186.   i++;
  187.   TPicResult rslt = Process(input, groupTermCh - 1, i, j);
  188.   if (!IsIncomplete(rslt))
  189.     i = groupTermCh;
  190.   return rslt;
  191. }
  192.  
  193. //
  194. //
  195. //
  196. TPicResult
  197. TPXPictureValidator::CheckComplete(uint termCh, uint& i, TPicResult rslt)
  198. {
  199.   uint j = i;
  200.   if (IsIncomplete(rslt)) {
  201.     // Skip optional pieces
  202.     for (;;) {
  203.       if (Pic[j] == '[')
  204.         ToGroupEnd(termCh, j);
  205.  
  206.       else if (Pic[j] == '*') {
  207.         if (!isdigit(Pic[j+1])) {
  208.           j++;
  209.           ToGroupEnd(termCh, j);
  210.         }
  211.         else
  212.           break;
  213.       }
  214.       else
  215.         break;
  216.  
  217.       if (j == termCh)
  218.         return prAmbiguous;  // end of the string, don't know if complete
  219.     }
  220.   }
  221.   return rslt;
  222. }
  223.  
  224. TPicResult
  225. TPXPictureValidator::Scan(char far* input, uint termCh, uint& i, uint& j)
  226. {
  227.   char ch;
  228.   TPicResult rslt = prEmpty;
  229.  
  230.   unsigned len = strlen(input);
  231.   while (i != termCh && Pic[i] != ',') {
  232.     if (j >= len)
  233.       return CheckComplete(termCh, i, rslt);
  234.  
  235.     ch = input[j];
  236.     switch (Pic[i]) {
  237.       case '#':
  238.         if (!isdigit(ch))
  239.           return prError;
  240.         else {
  241.           input[j++] = ch;
  242.           i++;
  243.         }
  244.         break;
  245.       case '?':
  246.         if (!isalpha(ch))
  247.           return prError;
  248.         else {
  249.           input[j++] = ch;
  250.           i++;
  251.         }
  252.         break;
  253.       case '&':
  254.         if (!isalpha(ch))
  255.           return prError;
  256.         else {
  257.           input[j++] = (char)toupper(ch);
  258.           i++;
  259.         }
  260.         break;
  261.       case '!':
  262.         input[j++] = (char)toupper(ch);
  263.         i++;
  264.         break;
  265.       case '@':
  266.         input[j++] = ch;
  267.         i++;
  268.         break;
  269.       case '*':
  270.         rslt = Iteration(input, termCh, i, j);
  271.         if (!IsComplete(rslt))
  272.           return rslt;
  273.         if (rslt == prError)
  274.           rslt = prAmbiguous;
  275.         break;
  276.       case '{':
  277.         rslt = Group(input, termCh, i, j);
  278.         if (!IsComplete(rslt))
  279.           return rslt;
  280.         break;
  281.       case '[':
  282.         rslt = Group(input, termCh, i, j);
  283.         if (IsIncomplete(rslt))
  284.           return rslt;
  285.         if (rslt == prError)
  286.           rslt = prAmbiguous;
  287.         break;
  288.       default:
  289.         if (Pic[i] == ';')
  290.           i++;
  291.         if (toupper(Pic[i]) != toupper(ch))
  292.           if (ch == ' ')
  293.             ch = Pic[i];
  294.           else
  295.             return prError;
  296.         input[j++] = Pic[i];
  297.         i++;
  298.     }
  299.     if (rslt == prAmbiguous)
  300.       rslt = prIncompNoFill;
  301.     else
  302.       rslt = prIncomplete;
  303.   }
  304.  
  305.   return (rslt == prIncompNoFill) ? prAmbiguous : prComplete;
  306. }
  307.  
  308. TPicResult
  309. TPXPictureValidator::Process(char far* input, uint termCh, uint& i, uint& j)
  310. {
  311.   TPicResult rslt;
  312.   uint incompJ, incompI;
  313.   incompJ = incompI = 0;
  314.  
  315.   bool incomp = false;
  316.   uint oldI = i;
  317.   uint oldJ = j;
  318.   do {
  319.     rslt = Scan(input, termCh, i, j);
  320.  
  321.     //
  322.     // Only accept completes if they make it farther in the input
  323.     // stream from the last incomplete
  324.     //
  325.     if ((rslt==prComplete || rslt==prAmbiguous) && incomp && j < incompJ) {
  326.       rslt = prIncomplete;
  327.       j = incompJ;
  328.     }
  329.  
  330.     if (rslt == prError || rslt == prIncomplete) {
  331.       if (!incomp && rslt == prIncomplete) {
  332.         incomp = true;
  333.         incompI = i;
  334.         incompJ = j;
  335.       }
  336.       i = oldI;
  337.       j = oldJ;
  338.       if (!SkipToComma(termCh, i)) {
  339.         if (incomp) {
  340.           i = incompI;
  341.           j = incompJ;
  342.           return prIncomplete;
  343.         }
  344.         return rslt;
  345.       }
  346.       oldI = i;
  347.     }
  348.   } while (rslt == prError || rslt == prIncomplete);
  349.  
  350.   return (rslt == prComplete && incomp) ? prAmbiguous : rslt;
  351. }
  352.  
  353. bool
  354. TPXPictureValidator::SyntaxCheck()
  355. {
  356.   if (Pic.is_null())
  357.     return false;
  358.   if (Pic[Pic.length()-1] == ';')
  359.     return false;
  360.   if (Pic[Pic.length()-1] == '*' && Pic[Pic.length()-2] != ';')
  361.     return false;
  362.  
  363.   int brkLevel = 0;
  364.   int brcLevel = 0;
  365.   for (int i = 0; i < Pic.length(); i++) {
  366.     switch (Pic[i]) {
  367.       case '[': brkLevel++; break;
  368.       case ']': brkLevel--; break;
  369.       case '{': brcLevel++; break;
  370.       case '}': brcLevel--; break;
  371.       case ';': i++;
  372.     }
  373.   }
  374.   return !(brkLevel || brcLevel);
  375. }
  376.  
  377. TPicResult
  378. TPXPictureValidator::Picture(char far* input, bool autoFill)
  379. {
  380.   if (!SyntaxCheck())
  381.     return prSyntax;
  382.   if (!input || !*input)
  383.     return prEmpty;
  384.  
  385.   uint j = 0;  // index for input[]
  386.   uint i = 0;  // index for Pic[]
  387.  
  388.   TPicResult rslt = Process(input, Pic.length(), i, j);
  389.   if (rslt != prError && rslt != prSyntax && j < strlen(input))
  390.     rslt = prError;
  391.  
  392.   // If the result is incomplete & autofill is requested, then copy literal
  393.   // characters from the picture over to the input.
  394.   //
  395.   if (rslt == prIncomplete && autoFill) {
  396.     bool  reprocess = false;
  397.     while (i < Pic.length() && !strchr("#?&!@*{}[],", Pic[i])) {
  398.       if (Pic[i] == ';')
  399.         i++;
  400.       input[j++] = Pic[i++];
  401.       reprocess = true;
  402.     }
  403.     if (reprocess) {
  404.       input[j] = 0;   // terminate the copy, since we are probably appending
  405.       j = i = 0;
  406.       rslt = Process(input, Pic.length(), i, j);
  407.     }
  408.   }
  409.  
  410.   return (rslt == prAmbiguous) ? prComplete
  411.                                : (rslt == prIncompNoFill) ? prIncomplete : rslt;
  412. }
  413.  
  414. #endif
  415. #if !defined(SECTION) || SECTION == 2
  416.  
  417. IMPLEMENT_STREAMABLE1(TPXPictureValidator, TValidator);
  418.  
  419. void*
  420. TPXPictureValidator::Streamer::Read(ipstream& is, uint32 /*version*/) const
  421. {
  422.   ReadBaseObject((TValidator*)GetObject(), is);
  423.   is >> GetObject()->Pic;
  424.   return GetObject();
  425. }
  426.  
  427. void
  428. TPXPictureValidator::Streamer::Write(opstream& os) const
  429. {
  430.   WriteBaseObject((TValidator*)GetObject(), os);
  431.   os << GetObject()->Pic;
  432. }
  433.  
  434. #endif
  435.  
  436.