home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / PICTVAL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  9.2 KB  |  420 lines

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