home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mavcl130.zip / mavfrent.cpp < prev    next >
Text File  |  1996-10-29  |  19KB  |  752 lines

  1. /*  File: mavfrent.cpp      Updated: Sun Dec 17 19:26:32 1995
  2. Copyright (c) Fabrizio Aversa
  3. ===========================================================*/
  4.  
  5. #include <mavfrent.hpp>
  6. #include <mavconv.hpp>
  7. #include <mavregex.hpp>
  8.  
  9. #define FORM_DATE_SEP " ,/-.=*_:"
  10. #define FORM_TIME_SEP " ,/-.=*_:"
  11.  
  12. /* ====================== FormEntryField =================== */
  13.  
  14. FormEntryField::FormEntryField(unsigned long l, IWindow * iw, IWindow * iw1, const IRectangle & r)
  15. :IEntryField(l, iw, iw1, r, IEntryField::defaultStyle() | IControl::tabStop
  16. | IEntryField::margin),
  17. piwParent(iw), IFocusHandler(), IKeyboardHandler()
  18. {
  19.  
  20.    IFocusHandler::handleEventsFor(this);
  21.    IKeyboardHandler::handleEventsFor(this);
  22.  
  23.    getCountryInfo(&CountryInfo);
  24. }
  25.  
  26. FormEntryField::FormEntryField(unsigned long l, IWindow * iw)
  27. :IEntryField(l, iw), piwParent(iw), IFocusHandler(), IKeyboardHandler()
  28. {
  29.  
  30.    IKeyboardHandler::handleEventsFor(this);
  31.    IFocusHandler::handleEventsFor(this);
  32.  
  33.    getCountryInfo(&CountryInfo);
  34. }
  35.  
  36. FormEntryField::FormEntryField(unsigned long id, IWindow * parent,
  37. IWindow * owner, const IRectangle & rect,
  38. const IEntryField::Style & style)
  39. :IEntryField(id, parent, owner, rect, style),
  40. piwParent(parent), IFocusHandler(), IKeyboardHandler()
  41. {
  42.  
  43.    IKeyboardHandler::handleEventsFor(this);
  44.    IFocusHandler::handleEventsFor(this);
  45.  
  46.    getCountryInfo(&CountryInfo);
  47. }
  48.  
  49. IWindow & FormEntryField::setFocus()
  50. /* just to change colors of first field in a dialog when getting focus,
  51. strangely gotfocus is not called automatically */
  52. {
  53.    setColor(border, IColor(IColor::red));
  54.    setColor(background, IColor(IColor::white));
  55.    setColor(foreground, IColor(IColor::black));
  56.  
  57.    return IEntryField::setFocus();
  58.  
  59. }
  60.  
  61. FormEntryField::gotFocus(IControlEvent&)
  62. {
  63.    setColor(border, IColor(IColor::red));
  64.    setColor(background, IColor(IColor::white));
  65.    setColor(foreground, IColor(IColor::black));
  66.  
  67.    return false;
  68. }
  69.  
  70. FormEntryField::lostFocus(IControlEvent&)
  71. {
  72.    setColor(border, IColor(IColor::darkGray));
  73.    setColor(background, IColor(IColor::white));
  74.  
  75.    return false;
  76. }
  77.  
  78. /* ====================== AlphaEntryField =================== */
  79.  
  80. AlphaEntryField::AlphaEntryField(unsigned long l,
  81. IWindow * iw, IWindow * iw1, const IRectangle & r,
  82. Boolean b1, Boolean b2, IString s, IString s1)
  83. :FormEntryField(l, iw, iw1, r)
  84. {
  85.    booCaps= b1;
  86.    booNoNum= b2;
  87.    strAllowed= s;
  88.    strRegex= s1;
  89.  
  90. }
  91.  
  92. AlphaEntryField::AlphaEntryField(unsigned long l, IWindow * iw,
  93. Boolean b1, Boolean b2, IString s, IString s1)
  94. :FormEntryField(l, iw)
  95. {
  96.    booCaps= b1;
  97.    booNoNum= b2;
  98.    strAllowed= s;
  99.    strRegex= s1;
  100.  
  101. }
  102.  
  103. AlphaEntryField::AlphaEntryField(unsigned long id, IWindow * parent,
  104. IWindow * owner, const IRectangle & rect,
  105. const IEntryField::Style & style)
  106. :FormEntryField(id, parent, owner, rect, style)
  107. {
  108.    booCaps= false;
  109.    booNoNum= false;
  110.    strAllowed= "";
  111.    strRegex= "";
  112.  
  113. }
  114.  
  115. Boolean AlphaEntryField::characterKeyPress(IKeyboardEvent& keyevt)
  116. {
  117.    CHAR ch= keyevt.character();
  118.  
  119.    if (booNoNum && ch >= '0' && ch <= '9') return true;
  120.  
  121.    if (strAllowed.length())
  122.    if(!strAllowed.includes(ch)) return true;
  123.  
  124.    return false;
  125. }
  126.  
  127.  
  128. Boolean AlphaEntryField::lostFocus(IControlEvent& ctl)
  129. {
  130.    IString strFlags= "";
  131.    IString strText= text();
  132.  
  133.    FormEntryField::lostFocus(ctl);
  134.  
  135.    if(booCaps) {
  136.       setText(strText.upperCase());
  137.       strFlags="i";
  138.    }
  139.  
  140.    /* change single and double quotes in ` */
  141.    for (USHORT i= 1; i <= strText.length(); i++)
  142.    if (strText[i] == 39 || strText[i] == '"') strText[i]= '`';
  143.    setText(strText);
  144.  
  145.    if(strRegex.length()) {
  146.  
  147.       CHAR pszTarget[100];
  148.       strcpy(pszTarget, "");
  149.       istrstream istAct((PSZ)text());
  150.       ostrstream ostAct(pszTarget, 100);
  151.       RegEx rx(istAct, ostAct, strFlags);
  152.       rx.process(strRegex);
  153.  
  154.       if(!(*pszTarget)) {
  155.  
  156.          setColor(background, IColor(IColor::red));
  157.          setColor(foreground, IColor(IColor::white));
  158.  
  159.          return true;
  160.       }
  161.  
  162.    }
  163.  
  164.    return false;
  165. }
  166.  
  167. /* ====================== NumEntryField =================== */
  168.  
  169. NumEntryField::NumEntryField(unsigned long id, IWindow * parent,
  170. IWindow * owner, const IRectangle & rect,
  171. const IEntryField::Style & style)
  172. :FormEntryField(id, parent, owner, rect, style)
  173. {
  174.    dblMin = 0.0;
  175.    dblMax = 0.0;
  176.    booThous= true;
  177.    booShowZero= false;
  178.    setAlignment(right);
  179.  
  180.    strValidChars = (IString)"x0123456789e-";
  181.    /* substitute 'x' with actual decimal separator */
  182.    strValidChars[1] = CountryInfo.szDecimal[0];
  183.  
  184. }
  185.  
  186. NumEntryField::NumEntryField(unsigned long l,
  187. IWindow * iw, IWindow * iw1, const IRectangle & r, Boolean b1, Boolean b2,
  188. double dblMin1, double dblMax1)
  189. :FormEntryField(l, iw, iw1, r)
  190. {
  191.    dblMin = dblMin1;
  192.    dblMax = dblMax1;
  193.    booThous= b1;
  194.    booShowZero= b2;
  195.    setAlignment(right);
  196.  
  197.    strValidChars = (IString)"x0123456789e-";
  198.    /* substitute 'x' with actual decimal separator */
  199.    strValidChars[1] = CountryInfo.szDecimal[0];
  200.  
  201. }
  202.  
  203. NumEntryField::NumEntryField(unsigned long l, IWindow * iw,
  204. Boolean b1, Boolean b2,
  205. double dblMin1, double dblMax1)
  206. :FormEntryField(l, iw)
  207. {
  208.    dblMin = dblMin1;
  209.    dblMax = dblMax1;
  210.    booThous= b1;
  211.    booShowZero= b2;
  212.    setAlignment(right);
  213.  
  214.    strValidChars = (IString)"x0123456789e-";
  215.    /* substitute 'x' with actual decimal separator */
  216.    strValidChars[1] = CountryInfo.szDecimal[0];
  217.  
  218. }
  219.  
  220. Boolean NumEntryField::characterKeyPress(IKeyboardEvent& keyevt)
  221. {
  222.    USHORT i;
  223.    Boolean booSign, booDecimal, booExp;
  224.  
  225.    i= text().length();
  226.  
  227.    if (text().includes(CountryInfo.szDecimal[0]))
  228.    booDecimal= true;
  229.    else
  230.    booDecimal= false;
  231.  
  232.    if (i && (text()[1] == '-'))
  233.    booSign= true;
  234.    else
  235.    booSign= false;
  236.  
  237.    if (text().includes('e'))
  238.    booExp= true;
  239.    else
  240.    booExp= false;
  241.  
  242.    CHAR ch= keyevt.character();
  243.  
  244.    if ( ! (strValidChars).includes(ch)) return true;
  245.  
  246.    /* do not allow - if pos is not 1 or immediately after e */
  247.    if (
  248.    (ch == '-') && (booSign && (i && text()[i] != 'e'))
  249.    ) return true;
  250.  
  251.    if (ch == 'e' && booExp) return true;
  252.  
  253.    if (ch == CountryInfo.szDecimal[0] && booDecimal) return true;
  254.  
  255.    return false;
  256. }
  257.  
  258. IString NumEntryField::format(double d, Boolean booTh)
  259. {
  260.    INT i, iStart;
  261.  
  262.    IString strRet(d);
  263.  
  264.    // do not show 0
  265.    if (!d && !booShowZero) return (strRet= "");
  266.  
  267.    /* replace '.' with country specific decimal separator */
  268.    for (i= strRet.length() ; i; i-- ) {
  269.       if ( strRet[i] == '.' ) strRet[i] =  CountryInfo.szDecimal[0];
  270.    }
  271.  
  272.    if (booTh) {
  273.  
  274.       iStart= strRet.length()+1;
  275.  
  276.       /* find where integer part begins */
  277.       for (i= strRet.length() ; i; i-- ) {
  278.          if ( strRet[i] == CountryInfo.szDecimal[0] || strRet[i] == 'e') iStart= i ;
  279.       }
  280.  
  281.       for (i= iStart-4 ; i >= (strRet[1] == '-' ? 2:1) ; i -= 3 ) {
  282.          strRet= strRet.subString(1, i)+
  283.          IString(CountryInfo.szThousandsSeparator)+
  284.          strRet.subString(i+1, strRet.length()-i);
  285.       }
  286.    }
  287.  
  288.    return strRet;
  289. }
  290.  
  291. double NumEntryField::getDouble()
  292. {
  293.    USHORT i, dotfound= 0 ;
  294.  
  295.    IString temps= this->text();
  296.  
  297.    temps.lowerCase().strip();
  298.  
  299.    if ( temps.length() == 0 ) return 0.0 ;
  300.  
  301.    /* remove thousands separators */
  302.    for (i= 1 ; i<= temps.length() ; i++ ) {
  303.  
  304.       if ( temps[i] == CountryInfo.szThousandsSeparator[0] )
  305.       temps= temps.subString(1, i-1)+temps.subString(i+1, temps.length()-i);
  306.  
  307.    } /* end of for */
  308.  
  309.    /* replace country specific decimal separator with '.' */
  310.    for (i= 1 ; i<= temps.length() ; i++ ) {
  311.  
  312.       if ( temps[i] == CountryInfo.szDecimal[0] ) temps[i] = '.';
  313.  
  314.    } /* end of for */
  315.  
  316.    return temps.asDouble();
  317.  
  318. }
  319.  
  320. NumEntryField & NumEntryField::setDouble(double d)
  321. {
  322.    setText(format(d, booThous));
  323.  
  324.    /* if dblMin != dblMax means there is a range of validity */
  325.    if(
  326.    (d < dblMin || d > dblMax)
  327.    && dblMin != dblMax
  328.    && text().strip().length()
  329.    ) {
  330.       setColor(background, IColor(IColor::red));
  331.       setColor(foreground, IColor(IColor::white));
  332.    }
  333.  
  334.    return (NumEntryField &)(*this);
  335. }
  336.  
  337. Boolean NumEntryField::gotFocus(IControlEvent& evt)
  338. {
  339.    FormEntryField::gotFocus(evt);
  340.  
  341.    if(text().lowerCase().length()) setText(format(getDouble(), false));
  342.  
  343.    return false;
  344. }
  345.  
  346. Boolean NumEntryField::lostFocus(IControlEvent& ctl)
  347. {
  348.  
  349.    FormEntryField::lostFocus(ctl);
  350.  
  351.    double dblThis = getDouble();
  352.  
  353.    if(text().lowerCase().length())
  354.    setText(format(dblThis, booThous));
  355.  
  356.    /* if dblMin != dblMax means there is a range of validity */
  357.    if(
  358.    (dblThis < dblMin || dblThis > dblMax)
  359.    && dblMin != dblMax
  360.    && text().strip().length()
  361.    ) {
  362.       setColor(background, IColor(IColor::red));
  363.       setColor(foreground, IColor(IColor::white));
  364.    }
  365.  
  366.    return false;
  367. }
  368.  
  369. /* ====================== DateEntryField =================== */
  370.  
  371. DateEntryField::DateEntryField(unsigned long id, IWindow * parent,
  372. IWindow * owner, const IRectangle & rect,
  373. const IEntryField::Style & style)
  374. :FormEntryField(id, parent, owner, rect, style)
  375. {
  376.    booNoYear = false;
  377.    setAlignment(right);
  378. }
  379.  
  380. DateEntryField::DateEntryField(unsigned long l, IWindow * iw, Boolean b1)
  381. :FormEntryField(l, iw), booNoYear(b1)
  382. {
  383.    setAlignment(right);
  384. }
  385.  
  386. DateEntryField::DateEntryField(unsigned long l,
  387. IWindow * iw, IWindow * iw1, const IRectangle & r, Boolean b1)
  388. :FormEntryField(l, iw, iw1, r), booNoYear(b1)
  389. {
  390.    setAlignment(right);
  391. }
  392.  
  393. Boolean DateEntryField::characterKeyPress(IKeyboardEvent& keyevt)
  394. {
  395.    USHORT i, j, SepPos[2], Da, Mo;
  396.  
  397.    /* if last char is a separator replace with the standard separator */
  398.    if( text().length() > 1)
  399.    if(((IString)FORM_DATE_SEP).includes(text()[text().length()]))
  400.    setText(text().subString(1,text().length()-1)+CountryInfo.szDateSeparator);
  401.  
  402.    /* search separators */
  403.    j=0;
  404.    for (i= 1 ; (i <= text().length()) && (j < 2); i++ )
  405.    /* check for possible separators */
  406.    if ( strchr(FORM_DATE_SEP, text()[i]) ) SepPos[j++]= i;
  407.    /* j number of separators found */
  408.  
  409.    CHAR ch= keyevt.character();
  410.  
  411.    /* only 2 separators allowed */
  412.    if (((IString)FORM_DATE_SEP).includes(ch) && j == 2) return true;
  413.  
  414.    if (!(
  415.    (ch >= '0' && ch <= '9')
  416.    || ((IString)FORM_DATE_SEP).includes(ch)
  417.    )) return true;
  418.  
  419.    if ((
  420.    ((cursorPosition() == 2 && ( j == 0 || (j == 1 && SepPos[0] > 2)))
  421.    ||
  422.    (cursorPosition() == SepPos[0]+2 && j == 1))
  423.    && !((IString)FORM_DATE_SEP).includes(ch)
  424.    )) {
  425.       /* user entered a number in a position where a
  426.       separator should be, put separator */
  427.       IString str1 = text();
  428.       short usCurPos = cursorPosition();
  429.       setText(str1.subString(1, usCurPos)
  430.       +CountryInfo.szDateSeparator+
  431.       str1.subString(usCurPos+1, str1.length() - usCurPos));
  432.       setCursorPosition(usCurPos+1);
  433.    }
  434.  
  435.    return false;
  436. }
  437.  
  438. IDate DateEntryField::getDate()
  439. {
  440.    USHORT SepPos[2];
  441.    USHORT i, j= 0, Da, Mo, Ye;
  442.    IString temps= this->text();
  443.    IDate dat1= 0;
  444.  
  445.    temps.strip();
  446.    if((temps.length() < 6) && (!booNoYear)) return dat1;
  447.    if((temps.length() < 4) && booNoYear) return dat1;
  448.  
  449.    /* search separators */
  450.    for (i= 1 ; (i <= temps.length()) && (j < 2); i++ )
  451.    /* check for possible separators */
  452.    if ( strchr(FORM_DATE_SEP, temps[i]) ) SepPos[j++]= i;
  453.  
  454.    if ((j != 2) && (!booNoYear)) return dat1;
  455.  
  456.    /* read as dd/mm/yy or dd/mm if noyear */
  457.    Da= atoi(temps.subString(1, SepPos[0]-1));
  458.    if(booNoYear) {
  459.       /* year = 1500 means this date represent a day/month set only */
  460.       Mo= atoi(temps.subString(SepPos[0]+1,temps.length()-SepPos[0]));
  461.       Ye= 1500;
  462.    } else {
  463.       Mo= atoi(temps.subString(SepPos[0]+1,SepPos[1]-SepPos[0]-1));
  464.       Ye= atoi(temps.subString(SepPos[1]+1,temps.length()-SepPos[1]));
  465.    }
  466.  
  467.    switch (CountryInfo.fsDateFmt) {
  468.  
  469.       case(0):
  470.       /* it is to be interpreted as mm/dd/yy or mm/dd */
  471.       /* swap mm with dd */
  472.       i = Mo;
  473.       Mo = Da;
  474.       Da = i;
  475.  
  476.       break;
  477.  
  478.       case (1):
  479.       break;
  480.  
  481.       case (2):
  482.       /* it is to be interpreted as yy/mm/dd, DO NOT ADMIT noYear */
  483.  
  484.       if(booNoYear) {
  485.          /* invalidate */
  486.          Da = 0;
  487.       }
  488.  
  489.       /* swap yy with dd */
  490.       i = Ye;
  491.       Ye = Da;
  492.       Da = i;
  493.  
  494.       break;
  495.  
  496.    }
  497.  
  498.    /* year offset is now taken into account if year between 1970 and 2069 */
  499.    /* if year < 70 it's beyond 2000 !!! */
  500.    if(Ye < 70) Ye += 2000;
  501.    else
  502.    /* if year is > 100 user entered in format ccyy */
  503.    if(Ye < 100) Ye += 1900;
  504.  
  505.    if(IDate::isValid((IDate::Month)Mo,Da,Ye)) {
  506.       dat1= IDate((IDate::Month)Mo,Da,Ye);
  507.    }
  508.  
  509.    return dat1;
  510.  
  511. }
  512.  
  513. DateEntryField & DateEntryField::setDate(IDate& d)
  514. {
  515.    IString strSep= IString(CountryInfo.szDateSeparator);
  516.    IString strYearFormat, strNoYearFormat;
  517.  
  518.    if(d.julianDate()) {
  519.  
  520.       switch (CountryInfo.fsDateFmt) {
  521.  
  522.          case(0):
  523.          strYearFormat= IString("%m") + strSep + IString("%d") + strSep + IString("%Y");
  524.          strNoYearFormat= IString("%m") + strSep + IString("%d");
  525.          break;
  526.  
  527.          case(1):
  528.          strYearFormat= IString("%d") + strSep + IString("%m") + strSep + IString("%Y");
  529.          strNoYearFormat= IString("%d") + strSep + IString("%m");
  530.          break;
  531.  
  532.          case(2):
  533.          strYearFormat= IString("%Y") + strSep + IString("%m") + strSep + IString("%d");
  534.          strNoYearFormat= IString("%m") + strSep + IString("%d");
  535.          break;
  536.  
  537.       } /* endswitch */
  538.  
  539.       if(booNoYear) {
  540.          setText(d.asString(strNoYearFormat));
  541.       } else {
  542.          setText(d.asString(strYearFormat));
  543.       }
  544.  
  545.    } else {
  546.  
  547.       setText("");
  548.  
  549.    }
  550.  
  551.    return (DateEntryField &)(*this);
  552. }
  553.  
  554. IString DateEntryField::getTextWithDefault()
  555. /* get date as string returning 1/1/1700 if
  556. invalid date (for DB) */
  557. {
  558.    IDate dat1 = getDate();
  559.  
  560.    if( !dat1.julianDate() ) {
  561.       dat1= IDate((IDate::Month)1,1,1700);
  562.    }
  563.  
  564.    return DateToString(dat1, false, true);
  565. }
  566.  
  567. DateEntryField & DateEntryField::setTextWithDefault(IString s)
  568. /* set date from string considering 1/1/1700 as
  569. invalid date (for DB) */
  570. {
  571.    IDate d = StringToDate(s);
  572.  
  573.    /* consider 1/1/1700 as default not to be displayed */
  574.    if(d.dayOfYear() == 1 && d.year() == 1700) {
  575.       d = 0;
  576.    }
  577.  
  578.    return setDate(d);
  579.  
  580. }
  581.  
  582. Boolean DateEntryField::lostFocus(IControlEvent& ctl)
  583. {
  584.    IDate dat1= getDate();
  585.  
  586.    FormEntryField::lostFocus(ctl);
  587.  
  588.    if(dat1.julianDate()) {
  589.       setDate(dat1);
  590.    } else {
  591.       if(text().strip().length()) {
  592.          setColor(background, IColor(IColor::red));
  593.          setColor(foreground, IColor(IColor::white));
  594.       }
  595.    }
  596.  
  597.    return false;
  598. }
  599.  
  600. /* ====================== TimeEntryField =================== */
  601.  
  602. TimeEntryField::TimeEntryField(unsigned long id, IWindow * parent,
  603. IWindow * owner, const IRectangle & rect,
  604. const IEntryField::Style & style)
  605. :FormEntryField(id, parent, owner, rect, style)
  606. {
  607.    setAlignment(right);
  608. }
  609.  
  610. TimeEntryField::TimeEntryField(unsigned long l, IWindow * iw)
  611. :FormEntryField(l, iw)
  612. {
  613.    setAlignment(right);
  614. }
  615.  
  616. TimeEntryField::TimeEntryField(unsigned long l, IWindow * iw, IWindow * iw1, const IRectangle & r)
  617. :FormEntryField(l, iw, iw1, r)
  618. {
  619.    setAlignment(right);
  620. }
  621.  
  622. Boolean TimeEntryField::characterKeyPress(IKeyboardEvent& keyevt)
  623. {
  624.    USHORT i, j, SepPos[2];
  625.  
  626.    /* if last char is a separator replace with the standard separator */
  627.    if( text().length() > 1)
  628.    if(((IString)FORM_TIME_SEP).includes(text()[text().length()]))
  629.    setText(text().subString(1,text().length()-1)+":");
  630.  
  631.    /* search separators */
  632.    j=0;
  633.    for (i= 1 ; (i <= text().length()) && (j < 2); i++ )
  634.    /* check for possible separators */
  635.    if ( strchr(FORM_TIME_SEP, text()[i]) ) SepPos[j++]= i;
  636.    /* j number of separators found */
  637.  
  638.    CHAR ch= keyevt.character();
  639.  
  640.    /* only 2 separators allowed */
  641.    if (((IString)FORM_TIME_SEP).includes(ch) && j == 2) return true;
  642.  
  643.    if (!(
  644.    (ch >= '0' && ch <= '9')
  645.    || ((IString)FORM_TIME_SEP).includes(ch)
  646.    )) return true;
  647.  
  648.    if (!(
  649.    (ch >= '0' && ch <= '9')
  650.    || ((IString)FORM_DATE_SEP).includes(ch)
  651.    )) return true;
  652.  
  653.    if ((
  654.    ((cursorPosition() == 2 && ( j == 0 || (j == 1 && SepPos[0] > 2)))
  655.    ||
  656.    (cursorPosition() == SepPos[0]+2 && j == 1))
  657.    && !((IString)FORM_TIME_SEP).includes(ch)
  658.    )) {
  659.       /* user entered a number in a position where a
  660.       separator should be, put separator */
  661.       IString str1 = text();
  662.       short usCurPos = cursorPosition();
  663.       setText(str1.subString(1, usCurPos)
  664.       +CountryInfo.szTimeSeparator+
  665.       str1.subString(usCurPos+1, str1.length() - usCurPos));
  666.       setCursorPosition(usCurPos+1);
  667.    }
  668.  
  669.    return false;
  670. }
  671.  
  672. ITime TimeEntryField::getTime()
  673. {
  674.    USHORT SepPos[2];
  675.    USHORT i, j= 0, Hour, Min, Sec;
  676.    IString temps= this->text();
  677.    ITime tim1= 0;
  678.  
  679.    temps.strip();
  680.    if(temps.length() < 4) return tim1;
  681.  
  682.    /* search separators */
  683.    for (i= 1 ; (i <= temps.length()) && (j < 2); i++ )
  684.    /* check for possible separators */
  685.    if ( strchr(FORM_TIME_SEP, temps[i]) ) SepPos[j++]= i;
  686.  
  687.    if (j == 0) return tim1;
  688.  
  689.    Hour= atoi(temps.subString(1, SepPos[0]-1));
  690.  
  691.    if (j == 1) SepPos[1]= temps.length()+1;
  692.  
  693.    Min= atoi(temps.subString(SepPos[0]+1,SepPos[1]-SepPos[0]-1));
  694.  
  695.    if(j == 2) {
  696.       Sec= atoi(temps.subString(SepPos[1]+1,temps.length()-SepPos[1]));
  697.    } else {
  698.       Sec= 0;
  699.    }
  700.  
  701.    tim1= ITime(Hour, Min, Sec);
  702.  
  703.    return tim1;
  704.  
  705. }
  706.  
  707. TimeEntryField & TimeEntryField::setTime(ITime& t)
  708. {
  709.    IString strSep= IString(CountryInfo.szTimeSeparator);
  710.    IString strFormat;
  711.  
  712.    if(t.asSeconds()) {
  713.       strFormat= IString("%H") + strSep + IString("%M") + strSep + IString("%S");
  714.       setText(t.asString(strFormat));
  715.    }
  716.  
  717.    return (TimeEntryField &)(*this);
  718. }
  719.  
  720. Boolean TimeEntryField::lostFocus(IControlEvent& ctl)
  721. {
  722.    ITime tim1= getTime();
  723.  
  724.    FormEntryField::lostFocus(ctl);
  725.  
  726.    if(tim1.asSeconds()) {
  727.       setTime(tim1);
  728.    } else {
  729.       if(text().strip().length()) {
  730.          setColor(background, IColor(IColor::red));
  731.          setColor(foreground, IColor(IColor::white));
  732.       }
  733.    }
  734.  
  735.    return false;
  736. }
  737.  
  738. IString TimeEntryField::getTextWithDefault()
  739. /* get time as string returning 00:00:00 if
  740. invalid time (for DB) */
  741. {
  742.    ITime tim1 = getTime();
  743.  
  744.    if( !tim1.asSeconds() ) {
  745.       return (IString)"00:00:00";
  746.    }
  747.  
  748.    return tim1.asString("%H:%M:%S");
  749. }
  750.  
  751.  
  752.