home *** CD-ROM | disk | FTP | other *** search
/ Troubleshooting Netware Systems / CSTRIAL0196.BIN / attach / msj / v10n04 / multilin.exe / PICTURE.CPP < prev    next >
C/C++ Source or Header  |  1995-04-01  |  9KB  |  393 lines

  1. // Implement Numeric pictures
  2.  
  3. #include "stdafx.h"
  4. #include "picture.h"
  5.  
  6.  
  7. // 
  8. // This file implements the class CPicture that can convert
  9. // between the NUMBERFMT struct and a "picture" format of
  10. // expressing numeric formatting. It is used by the overloaded
  11. // GetNumberFormat() function in numform.cpp
  12. // 
  13. // Pieces of the lpInput string that form the picture for 
  14. // an individual number    and are converted to the lpInput
  15. // required by the built-in GetNumberFormat. The CPicture
  16. // class, and which is derived form the NUMBERFMT class that
  17. // is the lpInput to the built-in GetNumberFormat handles the
  18. // conversion. The constructor 
  19. // CPicture::CPicture is where the picture definition is
  20. // parsed and translated into the field values in the 
  21. // NUMBERFMT structure. This is the syntax for numeric
  22. // pictures
  23. // [-][(][{#|0},][{#|0}+][.][{#|0}+][)][-]     
  24. // where 
  25. //   0 means a digit position including leading zeros
  26. //   # means a non-zero digit position    
  27. //      . means the decimal separator of the active locale
  28. //   , means the thousands separator ...
  29. //   - means placeholder for the sign string
  30. //     ( means use of () instead of - sign
  31. //   and the number of repetitions (+ in syntax)
  32. //     is counted to determine grouping and fraction 
  33. //   width.
  34. // The default constructor creates a picture from the active
  35. // locale. Another overloaded constructor is provided to create
  36. // pictures for any given locale. This latter constructor is
  37. // used when GetNumberFormat is called without an lpFormat string.
  38.  
  39. /* As a reminder: this is the NUMBERFMT structure
  40. typedef struct _NUMBERFMT { 
  41.  
  42.     UINT      NumDigits;     // number of fractional digits
  43.     UINT      LeadingZero;     // Boolean for leading 0
  44.     UINT      Grouping;         // Grouping 0-9 (3 or 4 are common)
  45.     LPTSTR    lpDecimalSep;     // string for same
  46.     LPTSTR    lpThousandSep; // string for same
  47.     UINT      NegativeOrder;  //??
  48. } NUMBERFMT;
  49. */
  50.  
  51. // Default constructor contructs picture from
  52. // GetLocaleInfo
  53. CPicture::CPicture(LCID lcid/*=LOCALE_SYSTEMDEFAULT*/, DWORD dwFlags /*=LOCALE_WITHOVERRIDE*/)
  54. {
  55.     if( lcid == LOCALE_SYSTEM_DEFAULT)
  56.     {
  57.         lcid = GetThreadLocale();  // NT only
  58.         // put Chicago specific code here
  59.     }
  60.     GetFieldValue(lcid,LOCALE_IDIGITS|dwFlags, NumDigits);
  61.     GetFieldValue(lcid,LOCALE_ILZERO|dwFlags, LeadingZero);
  62.     GetFieldValue(LOCALE_INEGNUMBER|dwFlags, NegativeOrder);
  63.     // Grouping is really a string value as LCTYPE
  64.     // just use the first entry in the Grouping string
  65.     GetFieldValue(LOCALE_SGROUPING|dwFlags, Grouping);
  66.     // These are string values
  67.     lpDecimalSep = m_DecSep;
  68.     lpThousandSep = m_ThouSep;
  69.     GetFieldValue(LOCALE_SDECIMAL|dwFlags, lpDecimalSep);
  70.     GetFieldValue(LOCALE_STHOUSAND|dwFlags, lpThousandSep);
  71.     m_Length = BuildUp();    // if we can delay build-up we can overload
  72. }
  73.  
  74. void CPicture::GetFieldValue(LCTYPE lctype, UINT& uiVal)
  75. {
  76.     LCID lcid = GetThreadLocale(); 
  77.     GetFieldValue(lcid, lctype, uiVal);
  78. }
  79.  
  80. void CPicture::GetFieldValue(LCID lcid, LCTYPE lctype, UINT& uiVal)
  81. {
  82.     const int cch=8 ;
  83.     TCHAR ach[cch];
  84.     GetLocaleInfo(lcid, lctype, ach, cch);
  85.     uiVal = _ttoi(ach);
  86. }
  87.  
  88. void CPicture::GetFieldValue(LCTYPE lctype, LPTSTR str)
  89. {
  90.     LCID lcid = GetThreadLocale();
  91.     GetFieldValue(lcid, lctype, str);
  92. }
  93.                                                       
  94. void CPicture::GetFieldValue(LCID lcid, LCTYPE lctype, LPTSTR str)
  95. {
  96.     GetLocaleInfo(lcid, lctype, str, MAXSEP );
  97. }
  98.  
  99. int CPicture::BuildUp()
  100. {                   
  101.     int count=0;
  102.     switch(NegativeOrder)
  103.     {
  104.     case 0:
  105.         m_Picture[count++]=_T('(');
  106.         BuildUpPositive(count);    
  107.         m_Picture[count++]=_T(')');
  108.         break;
  109.     case 1:
  110.         m_Picture[count++]=_T('-');
  111.         BuildUpPositive(count);    
  112.         break;
  113.     case 2:                 
  114.         m_Picture[count++]=_T('-');
  115.         m_Picture[count++]=_T(' ');
  116.         BuildUpPositive(count);    
  117.         break;
  118.     case 3:
  119.         BuildUpPositive(count);    
  120.         m_Picture[count++]=_T('-');
  121.         break;
  122.     case 4:
  123.         BuildUpPositive(count);
  124.         m_Picture[count++]=_T(' ');
  125.         m_Picture[count++]=_T('-');
  126.         break;
  127.     default:
  128.         ASSERT(0);    // Can't happen
  129.     }
  130.     m_Picture[count]=_T('\0');    //TERMINATE
  131.     return count;
  132. }
  133.                                            
  134. void CPicture::BuildUpPositive(int& count)
  135. {
  136.     TCHAR ch;
  137.     if( LeadingZero )
  138.     {
  139.         ch=    _T('0');
  140.     }
  141.     else
  142.     {
  143.         ch=    _T('#');
  144.     }
  145.     
  146.     m_Picture[count++]=ch;
  147.  
  148.     int j=Grouping; 
  149.     if( j )
  150.     {
  151.         m_Picture[count++]=_T(',');
  152.         while(j-->0)
  153.         {
  154.             m_Picture[count++]=ch;
  155.         }
  156.     }  
  157.  
  158.     int k= NumDigits;
  159.     if(k)
  160.     {
  161.         m_Picture[count++]=_T('.');
  162.         while(k-->0)
  163.         {
  164.             m_Picture[count++]=ch;
  165.         }
  166.     }
  167. }
  168.  
  169.  
  170. CPicture::CPicture( LPCTSTR lpInp, LCID lcid, DWORD dwFlags)
  171.     dwFlags &= ~LOCALE_NOUSEROVERRIDE; // limit to this flag
  172.  
  173.     if( lcid == LOCALE_SYSTEM_DEFAULT )
  174.     {
  175.         lcid=GetThreadLocale();
  176.     }
  177.     // These are string values    
  178.     lpDecimalSep = m_DecSep;
  179.     lpThousandSep = m_ThouSep;
  180.     GetFieldValue(lcid, LOCALE_SDECIMAL|dwFlags, lpDecimalSep);
  181.     GetFieldValue(LOCALE_STHOUSAND|dwFlags, lpThousandSep);
  182.     
  183.     if(lpInp)
  184.     {
  185.         m_Length=Parse(lpInp);
  186.     }
  187.     else
  188.     {
  189.         GetFieldValue(lcid,LOCALE_IDIGITS|dwFlags, NumDigits);
  190.         GetFieldValue(lcid,LOCALE_ILZERO|dwFlags, LeadingZero);
  191.         GetFieldValue(LOCALE_INEGNUMBER|dwFlags, NegativeOrder);
  192.         // Grouping is really a string value as LCTYPE
  193.         // just use the first entry in the Grouping string
  194.         GetFieldValue(LOCALE_SGROUPING|dwFlags, Grouping);
  195.     }
  196. }
  197. // This and the next few functions parse the number specifier
  198. // They return the number of character consumed from the input
  199. // specification in lpInp
  200.  
  201.  
  202. int CPicture::Parse(LPCTSTR lpInp)
  203. {
  204.     const unsigned int UNDEFINED = 5;
  205.  
  206.     // Sign part
  207.     NegativeOrder=UNDEFINED;    // == no sign seen so far
  208.     
  209.     int    count=Sign(lpInp);
  210.  
  211.     // Number part
  212.     TCHAR chDigit=_T('#');
  213.     count+=Integer(lpInp, chDigit);
  214.     LeadingZero=(chDigit==_T('0')? 1 : 0);
  215.  
  216.     // Fraction part
  217.     count+=Fraction(lpInp, chDigit);
  218.     
  219.     // Check for trailing sign
  220.     if( NegativeOrder == UNDEFINED )
  221.     {
  222.         count+=AltSign(lpInp);
  223.     }
  224.     else if( NegativeOrder == 0)
  225.     {
  226.         count=ParSign(lpInp, count);
  227.     }
  228.     NegativeOrder%=4;    // 1 is default, use if no sign specified
  229.     return count;
  230. }
  231.  
  232. int CPicture::Sign(LPCTSTR& lpInp)
  233. {
  234.     int count=0;
  235.        if( *lpInp == _T('-') )
  236.     {
  237.         lpInp++;
  238.         count++;
  239.         NegativeOrder=1;
  240.         if(*lpInp==_T(' '))
  241.         {
  242.             count++;
  243.             lpInp++;
  244.             NegativeOrder=2;
  245.         }
  246.     }
  247.     else if( *lpInp == _T('('))
  248.     {
  249.         NegativeOrder=0;
  250.         lpInp++;
  251.         count++;
  252.     }
  253.     return count;
  254. }
  255.     
  256. int CPicture::ParSign(LPCTSTR& lpInp,int count)
  257. {
  258.     if    (NegativeOrder==0)
  259.     {
  260.         if(*lpInp == _T(')'))
  261.         {
  262.             lpInp++;
  263.             count++    ;
  264.             return count;
  265.         }
  266.         else
  267.         {
  268.             lpInp-=count;
  269.             return (-count);
  270.         }
  271.     } 
  272.     return(0);
  273. }
  274. int CPicture::AltSign(LPCTSTR& lpInp)
  275. {     
  276.     int count=0;
  277.     if( *lpInp == _T(' ') )
  278.     {
  279.         lpInp++;
  280.         count++;
  281.         if(*lpInp==_T('-'))
  282.         {
  283.             count++;
  284.             lpInp++;
  285.             NegativeOrder=4;                               
  286.         }
  287.         else
  288.         {
  289.             count--;
  290.             lpInp--;
  291.         }
  292.     } 
  293.     else if(*lpInp ==_T('-') )
  294.     {
  295.         lpInp++;
  296.         count++;
  297.         NegativeOrder=3;
  298.     } 
  299.     return count;
  300. }
  301.  
  302. int    CPicture::Integer(LPCTSTR& lpInp, TCHAR& chDigit)
  303. {
  304.     int count=0;
  305.     Grouping=0;
  306.     if( *lpInp == _T('0') )
  307.     {
  308.         chDigit=*lpInp;
  309.         count = PosNum(lpInp, chDigit);
  310.     }
  311.     else if( *lpInp == _T('#') )
  312.     {
  313.         chDigit=*lpInp;
  314.         count = PosNum(lpInp, chDigit);
  315.     }
  316.     else
  317.     {
  318.         return(0);
  319.     } 
  320.  
  321.     ASSERT(count>=1);
  322.  
  323.     if(*lpInp==_T(',') )
  324.     {
  325.          lpInp++;
  326.          count++;
  327.          Grouping=PosNum(lpInp, chDigit);
  328.          if(Grouping ==0)
  329.          {
  330.              // back up over ','
  331.             lpInp--;
  332.             count--;
  333.          }
  334.     }
  335.     return(count+Grouping);
  336. }
  337.     
  338. int    CPicture::PosNum(LPCTSTR& lpInp, TCHAR chDigit)
  339. {       
  340.     int count = 0;
  341.     while(*lpInp == chDigit)
  342.     {
  343.         count++;
  344.         lpInp++;
  345.     }
  346.     return count;
  347. }
  348.  
  349. int CPicture::Fraction(LPCTSTR& lpInp, TCHAR chDigit)
  350. {
  351.     NumDigits=0;
  352.     if(*lpInp == _T('.'))
  353.     {
  354.         lpInp++ ;
  355.         return (NumDigits=PosNum(lpInp, chDigit))+1;
  356.     }
  357.     return 0;
  358. }
  359.  
  360. #if _DEBUG
  361. #ifndef _UNICODE
  362. // Test works for ANSI only
  363. void Test()
  364. {
  365.     TCHAR test[25];
  366.     CPicture pc;
  367.     ::MessageBox(NULL, pc.m_Picture, "TEST", MB_OK);
  368.     CPicture pc0("(00.00)");
  369.     GetNumberFormat(GetThreadLocale(),NULL, 
  370.         _T("-123456789"),&pc0,  test, 25);
  371.     ::MessageBox(NULL, test, "TEST", MB_OK);
  372.     CPicture pc1("-00,00)");
  373.     GetNumberFormat(GetThreadLocale(),NULL, 
  374.         _T("-123456789"), &pc1,test, 25);
  375.     ::MessageBox(NULL, test, "TEST", MB_OK);      
  376.     CPicture pc2("- 0,0#0)");
  377.     GetNumberFormat(GetThreadLocale(),NULL,  
  378.         _T("-123456789"),&pc2, test, 25);
  379.     ::MessageBox(NULL, test, "TEST", MB_OK);
  380.     CPicture pc3("0,0.00-");
  381.     GetNumberFormat(GetThreadLocale(),NULL, 
  382.         _T("-123456789"),&pc3, test, 25);
  383.     ::MessageBox(NULL, test, "TEST", MB_OK);
  384.     CPicture pc4(".######### -");
  385.     GetNumberFormat(GetThreadLocale(),NULL,
  386.         _T("-.123456789"), &pc4, test, 25);
  387.     ::MessageBox(NULL, test, "TEST", MB_OK);
  388. }
  389. #endif
  390. #endif //DEBUG
  391.  
  392.