home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / database / parapi / parapict.cpp next >
Encoding:
C/C++ Source or Header  |  1992-04-18  |  22.9 KB  |  744 lines

  1. /*************************************************************************
  2. **           Paradox-Like Picture Field Input Processing
  3. **************************************************************************
  4. **                                                                      **
  5. **  Copyright (c) 1992  Flexible Information Systems, Inc.              **
  6. **                                                                      **
  7. **    This code may be freely used by any programmer                    **
  8. **    including royalty free inclusion in any commercial                **
  9. **    application, but any commercial rights to the source              **
  10. **    code or object files of this code is are reserved.                **
  11. **                                                                      **
  12. **    This code is supplied strictly as-is, and FIS, Inc. and the       **
  13. **    author assume no responsibility for the accuracy, use or fitness  **
  14. **    for a particular purpose                                          **
  15. **                                                                      **
  16. **                                                                      **
  17. **      Author:         Ken Vogel                                       **
  18. **      CIS Id:         74007,564                                       **
  19. **      Filename:       parapict.cpp                                    **
  20. **      Prefix:         PPIC_                                           **
  21. **      Date:           24-Mar-92                                       **
  22. **                                                                      **
  23. **      Description:    A set of recursive C++ classes which process
  24. **                      data entry with Paradox-like picture formats.
  25. **
  26. **                      The classes in this file do not actually perform
  27. **                      any keyboard or display functions, but should be
  28. **                      integrated into a data entry system.  This allows
  29. **                      them to be used in TurboVision, Windows, etc.
  30. **
  31. **                                                                      **
  32. **************************************************************************/
  33.  
  34.  
  35. #if 0
  36.     ---->>> Revision History <<<----
  37.     ---->>> Revision History <<<----
  38. #endif
  39.  
  40. #include <ctype.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43.  
  44. #define Uses_parapict
  45.  
  46. #include "parapict.hpp"
  47.  
  48. void tbg_ResetOneElement (PPIC_ElementClass *element)
  49. // Reset a single element of a list of PPIC_ElementClass *
  50. {
  51.     element->ResetState();
  52. }
  53.  
  54.  
  55. //////////////////////  PPIC_ElementListClass \\\\\\\\\\\\\\\\\\\\\\\\\
  56.  
  57. PPIC_ElementListClass::PPIC_ElementListClass()
  58.                      : dElementsCPP (0)
  59.                      , dCount (0)
  60. {
  61. }
  62.  
  63. PPIC_ElementListClass::~PPIC_ElementListClass()
  64. {
  65.     PPIC_ElementClass **cursor = dElementsCPP;
  66.     while (dCount-- > 0)
  67.         delete (*cursor++);
  68.     delete dElementsCPP;
  69. }
  70.  
  71. PPIC_ElementClass *PPIC_ElementListClass::at (int index)
  72. {
  73.     return (index < dCount) ? dElementsCPP[ index ] : 0;
  74. }
  75.  
  76. void PPIC_ElementListClass::insert (PPIC_ElementClass *newElement)
  77. {
  78.     PPIC_ElementClass **NewElementsCPP = new PPIC_ElementClass *[dCount + 1];
  79.     if (dCount > 0)
  80.         memcpy (NewElementsCPP, dElementsCPP, dCount * sizeof (*dElementsCPP));
  81.     delete dElementsCPP;
  82.     dElementsCPP = NewElementsCPP;
  83.     dElementsCPP[dCount++] = newElement;
  84. }
  85.  
  86.  
  87. void PPIC_ElementListClass::forEach ( void (*actionFun)(PPIC_ElementClass *))
  88. {
  89.     for (int index = 0; index < dCount; index++)
  90.         actionFun (dElementsCPP[ index ]);
  91. }
  92.  
  93. //////////////////////  PPIC_SequenceClass \\\\\\\\\\\\\\\\\\\\\\\\\
  94.  
  95. PPIC_SequenceClass::PPIC_SequenceClass ( PPIC_ElementClass  *ElementCP)
  96.                       : dElementListCP (new PPIC_ElementListClass())
  97.                       , dCurrentEl(0)
  98. // Constructor to create a sequence class from a single element
  99. {
  100.     dElementListCP->insert (ElementCP);
  101. }
  102.  
  103. PPIC_SequenceClass::~PPIC_SequenceClass()
  104. {
  105.     delete dElementListCP;
  106. }
  107.  
  108. void PPIC_SequenceClass::AddElement (PPIC_ElementClass *ElementCP)
  109. // Add an element to a sequence class
  110. {
  111.     dElementListCP->insert (ElementCP);
  112. }
  113.  
  114.  
  115. void PPIC_SequenceClass::ResetState( void )
  116. // Reset state of entry system
  117. {
  118.     dElementListCP->forEach (tbg_ResetOneElement);
  119.     dCurrentEl = 0;
  120. }
  121.  
  122. int PPIC_SequenceClass::ProcessLetter( char    Letter
  123.                                         , PPIC_FlagsType *FlagsP
  124.                                         , Boolean IsKeypress
  125.                                         , char    *DestP
  126.                                         , int     MaxLength )
  127. {
  128.     int Result;
  129.     if (dCurrentEl >= dElementListCP->getCount())
  130.       {
  131.         *FlagsP = PPIC_cOverflow;
  132.         return 0;
  133.       }
  134.  
  135.     // Loop in case they are done
  136.     while (1)
  137.       {
  138.         PPIC_ElementClass *CurrentElP = dElementListCP->at (dCurrentEl);
  139.  
  140.         *FlagsP = 0;
  141.         Result = CurrentElP->ProcessLetter (Letter, FlagsP, IsKeypress
  142.                                            , DestP, MaxLength);
  143.         if (*FlagsP & PPIC_cOverflow)
  144.           {
  145.             if (++dCurrentEl >= dElementListCP->getCount())
  146.                 return 0;   // Keep overflow flag
  147.             continue;
  148.           }
  149.  
  150.         if (dCurrentEl < dElementListCP->getCount() - 1)
  151.             *FlagsP = 0;  // Cannot be Full if not in last element
  152.         return Result;
  153.       } // Loop over elements when done
  154. } // PPIC_SequenceClass::ProcessLetter
  155.  
  156. //////////////////////  PPIC_AlternateClass \\\\\\\\\\\\\\\\\\\\\\\\\
  157.  
  158. PPIC_AlternateClass::PPIC_AlternateClass ( PPIC_ElementClass  *ElementCP)
  159.                       : dAlternativeListCP (new PPIC_ElementListClass ())
  160.                       , dSelectedEl (-1)
  161. // Constructor to create a sequence class from a single element
  162. {
  163.     dAlternativeListCP->insert (ElementCP);
  164. }
  165.  
  166. PPIC_AlternateClass::~PPIC_AlternateClass()
  167. {
  168.     delete dAlternativeListCP;
  169. }
  170.  
  171. void PPIC_AlternateClass::AddElement (PPIC_ElementClass *ElementCP)
  172. // Add an element to a sequence class
  173. {
  174.     dAlternativeListCP->insert (ElementCP);
  175. }
  176.  
  177. void PPIC_AlternateClass::ResetState( void )
  178. // Reset state of entry system
  179. {
  180.     dAlternativeListCP->forEach (tbg_ResetOneElement);
  181.     dSelectedEl = -1;
  182. }
  183.  
  184. int PPIC_AlternateClass::ProcessLetter( char    Letter
  185.                                      , PPIC_FlagsType *FlagsP
  186.                                      , Boolean IsKeypress
  187.                                      , char    *DestP
  188.                                      , int     MaxLength )
  189. {
  190.     int Result;
  191.     PPIC_ElementClass *CurrentElP;
  192.  
  193.     if (dSelectedEl == -1)
  194.       {
  195.         for (dSelectedEl = 0; dSelectedEl < dAlternativeListCP->getCount();
  196.              dSelectedEl++)
  197.           {
  198.             CurrentElP = dAlternativeListCP->at (dSelectedEl);
  199.             Result = CurrentElP->ProcessLetter (Letter, FlagsP, IsKeypress
  200.                                                , DestP, MaxLength);
  201.             if (Result > 0)
  202.               {
  203.                 // Have a selection -- dSelectedEl is correct
  204.                 return Result;
  205.               }
  206.           }
  207.         // No-one was able to handle it
  208.         dSelectedEl = -1;
  209.         return 0;
  210.       } // Select an alternate
  211.     else
  212.       {
  213.         CurrentElP = dAlternativeListCP->at (dSelectedEl);
  214.         return CurrentElP->ProcessLetter (Letter, FlagsP, IsKeypress
  215.                                                , DestP, MaxLength);
  216.       } // Use existing selection
  217. } // PPIC_AlternateClass::ProcessLetter
  218.  
  219.  
  220. //////////////////////// PPIC_OptionalClass \\\\\\\\\\\\\\\\\\\\\\\\\\\
  221.  
  222. PPIC_OptionalClass::PPIC_OptionalClass ( PPIC_ElementClass *LeftCP
  223.                                      , PPIC_ElementClass *RightCP )
  224.                           : dLeftElementCP (LeftCP)
  225.                           , dRightElementCP (RightCP)
  226.                           , dState (PPIC_fStarting)
  227. // Construct an optional selection from two elements (first is the optional
  228. // one)
  229. {
  230. }
  231.  
  232. PPIC_OptionalClass::~PPIC_OptionalClass()
  233. {
  234.     delete dLeftElementCP;
  235.     delete dRightElementCP;
  236. }
  237.  
  238. void PPIC_OptionalClass::ResetState ()
  239. {
  240.     dLeftElementCP->ResetState();
  241.     if (dRightElementCP)
  242.         dRightElementCP->ResetState();
  243.     dState = PPIC_fStarting;
  244. }
  245.  
  246. int PPIC_OptionalClass::ProcessLetter( char    Letter
  247.                                     , PPIC_FlagsType *FlagsP
  248.                                     , Boolean IsKeypress
  249.                                     , char    *DestP
  250.                                     , int     MaxLength )
  251. {
  252.     int Result;
  253.  
  254.     if (dState == PPIC_fStarting || dState == PPIC_fLeftActive)
  255.       {
  256.         if (dState == PPIC_fStarting && Letter == '\r')
  257.           {
  258.             // Optional, so they can end it now only if right element says
  259.             // it's ok
  260.             *FlagsP = PPIC_cOverflow;
  261.             Result = 0;
  262.             // Then let the right element have a crack at it
  263.           }
  264.         else
  265.           {
  266.             // Try processing with left
  267.             Result = dLeftElementCP->ProcessLetter (Letter, FlagsP, IsKeypress
  268.                                                    , DestP, MaxLength);
  269.             if ((*FlagsP & PPIC_cOverflow)
  270.                 || (Result == 0 && dState == PPIC_fStarting))
  271.                 dState = PPIC_fRightActive;
  272.             else
  273.               {
  274.                 dState = PPIC_fLeftActive;
  275.                 return Result;
  276.               }
  277.           }
  278.       } // Check the left element
  279.  
  280.     // Only gets here if right active
  281.     if (dRightElementCP)
  282.       {
  283.         return dRightElementCP->ProcessLetter (Letter, FlagsP, IsKeypress
  284.                                           , DestP, MaxLength);
  285.       }
  286.     else
  287.       {
  288.         *FlagsP = PPIC_cOverflow;
  289.         return 0;
  290.       }
  291. } // PPIC_OptionalClass::ProcessLetter
  292.  
  293.  
  294. //////////////////// PPIC_FormatClass \\\\\\\\\\\\\\\\\\\\\\\\\\\\
  295. PPIC_FormatClass::PPIC_FormatClass (const char *FormatStrP)
  296. {
  297.     dFormatStringOP = new char [strlen (FormatStrP) + 1];
  298.     if (dFormatStringOP)
  299.         strcpy (dFormatStringOP, FormatStrP);
  300.     dCursorP = dFormatStringOP;
  301. }
  302.  
  303. void PPIC_FormatClass::~PPIC_FormatClass()
  304. {
  305.     delete dFormatStringOP;
  306. }
  307.  
  308. void PPIC_FormatClass::ResetState()
  309. {
  310.     dCursorP = dFormatStringOP;
  311. }
  312.  
  313. int PPIC_FormatClass::ProcessLetter( char    Letter
  314.                                   , PPIC_FlagsType *FlagsP
  315.                                   , Boolean IsKeypress
  316.                                   , char    *DestP
  317.                                   , int     MaxLength )
  318. {
  319.     int Result;
  320.  
  321.     if (*dCursorP == 0)
  322.       {
  323.         *FlagsP = PPIC_cOverflow;
  324.         return 0;
  325.       }
  326.     *FlagsP = 0;
  327.  
  328.     // Process a single letter
  329.     if (*dCursorP <= PPIC_cMaxFormatChar)
  330.       {
  331.         Boolean Good = False;
  332.         // A formatting character
  333.         switch (*dCursorP)
  334.           {
  335.             case PPIC_cDigit:
  336.                 Good = Boolean (isdigit (Letter));
  337.                 break;
  338.  
  339.             case PPIC_cUpperLetter:
  340.                 Letter = toupper (Letter);
  341.             case PPIC_cLetter:
  342.                 Good = Boolean (isalpha (Letter));
  343.                 break;
  344.  
  345.             case PPIC_cUpperAny:
  346.                 Letter = toupper (Letter);
  347.                 break;
  348.             case PPIC_cAny:
  349.             default:
  350.                 Good = True;
  351.                 break;
  352.           } // Switch on cursor
  353.  
  354.         // Now process
  355.         if (!Good)
  356.             return 0;
  357.       }
  358.     else
  359.       {
  360.         // A literal -- check if it matches
  361.         if ( (!IsKeypress || Letter != ' ')
  362.              && toupper (*dCursorP) != toupper (Letter))
  363.             return 0;
  364.         Letter = *dCursorP;
  365.       }
  366.  
  367.  
  368.     // Store this letter no matter what
  369.     dCursorP++;
  370.     Result = 1;
  371.     MaxLength--;
  372.     if (IsKeypress && DestP)
  373.       {
  374.         *DestP++ = Letter;
  375.         *DestP = 0;
  376.       }
  377.  
  378.     // Check for auto expand of literals after this letter
  379.     while (MaxLength-- > 0 && *dCursorP > PPIC_cMaxFormatChar)
  380.       {
  381.         *DestP++ = *dCursorP++;
  382.         Result++;
  383.       }
  384.     *DestP = 0;
  385.  
  386.     // Check for full
  387.     if (*dCursorP == 0)
  388.         *FlagsP = PPIC_cFull;
  389.  
  390.     return Result;
  391. } // FormatClass::ProcessLetter
  392.  
  393.  
  394. //////////////////// PPIC_RepetitionClass \\\\\\\\\\\\\\\\\\\\\\\\\\\\
  395.  
  396. PPIC_RepetitionClass::PPIC_RepetitionClass (int Count
  397.                                          , PPIC_ElementClass *ElementCP)
  398.                       : dRepeatCount (Count)
  399.                       , dRepsLeft (Count)
  400.                       , dElementCP (ElementCP)
  401.                       , dInProcess (False)
  402. {
  403. }
  404.  
  405. PPIC_RepetitionClass::~PPIC_RepetitionClass()
  406. {
  407.     delete dElementCP;
  408. }
  409.  
  410. void PPIC_RepetitionClass::ResetState()
  411. {
  412.     dElementCP->ResetState();
  413.     dRepsLeft = dRepeatCount;
  414.     dInProcess = False;
  415. }
  416.  
  417.  
  418. int PPIC_RepetitionClass::ProcessLetter( char    Letter
  419.                                      , PPIC_FlagsType *FlagsP
  420.                                      , Boolean IsKeypress
  421.                                      , char    *DestP
  422.                                      , int     MaxLength )
  423. {
  424.     if (dRepsLeft == 0 || (!dInProcess && dRepsLeft == -1 && Letter == '\r') )
  425.       {
  426.         *FlagsP = PPIC_cOverflow;
  427.         return 0;
  428.       }
  429.  
  430.     int Result = dElementCP->ProcessLetter (Letter, FlagsP, IsKeypress
  431.                                            , DestP, MaxLength);
  432.     if (*FlagsP & PPIC_cOverflow)
  433.       {
  434.         if (dRepsLeft != -1)
  435.             if (--dRepsLeft == 0)
  436.                 return 0;
  437.  
  438.         dInProcess = False;
  439.         dElementCP->ResetState();
  440.         Result = dElementCP->ProcessLetter (Letter, FlagsP, IsKeypress
  441.                                           , DestP, MaxLength);
  442.       }
  443.     if (!dInProcess && Result == 0 && dRepsLeft == -1)
  444.         *FlagsP = PPIC_cOverflow;
  445.     if (Result != 0)
  446.         dInProcess = True;
  447.  
  448.     // Cannot be full unless all reps are used
  449.     if (dRepsLeft != 0)
  450.         *FlagsP &= ~PPIC_cFull;
  451.  
  452.     return Result;
  453. } // PPIC_RepetitionClass::ProcessLetter
  454.  
  455. ////////////////////////  The recursive parser \\\\\\\\\\\\\\\\\\\\\\\\\\
  456. //  parses an input picture in an element
  457.  
  458. // Get one character from the input string, process to control
  459. // codes accordingly.  Returns the next character & updates the pointer
  460. // Does NOT handle control codes!
  461. char ppic_NextChar (const char *& CursorP)
  462. {
  463.     // The character translation set.  The index into this string is the
  464.     // "internal" representation of the formatting character.
  465.     char FromCharA[] = "*[]{},#?&@!";
  466.  
  467.     char Result = *CursorP;
  468.     if (Result == 0)
  469.         return 0;
  470.  
  471.     CursorP++;
  472.  
  473.     if (Result == ';')
  474.       {
  475.         if (0 != (Result = *CursorP))
  476.             CursorP++;
  477.       }
  478.     else
  479.       {
  480.         char *SpecialP = strchr (FromCharA, Result);
  481.         if (SpecialP != 0)
  482.             Result = (char)(SpecialP - FromCharA + 1);
  483.       }
  484.     return Result;
  485. } // ppic_NextChar
  486.  
  487.  
  488. // Forward declaration for recursion
  489. PPIC_ElementClass *PPIC_Parse ( const char *&CursorP);
  490.  
  491.  
  492. PPIC_ElementClass *PPIC_ElementParse ( const char *&CursorP)
  493. // Parse an element of a picture string
  494. // PictureP is the input picture
  495. // Modifies PictureP to point to last char afer input
  496. {
  497.     PPIC_ElementClass *ResultCP;
  498.     char *StoreCursorP;
  499.     const char *BeforePeekP = CursorP;
  500.  
  501.     char NextChar = ppic_NextChar (CursorP);
  502.  
  503.     if (NextChar == 0)
  504.         return NULL;
  505.  
  506.     if (NextChar > PPIC_cMaxSpecialChar)
  507.       {
  508.         // Formatting string -- get all chars possible
  509.         // Get the length for allocation
  510.         int Length = 1;
  511.         while (ppic_NextChar (CursorP) > PPIC_cMaxSpecialChar)
  512.             Length++;
  513.         char *FormatOP = new char [Length + 1];
  514.         if (FormatOP == 0)
  515.             return 0;
  516.  
  517.         // Copy the formatting characters into this
  518.         StoreCursorP = FormatOP;
  519.         CursorP = BeforePeekP;
  520.         while ( Length--)
  521.             *StoreCursorP++ = ppic_NextChar (CursorP);
  522.         *StoreCursorP = 0;
  523.  
  524.         CursorP = CursorP;
  525.         ResultCP = new PPIC_FormatClass (FormatOP);
  526.         delete FormatOP;
  527.       } // A formatting character
  528.     else
  529.       {
  530.         char BufferA[10];
  531.         int Counter, Count;
  532.         PPIC_ElementClass *NextElementCP, *LeftCP;
  533.  
  534.         switch (NextChar)
  535.           {
  536.             case PPIC_cRepetition:
  537.                 // Get up to 5 digits
  538.                 StoreCursorP = BufferA;
  539.                 Counter = 5;
  540.                 while (Counter-- && isdigit (*CursorP))
  541.                     *StoreCursorP++ = *CursorP++;
  542.                 *StoreCursorP = 0;
  543.                 if (*BufferA == 0)
  544.                     Count = -1;
  545.                 else
  546.                   {
  547.                     Count = atoi (BufferA);
  548.                     if (Count < 0)
  549.                         Count = -1;
  550.                   }
  551.  
  552.                 // Now get the next element
  553.                 BeforePeekP = CursorP;
  554.                 NextChar = ppic_NextChar (CursorP);
  555.                 if (NextChar <= PPIC_cMaxSpecialChar)
  556.                   {
  557.                     // A complex element.  If it's an option, we only want
  558.                     // to process the beginning
  559.                     if (NextChar == PPIC_cOptionOpen)
  560.                       {
  561.                         NextElementCP = PPIC_Parse (CursorP);
  562.                         NextChar = ppic_NextChar (CursorP);
  563.                         if (NextChar != PPIC_cOptionClose)
  564.                           {
  565.                             delete NextElementCP;
  566.                             NextElementCP = 0;
  567.                             return 0;
  568.                           }
  569.                         else
  570.                           {
  571.                             NextElementCP
  572.                                 = new PPIC_OptionalClass (NextElementCP, 0);
  573.                           }
  574.                       } // Process option repetition
  575.                     else
  576.                       {
  577.                         CursorP = BeforePeekP;
  578.                         NextElementCP = PPIC_ElementParse (CursorP);
  579.                       }
  580.                   } // Have a special character
  581.                 else
  582.                   {
  583.                     // A single character
  584.                     BufferA[0] = NextChar;
  585.                     BufferA[1] = 0;
  586.                     NextElementCP = new PPIC_FormatClass (BufferA);
  587.                   }
  588.  
  589.                 if (NextElementCP == 0)
  590.                     ResultCP = 0;
  591.                 else
  592.                     ResultCP = new PPIC_RepetitionClass (Count, NextElementCP);
  593.                 break; // A repetition
  594.  
  595.             case PPIC_cOptionOpen:
  596.                 LeftCP = PPIC_Parse (CursorP);
  597.                 if (ppic_NextChar (CursorP) != PPIC_cOptionClose)
  598.                   {
  599.                     delete LeftCP;
  600.                     ResultCP = 0;
  601.                   }
  602.                 else
  603.                   {
  604.                     NextElementCP = PPIC_Parse (CursorP);
  605.                     ResultCP = new PPIC_OptionalClass (LeftCP, NextElementCP);
  606.                   }
  607.                 break;
  608.  
  609.             case PPIC_cGroupOpen:
  610.                 ResultCP = PPIC_Parse (CursorP);
  611.                 if (ppic_NextChar (CursorP) != PPIC_cGroupClose)
  612.                   {
  613.                     delete ResultCP;
  614.                     ResultCP = 0;
  615.                   }
  616.                 break;
  617.  
  618.             case PPIC_cAlternate:
  619.             case PPIC_cOptionClose:
  620.             case PPIC_cGroupClose:
  621.             default:
  622.                 CursorP = BeforePeekP;
  623.                 ResultCP = 0;
  624.                 break;
  625.           } // Switch NextChar
  626.       } // A special character
  627.  
  628.     return ResultCP;
  629. } // PPIC_ElementParse
  630.  
  631.  
  632. PPIC_ElementClass *PPIC_Parse ( const char *&CursorP)
  633. // Parse an entire picture string
  634. {
  635.     PPIC_SequenceClass *SequenceCP = 0;
  636.     PPIC_AlternateClass *AlternateCP = 0;
  637.     PPIC_ElementClass *ElementCP;
  638.     const char *BeforeP;
  639.     char NextChar;
  640.  
  641.     // Loop over the expressions we can get
  642.     while (1)
  643.       {
  644.         ElementCP = PPIC_ElementParse (CursorP);
  645.         if (ElementCP != 0 && SequenceCP != 0)
  646.           {
  647.             // Add to end of sequence
  648.             SequenceCP->AddElement (ElementCP);
  649.             ElementCP = SequenceCP;
  650.           }
  651.  
  652.         BeforeP   = CursorP;
  653.         NextChar  = ppic_NextChar (CursorP);
  654.  
  655.         if (ElementCP == 0
  656.            || NextChar == 0
  657.            || NextChar == PPIC_cOptionClose
  658.            || NextChar == PPIC_cGroupClose)
  659.           {
  660.            // The end
  661.            if (AlternateCP != 0)
  662.              {
  663.                AlternateCP->AddElement (ElementCP);
  664.                ElementCP = AlternateCP;
  665.              }
  666.            CursorP = BeforeP;
  667.            return ElementCP;
  668.           }
  669.         else if (NextChar == PPIC_cAlternate)
  670.           {
  671.             if (AlternateCP != 0)
  672.                 AlternateCP->AddElement (ElementCP);
  673.             else
  674.                 AlternateCP = new PPIC_AlternateClass (ElementCP);
  675.             // Use the element in alternate -- erase any sequence
  676.             SequenceCP = 0;
  677.           }
  678.         else
  679.           {
  680.             // A sequence of elements (if exists, we already added to end)
  681.             if (SequenceCP == 0)
  682.                 SequenceCP = new PPIC_SequenceClass (ElementCP);
  683.             CursorP    = BeforeP;
  684.           }
  685.       } // Loop over parts of expression (terminates with return)
  686. } // PPIC_Parse
  687.  
  688. PPIC_PictureClass::PPIC_PictureClass(const char *PictureP)
  689.                  : thePicture (0)
  690. {
  691.     thePicture = PPIC_Parse (PictureP);
  692.     valid = Boolean (thePicture != 0);
  693. }
  694.  
  695. PPIC_PictureClass::~PPIC_PictureClass()
  696. {
  697.     delete thePicture;
  698. }
  699.  
  700. int PPIC_PictureClass::ProcessLetter( char    Letter
  701.                                     , PPIC_FlagsType *FlagsP
  702.                                     , Boolean IsKeypress
  703.                                     , char    *DestP
  704.                                     , int     MaxLength )
  705. {
  706.     int result = 0;
  707.     if (thePicture)
  708.       {
  709.         result = thePicture->ProcessLetter ( Letter, FlagsP, IsKeypress
  710.                                                , DestP, MaxLength);
  711.  
  712.         // Overflow of outermost picture is an error (unless c/r)
  713.         if ((*FlagsP & PPIC_cOverflow) && Letter != '\r')
  714.             *FlagsP = 0;
  715.       }
  716.     return result;
  717. }
  718.  
  719.  
  720. void PPIC_PictureClass::ResetState( void )
  721. {
  722.     if (thePicture)
  723.         thePicture->ResetState();
  724. }
  725. char *PPIC_PictureClass::ReprocessString ( char *StringP
  726.                                          , PPIC_FlagsType *FlagsP)
  727. {
  728.     *FlagsP = 0;
  729.     if (thePicture)
  730.       {
  731.         thePicture->ResetState();
  732.         char *CursorP = StringP;
  733.         while (*CursorP)
  734.           {
  735.             if (!thePicture->ProcessLetter ( *CursorP, FlagsP, False, 0, 0)
  736.                || (*FlagsP & PPIC_cOverflow))
  737.                 return CursorP;
  738.             CursorP++;
  739.           }
  740.       }
  741.  
  742.     return 0;
  743. }
  744.