[main]    [up]  

WxExtLib - WxMisc.cpp

00001: 
00002: /*
00003: -------------------------------------------------------------------------
00004: This file is part of WxWidgetsExtensions library.
00005: -------------------------------------------------------------------------
00006: 
00007: WxExtLib (WxWidgetsExtensions) library
00008: -----------------------------
00009: 
00010: COPYRIGHT NOTICE:
00011: 
00012: WxExtLib library Copyright (c) 2003-2007 Daniel Käps
00013: 
00014: The WxWidgetsExtensions library and associated documentation files (the
00015: "Software") is provided "AS IS".  The author(s) disclaim all
00016: warranties, expressed or implied, including, without limitation, the
00017: warranties of merchantability and of fitness for any purpose.  The
00018: author(s) assume no liability for direct, indirect, incidental,
00019: special, exemplary, or consequential damages, which may result from
00020: the use of or other dealings in the Software, even if advised of the
00021: possibility of such damage.
00022: 
00023: Permission is hereby granted, free of charge, to any person obtaining
00024: a copy of this Software, to deal in the Software without restriction,
00025: including without limitation the rights to use, copy, modify, merge,
00026: publish, distribute, sublicense, and/or sell copies of the Software,
00027: and to permit persons to whom the Software is furnished to do so,
00028: subject to the following conditions:
00029: 
00030:  1. The origin of this source code must not be misrepresented.
00031:  2. Altered versions must be plainly marked as such and must not be
00032:     misrepresented as being the original source.
00033:  3. This Copyright notice may not be removed or altered from any 
00034:     source or altered source distribution.
00035: 
00036: End of WxExtLib library Copyright Notice
00037: 
00038: -------------------------------------------------------------------------
00039: */
00040: 
00041: #ifndef _NO_HEADER_INCLUDE
00042: 
00043: #if defined(__GNUG__) && (!defined(__APPLE__)) && (!(defined M_NoPragmaInterface))
00044:     #pragma implementation "WxMisc.cpp"
00045: #endif
00046: 
00047: #include "WxExtLibConfig.h"
00048: 
00049: // For compilers that support precompilation, includes "wx/wx.h".
00050: #include "wx/wxprec.h"
00051: 
00052: #ifdef __BORLANDC__
00053:     #pragma hdrstop
00054: #endif
00055: 
00056: #include "WxMisc.h"
00057: 
00058: #include <wx/mstream.h>
00059: 
00060: #if wxUSE_GUI
00061: #   include <wx/dc.h>
00062: #   include <wx/dcclient.h>
00063: 
00064: #   ifdef M_WxExtLib_IsFilteredDIBEnabled
00065: #       include "magick/studio.h"
00066: #       include "magick/error.h"
00067: #       include "magick/image.h"
00068: #       include "magick/enhance.h"
00069: #       include "magick/constitute.h"
00070: #       include "ImageMagickExtensions.h"
00071: #   endif
00072: #endif // wxUSE_GUI
00073: 
00074: #include "safecast.h"
00075: 
00076: #if (M_WxExtLib_IsUseGraphicsHelper == 1)
00077: #   include <GraphicsMisc.h>
00078: #endif
00079: 
00080: #endif // _NO_HEADER_INCLUDE
00081: 
00082: //=========================================================================
00083: 
00084: wxMinimalTimeInterval::wxMinimalTimeInterval ()
00085: {
00086:     m_IsInitialized = false;
00087: }
00088:     
00089: void wxMinimalTimeInterval::setMinimalTimeInterval (long MinimalTimeIntervalMS)
00090: {
00091:     m_MinimalTimeIntervalMS = MinimalTimeIntervalMS;
00092: }
00093: 
00094: void wxMinimalTimeInterval::setBegin ()
00095: {
00096: #ifdef M_MinimalTimeInterval_UseGetTickCount
00097:     m_BeginUpTimeMS = ::GetTickCount();
00098: #else
00099:     // m_StopWatch.Start ();
00100:     m_BeginTimeMSLongLong = wxGetLocalTimeMillis();
00101: #endif
00102:     m_IsInitialized = true;
00103: }
00104: 
00105: bool wxMinimalTimeInterval::check ()
00106: {
00107:     // return true if start of interval is unspecified, i.e. no start event
00108:     // has taken place
00109:     if (!m_IsInitialized)
00110:       return true;
00111: 
00112: #ifdef M_MinimalTimeInterval_UseGetTickCount
00113:     DWORD CurrentUpTimeMS = ::GetTickCount ();
00114:     DWORD ElapsedTimeMS;
00115:     if (m_BeginUpTimeMS > CurrentUpTimeMS)
00116:       {
00117:         // handle timer overflow?
00118: //      CurrentUpTimeMS += 0xFFFFFFFF - CurrentUpTimeMS;
00119: //      m_BeginUpTimeMS = 0;
00120:         ElapsedTimeMS = CurrentUpTimeMS - m_BeginUpTimeMS;
00121:       }
00122:     else
00123:       {
00124:         ElapsedTimeMS = CurrentUpTimeMS - m_BeginUpTimeMS;
00125:       }
00126:     
00127:     // if (ElapsedTimeMS >= m_MinimalTimeIntervalMS)
00128:     if (cast_is_equal_smaller (m_MinimalTimeIntervalMS, ElapsedTimeMS))
00129:       {
00130:         return true;
00131:       }
00132:     else
00133:       {
00134:         return false;
00135:       }
00136: #else
00137:     // BUG doesn't handle timer overflows (will happen after 
00138:     // about 48 days)
00139:     // return (m_StopWatch.Time () > m_MinimalTimeIntervalMS);
00140: 
00141:     // alternative implementation: use wxGetLocalTimeMillis() which
00142:     // uses wxLongLong and thus has no overflow for about eternal years
00143:     wxLongLong CurrentTimeMSLongLong = wxGetLocalTimeMillis();
00144:     wxLongLong MinimalTimeIntervalMSLongLong = m_MinimalTimeIntervalMS;
00145:     wxLongLong ElapsedTimeMSLongLong = CurrentTimeMSLongLong - m_BeginTimeMSLongLong;
00146: 
00147:     // WARN don't know if ElapsedTimeMS<0 may happen - under e.g. Win9x this seems to be 
00148:     // the case after adjusting the system clock backwards; however, adjusting
00149:     // the system clock forwards will yield incorrect results too -
00150:     // TODO check if adjusting system time influences running processes under 
00151:     // Linux, Unix
00152:     // WARN workaround for ElapsedTimeMS < 0
00153:     if (ElapsedTimeMSLongLong < 0)
00154:       {
00155:         setBegin();
00156:         return false;
00157:       }
00158:     if (ElapsedTimeMSLongLong >= MinimalTimeIntervalMSLongLong)
00159:       {
00160:         return true;
00161:       }
00162:     else
00163:       {
00164:         return false;
00165:       }
00166: #endif
00167: }
00168: 
00169: //=========================================================================
00170: 
00171: bool convertStringToLong (const char * CharPtr, long & Long)
00172: {
00173:     // replacement for:
00174:     // if (sscanf (CharPtr,"%d%c", & TempLong, &DummyChar) !=1 ) { // handle error }
00175: 
00176:     bool IsOk = false;
00177:     char * EndCharPtr = NULL;
00178:     int Base = 10;
00179:     long TempLong = strtol (CharPtr, & EndCharPtr, Base);
00180: 
00181:     if (EndCharPtr != NULL 
00182:         && EndCharPtr != CharPtr 
00183:         && *EndCharPtr == '\0')
00184:       {
00185:         // WARN should use macros for minimal/maximal long values
00186:         // defined in some header file somewhere
00187:         // using macros LONG_MAX and LONG_MIN may require #include <limits.h>
00188:         if ((TempLong != LONG_MAX)
00189:             && (TempLong != LONG_MIN))
00190:           {
00191:             IsOk = true;
00192:             Long = TempLong;
00193:           }
00194:       }
00195:     return IsOk;
00196: }
00197: 
00198: // same as above, but for 'unsigned long' instead of 'long'
00199: bool convertStringToLong (const char * CharPtr, unsigned long & Long)
00200: {
00201:     // replacement for:
00202:     // if (sscanf (CharPtr,"%u%c", & TempLong, &DummyChar) !=1 ) { // handle error }
00203: 
00204:     bool IsOk = false;
00205:     char * EndCharPtr = NULL;
00206:     int Base = 10;
00207:     unsigned long TempLong = strtoul (CharPtr, & EndCharPtr, Base);
00208: 
00209:     if (EndCharPtr != NULL 
00210:         && EndCharPtr != CharPtr 
00211:         && *EndCharPtr == '\0')
00212:       {
00213:         // using macros ULONG_MAX may require #include <limits.h>
00214:         if ((TempLong != ULONG_MAX)
00215:             && (TempLong != 0))
00216:           {
00217:             IsOk = true;
00218:             Long = TempLong;
00219:           }
00220:       }
00221:     return IsOk;
00222: }
00223: 
00224: //=========================================================================
00225: 
00226: void convertAsciiToHtml (const char * AsciiStringCharPtr, wxString & HtmlString,
00227:                          bool IsTranslateNewlines,
00228:                          long WxAsciiToHtmlFlags)
00229: {
00230:     int HtmlStringLength = 0;
00231:     HtmlString.Clear();
00232: 
00233: #   define M_HandleReplace(HtmlCharSequence) \
00234:     \
00235:     if (StageIndex == 0) \
00236:       { \
00237:         /* PERFORMANCE calling strlen() should be replaced by some */ \
00238:         /* static string length table */ \
00239:         HtmlStringLength += strlen(HtmlCharSequence); \
00240:       } \
00241:     else                                       \
00242:       { \
00243:         HtmlString += HtmlCharSequence; \
00244:       }
00245: 
00246: #   define M_HandleNonReplace \
00247:     \
00248:     if (StageIndex == 0) \
00249:       { \
00250:         HtmlStringLength += 1; \
00251:       } \
00252:     else                                       \
00253:       { \
00254:         HtmlString += (char) CharAsInt; \
00255:       }
00256: 
00257:     // now the loop in two stages:
00258:     // - first stage:
00259:     //   determine length of resulting HTML string and pre-alloc to
00260:     //   this length to avoid multiple reallocations
00261:     // - second stage:
00262:     //   do actual replacement/append
00263:     for (int StageIndex = 0; StageIndex < 2; ++StageIndex)
00264:       {
00265:         bool IsLeadingSpace = true;
00266: 
00267:         if (StageIndex == 1)
00268:           {
00269:             HtmlString.Alloc (HtmlStringLength);
00270:           }
00271:     
00272:         const char * CurrentAsciiStringCharPtr = NULL;
00273: 
00274:         // loop over all characters in input string
00275:         for (CurrentAsciiStringCharPtr = AsciiStringCharPtr; 
00276:              *CurrentAsciiStringCharPtr!='\0'; ++CurrentAsciiStringCharPtr)
00277:           {
00278:             char Char = *CurrentAsciiStringCharPtr;
00279:             int CharAsInt = Char;
00280: 
00281:             bool IsSpaceChar = false;
00282: 
00283:             switch (CharAsInt)
00284:               {
00285:               case '<':
00286:                 M_HandleReplace ("&lt;");
00287:                 break;
00288:               case '>':
00289:                 M_HandleReplace ("&gt;");
00290:                 break;
00291:               case '&':
00292:                 M_HandleReplace ("&amp;");
00293:                 break;
00294:               case '"':
00295:                 M_HandleReplace ("&quot;");
00296:                 break;
00297:               case ' ': 
00298:               case '\t': 
00299:                 IsSpaceChar = true;
00300:                 if ((IsLeadingSpace && ((WxAsciiToHtmlFlags & wxAsciiToHtml_ConvertLeadingSpaces) != 0))
00301:                      || ((WxAsciiToHtmlFlags & wxAsciiToHtml_ConvertAllSpaces) != 0))
00302:                   {
00303:                     if (Char == '\t')
00304:                       {
00305:                         M_HandleReplace ("&nbsp;&nbsp;&nbsp;&nbsp;");
00306:                       }
00307:                     else
00308:                       {
00309:                         M_HandleReplace ("&nbsp;");
00310:                       }
00311:                   }
00312:                 else
00313:                   {
00314:                     M_HandleNonReplace;
00315:                   }
00316:                 break;
00317:               case '\r':
00318:                 if (IsTranslateNewlines)
00319:                   {
00320:                     // it is assumed that next character it '\n' and this 
00321:                     // will cause "<br>\r\n" to be appended
00322:                     M_HandleReplace ("");
00323:                   }
00324:                 else
00325:                   {
00326:                     M_HandleNonReplace;
00327:                   }
00328:                 break;
00329:               case '\n':
00330:                 if (IsTranslateNewlines)
00331:                   {
00332:                     M_HandleReplace ("<br>\r\n");
00333: 
00334:                     IsSpaceChar = true;
00335:                     IsLeadingSpace = true;
00336:                   }
00337:                 else
00338:                   {
00339:                     M_HandleNonReplace;
00340:                   }
00341:               default:
00342:                 M_HandleNonReplace;
00343:                 break;
00344:               }
00345: 
00346:             if (IsLeadingSpace && (!IsSpaceChar))
00347:               {
00348:                 IsLeadingSpace = false;
00349:               }
00350:           }
00351:       }
00352: 
00353: #undef M_HandleReplace
00354: #undef M_HandleNonReplace
00355: 
00356: }
00357: 
00358: wxString convertAsciiToHtml (const char * AsciiStringCharPtr,
00359:                              bool IsTranslateNewlines,
00360:                              long WxAsciiToHtmlFlags)
00361: {
00362:     wxString HtmlString;
00363:     convertAsciiToHtml (AsciiStringCharPtr, HtmlString, 
00364:                         IsTranslateNewlines,
00365:                         WxAsciiToHtmlFlags);
00366: 
00367:     return HtmlString;
00368: }
00369: 
00370: //-------------------------------------------------------------------------
00371: 
00372: wxString formatColourToHtmlParam (const wxColour & Colour)
00373: {
00374:     return wxString::Format ("#%02x%02x%02x", 
00375:                              Colour.Red(), Colour.Green(), Colour.Blue());
00376: }
00377: 
00378: //=========================================================================
00379: 
00380: bool getHtmlTagParamAsDouble (const wxHtmlTag & HtmlTag,
00381:                               const wxString & ParamNameString, double * Double)
00382: {
00383:     wxString ParamValueString = HtmlTag.GetParam (ParamNameString);
00384:     return parseDoubleFromAnyLocaleString (ParamValueString, Double);
00385: }
00386: 
00387: bool parseDoubleFromAnyLocaleString (const wxString & InputValueString, double * Double)
00388: {
00389:     // HACK to get around problem with locale for float/double formatting
00390:     // wxString::Format() and HtmlTag::ScanParam() seem to use current locale 
00391:     // settings, but sometimes we want to parse (as strings) hard-coded double 
00392:     // parameters (e.g. occuring in HTML templates)
00393:     // Normally ScanParam() would fail (depending on the locale setting).
00394: 
00395:     // BUG
00396:     // 1) the used approach probably fails if the input strings contains 
00397:     //    thousands-separators (grouping characters)
00398:     // 2) the used approach probably fails if a comma is used to separate
00399:     //    a sequence of numbers (possibly written without spaces)
00400: 
00401:     // WARN
00402:     // - don't know if there are other decimal separator charcaters than
00403:     //   comma and point. If so, parsing for them would have to be added too.
00404: 
00405:     wxString ValueString (InputValueString);
00406: 
00407:     // try to parse in two different ways: once with occurences of
00408:     // points replaced by commas and once with occurences of commas
00409:     // replaced by points
00410:     int WithCommaParsedCharacterCount = 0;
00411:     double WithCommaParsedDouble = 0.;
00412:     ValueString.Replace (".", ",", true);
00413:     int WithCommaParsedArgumentCount = wxSscanf (ValueString.c_str(), "%lf%n", 
00414:                                                  & WithCommaParsedDouble,
00415:                                                  & WithCommaParsedCharacterCount);
00416: 
00417:     int WithPointParsedCharacterCount = 0;
00418:     double WithPointParsedDouble = 0.;
00419:     ValueString.Replace (",", ".", true);
00420:     int WithPointParsedArgumentCount = wxSscanf (ValueString.c_str(), "%lf%n", 
00421:                                                  & WithPointParsedDouble,
00422:                                                  & WithPointParsedCharacterCount);
00423: 
00424:     // determine which of both possible results to use: if both ways we could
00425:     // parse at least on parameter, we use the result where more characters were
00426:     // parsed (quite hacky, admittedly). It would be better to ask for 
00427:     // the setting of the locale, but i don't know which function is available
00428:     // (if any) for this.
00429:     bool IsUsePointParsedDouble = true;
00430:     if (WithPointParsedArgumentCount > 0
00431:         && WithPointParsedArgumentCount == 0)
00432:       {
00433:         IsUsePointParsedDouble = true;
00434:       }
00435:     else if (WithPointParsedArgumentCount == 0
00436:         && WithCommaParsedArgumentCount > 0)
00437:       {
00438:         IsUsePointParsedDouble = false;
00439:       }
00440:     else if (WithPointParsedArgumentCount > 0
00441:         && WithCommaParsedArgumentCount > 0)
00442:       {
00443:         IsUsePointParsedDouble = (WithPointParsedCharacterCount >= WithCommaParsedCharacterCount);
00444:       }
00445: 
00446:     // set function's output values
00447:     int ParsedArgumentCount = IsUsePointParsedDouble 
00448:       ? WithPointParsedArgumentCount : WithCommaParsedArgumentCount;
00449:     if (IsUsePointParsedDouble)
00450:       {
00451:         * Double = WithPointParsedDouble;
00452:       }
00453:     else
00454:       {
00455:         * Double = WithCommaParsedDouble;
00456:       }
00457: 
00458:     return ParsedArgumentCount > 0;
00459: }
00460: 
00461: //=========================================================================
00462: 
00463: wxNumberFormatOptions::wxNumberFormatOptions ()
00464: {
00465:     m_GroupSize = 3;
00466:     m_GroupSeparatorChar = ',';
00467:     m_DecimalSeparatorChar = '.';
00468: }
00469: 
00470: wxNumberFormatOptions::wxNumberFormatOptions (int GroupSize, char GroupSeparatorChar, 
00471:                                               char DecimalSeparatorChar)
00472: {
00473:     set (GroupSize, GroupSeparatorChar, DecimalSeparatorChar);
00474: }
00475: 
00476: void wxNumberFormatOptions::set (int GroupSize, char GroupSeparatorChar, 
00477:                                  char DecimalSeparatorChar)
00478: {
00479:     m_GroupSize = GroupSize;
00480:     m_GroupSeparatorChar = GroupSeparatorChar;
00481:     m_DecimalSeparatorChar = DecimalSeparatorChar;
00482: }
00483: 
00484: //-------------------------------------------------------------------------
00485: 
00486: wxNumberFormattingInternals::wxNumberFormattingInternals()
00487: {
00488:     m_IsOkay = false;
00489: }
00490: 
00491: //-------------------------------------------------------------------------
00492: 
00493: void detectNumberFormattingInternals(wxNumberFormattingInternals * NumberFormattingInternals)
00494: {
00495:     wxString TempString;
00496: 
00497:     bool IsOkay = false;
00498: 
00499:     for_once
00500:       {
00501:         // determine decimal separator string
00502:         double SampleDouble = 1.4;
00503: 
00504:         TempString = wxString::Format ("%f", SampleDouble);
00505:         const char * TempCharPtr = TempString.c_str();
00506: 
00507:         if (TempCharPtr[1] == ',')
00508:           NumberFormattingInternals -> m_DecimalSeparatorChar = ',';
00509:         else if (TempCharPtr[1] == '.')
00510:           NumberFormattingInternals -> m_DecimalSeparatorChar = '.';
00511:         else 
00512:           break;
00513: 
00514:         if ((TempCharPtr[0] != '1') || (TempCharPtr[2] != '4'))
00515:           break;
00516: 
00517:         IsOkay = true;
00518:       }
00519: 
00520:     NumberFormattingInternals -> m_IsOkay = IsOkay;
00521: }
00522: 
00523: //-------------------------------------------------------------------------
00524: 
00525: void formatLong (const wxString & FormatString, 
00526:                  wxNumberFormatOptions & NumberFormatOptions, 
00527:                  long Long, 
00528:                  wxString & String, 
00529:                  wxNumberFormattingInternals * NumberFormattingInternals)
00530: {
00531:     // example: -123456.789 -> -123,456.789
00532: 
00533:     if (NumberFormattingInternals == NULL)
00534:       {
00535:         wxNumberFormattingInternals TempNumberFormattingInternals;
00536:         detectNumberFormattingInternals (& TempNumberFormattingInternals);
00537:         NumberFormattingInternals = & TempNumberFormattingInternals;
00538:       }
00539: 
00540:     if (!NumberFormattingInternals -> m_IsOkay)
00541:       {
00542:         String = wxString::Format (FormatString, Long);
00543:         return;
00544:       }
00545: 
00546:     // format into temporary string and add grouping if desired
00547:     wxString TempString;
00548:     TempString = wxString::Format (FormatString, Long);
00549: 
00550:     formatNumberStringWithGrouping (TempString,
00551:                                     NumberFormatOptions,
00552:                                     String,
00553:                                     NumberFormattingInternals);
00554: }
00555: 
00556: void formatDouble (const wxString & FormatString, 
00557:                    wxNumberFormatOptions & NumberFormatOptions, 
00558:                    double Double, 
00559:                    wxString & String, 
00560:                    wxNumberFormattingInternals * NumberFormattingInternals)
00561: {
00562:     // example: -123456.789 -> -123,456.789
00563: 
00564:     wxNumberFormattingInternals TempNumberFormattingInternals;
00565:     if (NumberFormattingInternals == NULL)
00566:       {
00567:         detectNumberFormattingInternals (& TempNumberFormattingInternals);
00568:         NumberFormattingInternals = & TempNumberFormattingInternals;
00569:       }
00570: 
00571:     if (!NumberFormattingInternals -> m_IsOkay)
00572:       {
00573:         String = wxString::Format (FormatString, Double);
00574:         return;
00575:       }
00576: 
00577:     // format into temporary string and add grouping if desired
00578:     wxString TempString;
00579:     TempString = wxString::Format (FormatString, Double);
00580: 
00581:     formatNumberStringWithGrouping (TempString,
00582:                                     NumberFormatOptions,
00583:                                     String,
00584:                                     NumberFormattingInternals);
00585: }
00586: 
00587: //-------------------------------------------------------------------------
00588: 
00589: void formatNumberStringWithGrouping (const wxString & NumberString, 
00590:                                      wxNumberFormatOptions & NumberFormatOptions, 
00591:                                      wxString & String, 
00592:                                      wxNumberFormattingInternals * NumberFormattingInternals)
00593: {
00594:     /* from manual page of fprintf():
00595:        For some numeric conversions a radix character (`decimal point') or thousands' grouping character is used. The
00596:        actual character used depends on the LC_NUMERIC part of the locale. The POSIX locale uses `.' as radix charac-
00597:        ter, and does not have a grouping character.  Thus,
00598:                    printf("%'.2f", 1234567.89);
00599:        results in `1234567.89' in the POSIX locale, in `1234567,89' in the nl_NL locale, and in `1.234.567,89' in the
00600:        da_DK locale.
00601: 
00602:        thus:
00603:        - newer version of the standard library may have support for using thousand grouping
00604:          characters, on an optional basis
00605:        - the user cannot force use of grouping if his/her locale is not configured for it
00606:        - scanf functions may not understand the grouping character format string flag
00607:     */
00608: 
00609:     // parse formatted temporary string and determine certain positions, such
00610:     // as non-fractional digits
00611:     const char * CharPtr = NumberString.c_str();
00612:     int Index = 0;
00613:     int DecimalSeparatorIndex = -1;
00614:     int DigitStartIndex = -1;
00615:     int DigitEndIndex = -1;
00616:     while (*CharPtr != '\0')
00617:       {
00618:         char Char = *CharPtr;
00619:         if (Char == NumberFormattingInternals -> m_DecimalSeparatorChar)
00620:           {
00621:             if (DecimalSeparatorIndex == -1)
00622:               DecimalSeparatorIndex = Index;
00623:           }
00624: 
00625:         if (wxIsdigit (Char))
00626:           {
00627:             if (DigitStartIndex == -1)
00628:               {
00629:                 DigitStartIndex = Index;
00630:               }
00631:             if ((*(CharPtr + 1) == '\0')
00632:                 && DigitEndIndex == -1)
00633:               {
00634:                 DigitEndIndex = Index + 1;
00635:               }
00636:           }
00637:         else
00638:           {
00639:             if (DigitStartIndex != -1
00640:                 && DigitEndIndex == -1)
00641:               {
00642:                 DigitEndIndex = Index;
00643:               }
00644:           }
00645: 
00646:         ++Index;
00647:         ++CharPtr;
00648:       }
00649: 
00650:     bool IsUseGrouping = NumberFormatOptions.m_GroupSize > 0;
00651:     int GroupCharacterCount = 0;
00652: 
00653:     if (IsUseGrouping
00654:         && (DigitStartIndex != -1) 
00655:         && (DigitEndIndex != -1))
00656:       {
00657:         GroupCharacterCount = ((DigitEndIndex - DigitStartIndex) / NumberFormatOptions.m_GroupSize);
00658:         if (GroupCharacterCount > 0)
00659:           --GroupCharacterCount;
00660:       }
00661: 
00662:     String.Clear();
00663:     String.Alloc (NumberString.Length() + GroupCharacterCount);
00664: 
00665:     // now produce string with inserted grouping characters
00666:     CharPtr = NumberString.c_str();
00667:     Index = 0;
00668:     while (*CharPtr != '\0')
00669:       {
00670:         if (IsUseGrouping
00671:             && (DigitStartIndex != -1) 
00672:             && (DigitEndIndex != -1)
00673:             && (Index >= DigitStartIndex)
00674:             && (Index < DigitEndIndex))
00675:           {
00676:             if ((Index < DigitEndIndex)
00677:                 && (Index > DigitStartIndex)
00678:                 && (((DigitEndIndex - Index) % NumberFormatOptions.m_GroupSize) == 0))
00679:               {
00680:                 // insert grouping character
00681:                 String += NumberFormatOptions.m_GroupSeparatorChar;
00682:               }
00683:           }
00684:         if (Index == DecimalSeparatorIndex)
00685:           {
00686:             // replace decimal separator
00687:             String += NumberFormatOptions.m_DecimalSeparatorChar;
00688:           }
00689:         else
00690:           {
00691:             // otherwise add characters from temporary string
00692:             String += *CharPtr;
00693:           }
00694: 
00695:         ++Index;
00696:         ++CharPtr;
00697:       }
00698: }
00699: 
00700: //-------------------------------------------------------------------------
00701: 
00702: #define M_CheckString(DesiredResult) \
00703:     if (String != DesiredResult) \
00704:       { \
00705:         wxString MessageString; \
00706:         MessageString << "string \"" << String << "\" obtained instead of desired result \"" << DesiredResult << "\""; \
00707:         wxASSERT_MSG (false, MessageString);   \
00708:         IsError = true; \
00709:         break; \
00710:       } \
00711: 
00712: bool testNumberFormat()
00713: {
00714:     wxString String;
00715:     wxNumberFormatOptions NumberFormatOptions (2, '.', ';');
00716: 
00717:     bool IsOkay = false;
00718:     bool IsError = false;
00719:     for_once
00720:       {
00721:         // NOTE: different compilers/libraries may use differing 
00722:         // interpretation of printf() format specifiers, causing M_CheckString
00723:         // to indicate failure
00724: 
00725:         NumberFormatOptions.set (2, '.', ';');
00726:         formatDouble ("%.1f", NumberFormatOptions, 12345678.9, String);
00727:         M_CheckString ("12.34.56.78;9");
00728: 
00729:         NumberFormatOptions.set (2, '.', ';');
00730:         formatDouble ("%g", NumberFormatOptions, 9, String);
00731:         M_CheckString ("9");
00732: 
00733:         NumberFormatOptions.set (2, '.', ';');
00734:         formatDouble ("%g", NumberFormatOptions, 9e50, String);
00735: #if (defined(_MSC_VER)) // ?? || (defined(__BORLANDC__))
00736:         M_CheckString ("9e+050");
00737: #else
00738:         M_CheckString ("9e+50");
00739: #endif
00740: 
00741:         NumberFormatOptions.set (4, '.', ';');
00742:         formatDouble ("%g", NumberFormatOptions, 23456789, String);
00743: #if (defined(_MSC_VER)) // ?? || (defined(__BORLANDC__))
00744:         M_CheckString ("2;34568e+007");
00745: #else
00746:         M_CheckString ("2;34568e+07");
00747: #endif
00748: 
00749:         NumberFormatOptions.set (1, ' ', ';');
00750:         formatDouble ("%.0f", NumberFormatOptions, -3456789, String);
00751:         M_CheckString ("-3 4 5 6 7 8 9");
00752: 
00753:         NumberFormatOptions.set (4, '.', ';');
00754:         formatDouble ("%g", NumberFormatOptions, 56789, String);
00755:         M_CheckString ("5.6789");
00756: 
00757:         NumberFormatOptions.set (4, '.', ';');
00758:         formatDouble ("%g", NumberFormatOptions, 6789, String);
00759:         M_CheckString ("6789");
00760: 
00761:         // still, specified field width is modified because of inserting
00762:         // grouping characters
00763:         NumberFormatOptions.set (3, '.', ',');
00764:         formatLong ("%14ld", NumberFormatOptions, -1123456789, String);
00765:         M_CheckString ("   -1.123.456.789");
00766: 
00767:         NumberFormatOptions.set (3, '.', ',');
00768:         formatLong ("%ld", NumberFormatOptions, 0, String);
00769:         M_CheckString ("0");
00770: 
00771:         IsOkay = true;
00772:       }
00773: 
00774:     return IsOkay;
00775: }
00776: 
00777: #undef M_CheckString
00778: 
00779: //=========================================================================
00780: 
00781: wxDateTime::Month getMonthFromMonthIndex (int MonthIndex) // MonthIndex starting from 1, _not_ 0!
00782: {
00783:     switch (MonthIndex)
00784:       {
00785:         case 1: return wxDateTime::Jan;
00786:         case 2: return wxDateTime::Feb;
00787:         case 3: return wxDateTime::Mar;
00788:         case 4: return wxDateTime::Apr;
00789:         case 5: return wxDateTime::May;
00790:         case 6: return wxDateTime::Jun;
00791:         case 7: return wxDateTime::Jul;
00792:         case 8: return wxDateTime::Aug;
00793:         case 9: return wxDateTime::Sep;
00794:         case 10: return wxDateTime::Oct;
00795:         case 11: return wxDateTime::Nov;
00796:         case 12: return wxDateTime::Dec;
00797:       }
00798:     return wxDateTime::Inv_Month;
00799: }
00800: 
00801: int getMonthIndexFromMonth (wxDateTime::Month Month) // MonthIndex starting from 1, _not_ 0!
00802: {
00803:     switch (Month)
00804:       {
00805:         case wxDateTime::Jan: return 1;
00806:         case wxDateTime::Feb: return 2;
00807:         case wxDateTime::Mar: return 3;
00808:         case wxDateTime::Apr: return 4;
00809:         case wxDateTime::May: return 5;
00810:         case wxDateTime::Jun: return 6;
00811:         case wxDateTime::Jul: return 7;
00812:         case wxDateTime::Aug: return 8;
00813:         case wxDateTime::Sep: return 9;
00814:         case wxDateTime::Oct: return 10;
00815:         case wxDateTime::Nov: return 11;
00816:         case wxDateTime::Dec: return 12;
00817:       default:
00818:         break;
00819:       }
00820:     return 0;
00821: }
00822: 
00823: //=========================================================================
00824: 
00825: void getDecomposedDateFormatString (const wxString & InputFormatString,
00826:                                     wxString & DecomposedDateFormatString)
00827: {
00828:     // our sample date: Monday, 22 October 1990
00829:     // - the numbers should be unique (don't use 12 December or the like)
00830:     // - the numbers should be 2-digit (so we don't have to care if a leading
00831:     //   zero is printed or is not printed) - to simplify things a little
00832:     wxDateTime SampleDateTime (/* day */ 22, 
00833:                              /* month */ wxDateTime::Oct, 
00834:                              /* year */ 1990);
00835:     //  wxDateTime_t hour = 0, wxDateTime_t minute = 0,
00836:     // wxDateTime_t second = 0, wxDateTime_t millisec = 0)    
00837: 
00838:     // WARN
00839:     // - maybe it would be more appropriate to call CallStrftime() directly
00840:     //   instead of calling wxDateTime::Format()
00841:     // - should check if wxDateTime::Format()/CallStrftime() returned
00842:     //   an error
00843: 
00844:     // get abbreviated and full weekday string for Monday for current locale
00845:     wxString AbbreviatedSampleWeekdayString = SampleDateTime.Format ("%a"); 
00846:     wxString FullSampleWeekdayString = SampleDateTime.Format ("%A");
00847: 
00848:     // get abbreviated and full month name for October for current locale
00849:     wxString AbbreviatedSampleMonthString = SampleDateTime.Format ("%b"); 
00850:     wxString FullSampleMonthString = SampleDateTime.Format ("%B");
00851: 
00852:     // format the sample date
00853:     wxString SampleDateTimeString = SampleDateTime.Format (InputFormatString);
00854: 
00855:     // replace occurences of "%" with "%%" first:
00856:     SampleDateTimeString.Replace ("%", "%%");
00857: 
00858:     // BUG: simply searching/replacing "%X" is incorrect if the format 
00859:     // string contains the sequence "%%" (then, the "%a" in "%%a" is not
00860:     // a placeholder) - to fix, add full parsing of format string
00861:     // 
00862:     SampleDateTimeString.Replace (FullSampleWeekdayString, "%A");
00863:     SampleDateTimeString.Replace (AbbreviatedSampleWeekdayString, "%a");
00864:     SampleDateTimeString.Replace ("22", "%d");
00865:     SampleDateTimeString.Replace (FullSampleMonthString, "%B");
00866:     SampleDateTimeString.Replace (AbbreviatedSampleMonthString, "%b");
00867:     SampleDateTimeString.Replace ("10", "%m");
00868:     SampleDateTimeString.Replace ("1990", "%Y");
00869:     SampleDateTimeString.Replace ("90", "%y"); // maybe use %Y here too
00870: 
00871:     // now, SampleDateTimeString should contain a valid format string according
00872:     // to the current locale setting
00873:     DecomposedDateFormatString = SampleDateTimeString;
00874: 
00875:     // TODO: add checking if it was actually possible to determine
00876:     // the decomposed format string; add a fall-back
00877: }
00878: 
00879: void getDecomposedDateFormatStringX (wxString & DecomposedDateFormatString,
00880:                                      bool IsLongFormat)
00881: {
00882:     if (IsLongFormat)
00883:       {
00884: #if defined(__WXMSW__)
00885: #if (!defined(_MSC_VER)) && (!defined(__BORLANDC__))
00886: #   pragma message ("Please check if your compiler/OS uses '%%#x' or '%%Ex' for alternative date format")
00887: #endif
00888:         // the format string to indicate alternative date/time 
00889:         // representation differs in MSW/VC++, Borland C++
00890:         // TODO check which other compilers use %#c instead of %Ec
00891:         getDecomposedDateFormatString ("%#x", DecomposedDateFormatString);
00892: #else
00893:         getDecomposedDateFormatString ("%Ex", DecomposedDateFormatString);
00894: #endif
00895:       }
00896:     else
00897:       {
00898:         getDecomposedDateFormatString ("%x", DecomposedDateFormatString);
00899:       }
00900: }
00901: 
00902: bool removeWeekdayFromDateFormatString (const wxString & DateFormatString,
00903:                                         wxString & WithoutWeekdayDateFormatString)
00904: {
00905:     // make format string with weekday placeholder removed:
00906:     // remove %a or %A, remove following spaces, punctuation characters etc.
00907:     // WARN may have to remove spaces, punctuation characters before %a, %A as well
00908:     //
00909:     // BUG: simply searching for "%X" is incorrect if the format string
00910:     // contains the sequence "%%" (then, the "%a" in "%%a" is not
00911:     // a placeholder) - to fix, add full parsing of format string
00912:     // 
00913:     int WeekdayPlaceholderCharIndex = DateFormatString.Find ("%a");
00914:     if (WeekdayPlaceholderCharIndex == wxNOT_FOUND)
00915:       WeekdayPlaceholderCharIndex = DateFormatString.Find ("%A");
00916:     if (WeekdayPlaceholderCharIndex != wxNOT_FOUND)
00917:       {
00918:         int CurrentCharIndex = WeekdayPlaceholderCharIndex + 2 /* strlen ("%a") */;
00919:         for (; cast_is_smaller (CurrentCharIndex, DateFormatString.Length());
00920:              ++CurrentCharIndex)
00921:           {
00922:             int CurrentChar = DateFormatString [CurrentCharIndex];
00923:             if (!(wxIsspace (CurrentChar)
00924:                   || (wxIspunct (CurrentChar) && CurrentChar != '%')))
00925:               break;
00926:           }
00927:         WithoutWeekdayDateFormatString = DateFormatString;
00928:         WithoutWeekdayDateFormatString.Remove (WeekdayPlaceholderCharIndex, 
00929:                                                CurrentCharIndex-WeekdayPlaceholderCharIndex);
00930: 
00931:         return true;
00932:       }
00933:     return false;
00934: }
00935: 
00936: //-------------------------------------------------------------------------
00937: 
00938: void formatDate (const wxDateTime & DateTime, wxString & String, 
00939:                  bool IsLongFormat)
00940: {
00941:     // NOTE date formatting using "%#x" or "%Ex"
00942:     // sometimes wxDateTime uses its own implementation which 
00943:     // doesn't understand 'E' or '#'. The wxWindows implementation
00944:     // is apparently used for dates before 2 Janary 1970
00945:     // (an assertion failure is reported, and the output string
00946:     // is set to the format string minus the percent character)
00947:     // 
00948:     // following hack is not required anymore, now there
00949:     // is getDecomposedDateFormatString() which works better
00950:     // 
00951:     // if (TextCtrlContentString.IsSameAs ("#x")
00952:     //  || TextCtrlContentString.IsSameAs ("Ex"))
00953:     //   {
00954:     //  // since we don't know if the current locale has 
00955:     //  // DAY MONTH or MONTH DAY order, we output the date with the
00956:     //  // month name to avoid any ambiguities
00957:     //  TextCtrlContentString = TempDateTime.Format("%d %B %Y");
00958:     // }
00959: 
00960:     wxString DateFormatString;
00961:     getDecomposedDateFormatStringX (DateFormatString, IsLongFormat);
00962:     
00963:     String = DateTime.Format (DateFormatString);
00964: }
00965: 
00966: //-------------------------------------------------------------------------
00967: 
00968: // parseDate()
00969: // BUG
00970: // - correct parsing of input (in case of occurences of "%%") would
00971: //   be required instead of simply replacing %X, if any of the format
00972: //   strings tried contains "%%"
00973: //
00974: bool parseDate (const wxString & String, wxDateTime & DateTime)
00975: {
00976:     // wxDateTime::ParseDate() works quite well unless the year in the string
00977:     // is 2 digit and less than 31... Such a date string is generated
00978:     // by Format("%#x") if no locale or some English locale was set 
00979:     // (so the output is e.g. 02/19/04)
00980:     // ParseDate() doesn't handle such a date.
00981:     //
00982:     // ParseFormat() may only be able to parse formats like dd/mm/yy or
00983:     // mm/dd/yy, because possibly 'strptime' is not available. 
00984:     // In this case, ParseFormat() cannot parse a date like '2 March 2002'.
00985:     //
00986:     // the following hack was used: The solution is to use try first 
00987:     // ParseFormat() and if it fails try ParseDate(). 
00988:     // However, this still doesn't work well because of the following problem:
00989:     // 
00990:     // possibly BUG in wxDateTime::ParseFormat():
00991:     // for "%x", it uses "%d/%m/%y" as format if the time zone is e.g. European.
00992:     // But the locale setting may well differ from the time zone setting.
00993:     // (scope: wxWindows 2.4.1). 
00994:     // Same problem may exist for ParseDate().
00995:     //
00996:     //!! A solution to this problem would be to make a dummy print of 
00997:     //!! a fixed date like 10 November 2012 (2012-11-10) and then 
00998:     //!! look in the output string if it was printed in day-month 
00999:     //!! or month-day order
01000:     //!! we could even try to construct a format string from the dummy
01001:     //!! result
01002:     // (the last idea is now implemented with getDecomposedDateFormatString())
01003:     //
01004:     // hack is obsolete now since we have getDecomposedDateFormatString()
01005:     // which works well
01006:     // --->
01007:     // WARN see bug in ParseFormat() above
01008:     // const char * EndCharPtr = TempDateTime.ParseFormat (BeginCharPtr, "%x");
01009:     // bool IsOk = true;
01010:     // if ((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0))
01011:     //   {
01012:     //  // try conversion with ParseDate() if ParseFormat() failed
01013:     //  EndCharPtr = TempDateTime.ParseDate (BeginCharPtr);
01014:     //  if ((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0))
01015:     //    {
01016:     //      IsOk = false;
01017:     //    }
01018:     //   }
01019:     // <----
01020: 
01021:     const char * BeginCharPtr = String.c_str();
01022:     const char * EndCharPtr = NULL;
01023: 
01024:     // try parsing the input as short date format:
01025:     wxString ShortDateFormatString;
01026:     getDecomposedDateFormatStringX (ShortDateFormatString, false);
01027:     // note: under some platforms/locals, %x is equal to "%d.%m.%Y,
01028:     // but we must parse with 2-digit year first because a 2-digit year
01029:     // in the input may be interpreted as first-century year by
01030:     // wxDateTime::ParseFormat().
01031:     ShortDateFormatString.Replace ("%Y", "%y"); // make year 2-digit
01032:     EndCharPtr = DateTime.ParseFormat (BeginCharPtr, ShortDateFormatString);
01033:     if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01034:       {
01035:         return true;
01036:       }
01037: 
01038:     // try to parse input as short format, but with 4-digit year now
01039:     ShortDateFormatString.Replace ("%y", "%Y");
01040:       {
01041:         EndCharPtr = DateTime.ParseFormat (BeginCharPtr, ShortDateFormatString);
01042:         if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01043:           {
01044:             return true;
01045:           }
01046:       }
01047: 
01048:     // try to parse input as long date format
01049:     wxString DateFormatString;
01050:     getDecomposedDateFormatStringX (DateFormatString, true);
01051:     EndCharPtr = DateTime.ParseFormat (BeginCharPtr, DateFormatString);
01052:     if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01053:       {
01054:         return true;
01055:       }
01056: 
01057:     // try to parse with weekday removed from long format string:
01058:     wxString WithoutWeekdayDateFormatString;
01059:     if (removeWeekdayFromDateFormatString (DateFormatString, 
01060:                                            WithoutWeekdayDateFormatString))
01061:       {
01062:         const char * EndCharPtr = DateTime.ParseFormat (BeginCharPtr, 
01063:                                                         WithoutWeekdayDateFormatString);
01064:         if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01065:           {
01066:             return true;
01067:           }
01068:       }
01069: 
01070:     // try to parse input date in ISO-8601 format (e.g. 2004-06-01)
01071:     // WARN 
01072:     // - Danish locale (and some others) may use %d-%m-%y as short date format, 
01073:     //   so this may be ambiguous with ISO-8601 %Y-%m-%d
01074:     // - at least, it would be wise not to use ISO-8601 with a two-digit year
01075:     wxString ISO8601DateFormatString = "%Y-%m-%d";
01076:     int DummyYear = 0;
01077:     int ParsedYearDigits = 0;
01078:     if ((wxSscanf (BeginCharPtr, "%d%n-", & DummyYear, & ParsedYearDigits) >= 1)
01079:         && ParsedYearDigits == 4)
01080:       {
01081:         EndCharPtr = DateTime.ParseFormat (BeginCharPtr, ISO8601DateFormatString);
01082:         if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01083:           {
01084:             return true;
01085:           }
01086:       }
01087: 
01088:     return false;
01089: }
01090: 
01091: //-------------------------------------------------------------------------
01092: 
01093: bool parseDateTimeWithFormat (const wxString & InputString, wxDateTime & DateTime,
01094:                               const wxString & DateTimeFormatString)
01095: {
01096:     const char * BeginCharPtr = InputString.c_str();
01097:     const char * EndCharPtr = NULL;
01098:     {
01099:       // use a different default date/time than default argument for
01100:       // ParseFormat() to get more deterministic behavior (default would
01101:       // be otherwise wxDateTime::Today())
01102:       wxDateTime DefaultDateTime = wxDateTime (1, wxDateTime::Jan, 1970);
01103: 
01104:       EndCharPtr = DateTime.ParseFormat (BeginCharPtr, DateTimeFormatString,
01105:                                          DefaultDateTime);
01106:       if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01107:         {
01108:           return true;
01109:         }
01110:     }
01111:     return false;
01112: }
01113: 
01114: void formatDateTimeWithFormat (const wxDateTime & DateTime, wxString & String,
01115:                                const wxString & DateTimeFormatString)
01116: {
01117:     String = DateTime.Format (DateTimeFormatString);
01118: }
01119: 
01120: //-------------------------------------------------------------------------
01121: 
01122: bool parseDateTimeFromISOFormat (const wxString & InputString, wxDateTime & DateTime)
01123: {
01124:     // try to parse input date in ISO-8601 format (e.g. 2004-06-01)
01125:     // WARN
01126:     // - Danish locale (and some others) may use %d-%m-%y as short date format,
01127:     //   so this may be ambiguous with ISO-8601 %Y-%m-%d
01128:     // - at least, it would be wise not to use ISO-8601 with a two-digit year
01129:     wxString ISODateTimeFormatString = "%Y-%m-%d %H:%M:%S";
01130:     return parseDateTimeWithFormat (InputString, DateTime, 
01131:                                     ISODateTimeFormatString);
01132: }
01133: 
01134: void formatDateTimeInISOFormat (const wxDateTime & DateTime, wxString & String)
01135: {
01136:     String = "";
01137:     String 
01138:       << DateTime.FormatISODate() << " " << DateTime.FormatISOTime();
01139: }
01140: 
01141: 
01142: //=========================================================================
01143: 
01144: void fitInside (const wxRect & FrameRect, const wxSize & ObjectSize, 
01145:                 wxRect & FittedObjectRect, int AlignmentFlags)
01146: {
01147:     int FrameRectWidth = FrameRect.GetWidth();
01148:     int FrameRectHeight = FrameRect.GetHeight();
01149:     int FittedX = FrameRect.GetX();
01150:     int FittedY = FrameRect.GetY();
01151:     int FittedWidth;
01152:     int FittedHeight;
01153:     double FrameRectWidthHeightRatio = (double) FrameRectWidth
01154:       / (double) FrameRectHeight;
01155:     double ObjectWidthHeightRatio = (double) ObjectSize.GetWidth()
01156:       / (double) ObjectSize.GetHeight();
01157: 
01158:     if (FrameRectWidthHeightRatio > ObjectWidthHeightRatio)
01159:       {
01160:         cast_round_assign (FittedWidth, FrameRectHeight * ObjectWidthHeightRatio);
01161:         FittedHeight = FrameRectHeight;
01162: 
01163:         if (AlignmentFlags & wxALIGN_CENTER_HORIZONTAL)
01164:           {
01165:             FittedX += (FrameRectWidth - FittedWidth) / 2;
01166:           }
01167:         else if (AlignmentFlags & wxALIGN_RIGHT)
01168:           {
01169:             FittedX += (FrameRectWidth - FittedWidth);
01170:           }
01171:       }
01172:     else
01173:       {
01174:         FittedWidth = FrameRectWidth;
01175:         cast_round_assign (FittedHeight, FrameRectWidth * 1/ObjectWidthHeightRatio);
01176: 
01177:         if (AlignmentFlags & wxALIGN_CENTER_VERTICAL)
01178:           {
01179:             FittedY += (FrameRectHeight - FittedHeight) / 2;
01180:           }
01181:         else if (AlignmentFlags & wxALIGN_BOTTOM)
01182:           {
01183:             FittedY += (FrameRectHeight - FittedHeight);
01184:           }
01185:       }
01186: 
01187:     FittedObjectRect = wxRect (FittedX, FittedY, FittedWidth, FittedHeight);
01188: }
01189: 
01190: //=========================================================================
01191: 
01192: void makePath (const wxString & LhsPathString,
01193:                const wxString & RhsPathString,
01194:                wxString & ResultPathString,
01195:                wxPathFormat LhsPathFormat,
01196:                wxPathFormat RhsPathFormat,
01197:                wxPathFormat ResultPathFormat)
01198: {
01199:     wxFileName FileName (RhsPathString, RhsPathFormat);
01200:     // alternative could be to use wxFileName::AppendDir() or
01201:     // wxFileName::PrependDir()
01202:     FileName.MakeAbsolute (LhsPathString, LhsPathFormat);
01203:     ResultPathString = FileName.GetFullPath (ResultPathFormat);
01204: }
01205: 
01206: wxString makePath (const wxString & LhsPathString,
01207:                    const wxString & RhsPathString,
01208:                    wxPathFormat LhsPathFormat,
01209:                    wxPathFormat RhsPathFormat,
01210:                    wxPathFormat ResultPathFormat)
01211: {
01212:     wxString ResultString;
01213:     makePath (LhsPathString, 
01214:               RhsPathString,
01215:               ResultString,
01216:               LhsPathFormat,
01217:               RhsPathFormat,
01218:               ResultPathFormat);
01219:     return ResultString;
01220: }
01221: 
01222: //-------------------------------------------------------------------------
01223: 
01224: void makeAbsolutePath (const wxString & RelativeOrAbsolutePathString,
01225:                        const wxString & ReferenceDirString,
01226:                        wxString & AbsolutePathString,
01227:                        wxPathFormat RelativeOrAbsolutePathFormat,
01228:                        wxPathFormat ReferenceDirFormat,
01229:                        wxPathFormat AbsolutePathFormat)
01230: {
01231:     wxFileName FileName (RelativeOrAbsolutePathString, RelativeOrAbsolutePathFormat);
01232:     // alternative could be to use wxFileName::AppendDir() or
01233:     // wxFileName::PrependDir()
01234:     FileName.MakeAbsolute (ReferenceDirString, ReferenceDirFormat);
01235:     AbsolutePathString = FileName.GetFullPath (AbsolutePathFormat);
01236: }
01237: 
01238: wxString makeAbsolutePath (const wxString & RelativeOrAbsolutePathString,
01239:                            const wxString & ReferenceDirString,
01240:                            wxPathFormat RelativeOrAbsolutePathFormat,
01241:                            wxPathFormat ReferenceDirFormat,
01242:                            wxPathFormat AbsolutePathFormat)
01243: {
01244:     wxString AbsolutePathString;
01245:     makeAbsolutePath (RelativeOrAbsolutePathString,
01246:                       ReferenceDirString,
01247:                       AbsolutePathString,
01248:                       RelativeOrAbsolutePathFormat,
01249:                       ReferenceDirFormat,
01250:                       AbsolutePathFormat);
01251:     return AbsolutePathString;
01252: }
01253: 
01254: //-------------------------------------------------------------------------
01255: 
01256: void makeRelativePath (const wxString & RelativeOrAbsolutePathString,
01257:                        const wxString & ReferenceDirString,
01258:                        wxString & RelativePathString,
01259:                        bool IsUseRelativeParentDir,
01260:                        wxPathFormat RelativeOrAbsolutePathFormat,
01261:                        wxPathFormat ReferenceDirFormat,
01262:                        wxPathFormat RelativePathFormat)
01263: {
01264:     wxFileName FileName (RelativeOrAbsolutePathString, RelativeOrAbsolutePathFormat);
01265:     FileName.MakeRelativeTo (ReferenceDirString, ReferenceDirFormat);
01266: 
01267:     if ((!IsUseRelativeParentDir)
01268:         && (FileName.GetFullPath().StartsWith ("..")))
01269:       {
01270:         RelativePathString = RelativeOrAbsolutePathString;
01271:       }
01272:     else
01273:       {
01274:         RelativePathString = FileName.GetFullPath (RelativePathFormat);
01275:       }
01276: }
01277: 
01278: wxString makeRelativePath (const wxString & RelativeOrAbsolutePathString,
01279:                            const wxString & ReferenceDirString,
01280:                            bool IsUseRelativeParentDir,
01281:                            wxPathFormat RelativeOrAbsolutePathFormat,
01282:                            wxPathFormat ReferenceDirFormat,
01283:                            wxPathFormat RelativePathFormat)
01284: {
01285:     wxString RelativePathString;
01286:     makeRelativePath (RelativeOrAbsolutePathString,
01287:                       ReferenceDirString,
01288:                       RelativePathString,
01289:                       IsUseRelativeParentDir,
01290:                       RelativeOrAbsolutePathFormat,
01291:                       ReferenceDirFormat,
01292:                       RelativePathFormat);
01293:     return RelativePathString;
01294: }
01295: 
01296: //-------------------------------------------------------------------------
01297: 
01298: void addConcatenatedStrings (const wxArrayString & StringArray, 
01299:                              wxString & OutputString,
01300:                              const wxString & ElementPrefixString,
01301:                              const wxString & ElementPostfixString,
01302:                              const wxString & InfixString)
01303: {
01304:     int Count = StringArray.GetCount();
01305:     bool IsElementPrefix = !ElementPrefixString.IsEmpty();
01306:     bool IsElementPostfix = !ElementPostfixString.IsEmpty();
01307:     // bool IsInfix = !InfixString.IsEmpty();
01308:     for (int Index = 0; Index < Count; ++Index)
01309:       {
01310:         if (Index > 0)
01311:           OutputString << InfixString;
01312: 
01313:         if (IsElementPrefix)
01314:           OutputString << ElementPrefixString;
01315: 
01316:         OutputString << StringArray.Item(Index);
01317: 
01318:         if (IsElementPostfix)
01319:           OutputString << ElementPostfixString;
01320:       }
01321: }
01322: 
01323: //-------------------------------------------------------------------------
01324: 
01325: const char * wxGetIdTranslation(const char * MessageIdentCharPtr, const char * DefaultCharPtr)
01326: {
01327:     const char * TranslatedCharPtr = wxGetTranslation (MessageIdentCharPtr);
01328:     const char CheckedPrefixCharArray [] = "{id:";
01329:     // TODO: could replace strncmp() with string pointer comparison to detect
01330:     // if a translation is available
01331:     if (strncmp (TranslatedCharPtr, CheckedPrefixCharArray, 
01332:                  WXSIZEOF(CheckedPrefixCharArray) - 1) == 0)
01333:       {
01334:         return DefaultCharPtr;
01335:       }
01336:     else
01337:       {
01338:         return TranslatedCharPtr;
01339:       }
01340: }
01341: 
01342: //-------------------------------------------------------------------------
01343: 
01344: const char * wxGetCatalogMetaData(const char * MessageIdentCharPtr)
01345: {
01346:     const char * TranslatedCharPtr = wxGetTranslation (MessageIdentCharPtr);
01347:     if (TranslatedCharPtr == MessageIdentCharPtr)
01348:       {
01349:         return NULL;
01350:       }
01351:     else
01352:       {
01353:         return TranslatedCharPtr;
01354:       }
01355: }
01356: 
01357: //-------------------------------------------------------------------------
01358: 
01359: wxCatalogAddManag::wxCatalogAddManag()
01360: {
01361:     init();
01362: }
01363: 
01364: void wxCatalogAddManag::init ()
01365: {
01366:     m_IsError = false;
01367: }
01368: 
01369: void wxCatalogAddManag::setLocale (wxLocale * Locale)
01370: {
01371:     m_Locale = Locale;
01372: }
01373: 
01374: bool wxCatalogAddManag::addCatalog (const wxString & CatalogName)
01375: {
01376:     if (m_Locale -> GetLanguage() == wxLANGUAGE_UNKNOWN)
01377:       {
01378:         // don't try to load catalogue if language is not set or known
01379:       }
01380:     else 
01381:       {
01382:         if (!m_Locale -> AddCatalog (CatalogName))
01383:           {
01384:             m_IsError = true;
01385:             // m_MessageString << "failed to load catalog \"" << CatalogName << "\".\n";
01386:             m_MessageString << CatalogName << ":\n" << "    failed to load catalogue\n";
01387:             return false;
01388:           }
01389:         // else
01390:           // m_MessageString << CatalogName << ": loaded\n";
01391:       }
01392: 
01393:     return true;
01394: }
01395: 
01396: bool wxCatalogAddManag::addCatalogWithVersionCheck (const wxString & CatalogName,
01397:                                                     const wxString & RequiredVersionString)
01398: {
01399:     if (m_Locale -> GetLanguage() == wxLANGUAGE_UNKNOWN)
01400:       {
01401:         // don't try to load catalogue if language is not set or known
01402:       }
01403:     else if (addCatalog (CatalogName))
01404:       {
01405:         wxString VersionMessageIdentString = wxString("{meta:") + CatalogName + ":VersionIdent}";
01406:         const char * ActualVersionString = wxGetCatalogMetaData (VersionMessageIdentString);
01407: 
01408:         if ((ActualVersionString == NULL)
01409:             || (strcmp (ActualVersionString, RequiredVersionString) != 0))
01410:           {
01411:             m_MessageString
01412:               << CatalogName << ":\n"
01413:               << "    required version: " << RequiredVersionString << "\n"
01414:               << "    actual version: " << ((ActualVersionString != NULL) ? ActualVersionString : "(unknown)")
01415:               << "\n";
01416: 
01417:             m_IsError = true;
01418:           }
01419: 
01420:         return false;
01421:       }
01422: 
01423:     return true;
01424: }
01425: 
01426: bool wxCatalogAddManag::getMessage (wxString & MessageString)
01427: {
01428:     if (true)
01429:       {
01430:         int LanguageId = m_Locale -> GetLanguage();
01431:         const struct wxLanguageInfo * LanguageInfoPtr = wxLocale::GetLanguageInfo (LanguageId);
01432:         MessageString << "Language: ";
01433:         if (LanguageInfoPtr != NULL)
01434:           {
01435:             MessageString
01436:               << LanguageInfoPtr->Description << " (" << LanguageInfoPtr->CanonicalName << ")\n\n";
01437:           }
01438:         else
01439:           {
01440:             MessageString << "(unknown)" << "\n\n";
01441:           }
01442:       }
01443: 
01444:     if (m_IsError)
01445:       {
01446:         MessageString
01447:           << "Some of the message translation catalogues could not be loaded "
01448:           << "or do not have the expected versions:\n\n";
01449:       }
01450: 
01451:     // output messages about specific language versions
01452:     MessageString << m_MessageString;
01453: 
01454:     return (m_IsError);
01455: }
01456: 
01457: 
01458: #if 0
01459: extern bool checkCatalogueMetaData (wxString & MessageString,
01460:                                     const char * CatalogueNameString,
01461:                                     const char * VersionMessageIdentCharPtr,
01462:                                     const char * RequiredVersionString)
01463: {
01464:     bool IsOkay = false;
01465:     const char * ActualVersionString = wxGetCatalogueMetaData (VersionMessageIdentCharPtr);
01466: 
01467: #if 0    
01468:     MessageString
01469:       << VersionMessageIdentCharPtr << ":\n"
01470:       << "    required value: " << RequiredVersionString << "\n"
01471:       << "    actual value: " << ((ActualVersionString != NULL) ? ActualVersionString : "(not found)") << "";
01472: #endif
01473:     MessageString
01474:       << CatalogueNameString << ":\n"
01475:       << "    required version: " << RequiredVersionString << "\n"
01476:       << "    actual version: " << ((ActualVersionString != NULL) ? ActualVersionString : "(not found)") << "";
01477:     
01478:     if (ActualVersionString == NULL)
01479:       {
01480: #if 0
01481:         MessageString
01482:           << "could not find entry for meta-data key \"" << VersionMessageIdentCharPtr << "\" "
01483:           << "in message catalogue \"" << CatalogueNameString << "\", "
01484:           << "which must match \"" << RequiredVersionString << "\" ";
01485: #endif
01486:       }
01487:     else
01488:       {
01489:         if (strcmp (ActualVersionString, RequiredVersionString) != 0)
01490:           {
01491: #if 0
01492:             MessageString
01493:               << "entry for meta-data \"" << VersionMessageIdentCharPtr << "\" "
01494:               << "in message catalogue " << CatalogueNameString << ", "
01495:               << "which must match \"" << RequiredVersionString << "\" "
01496:               << "has a value of \"" << ActualVersionString << "\" ";
01497: #endif
01498:           }
01499:         else
01500:           {
01501: #if 0
01502:             MessageString
01503:               << "entry for meta-data \"" << VersionMessageIdentCharPtr << "\" "
01504:               << "in message catalogue " << CatalogueNameString << ", "
01505:               << "matches required value of \"" << RequiredVersionString << "\" ";
01506: #endif
01507:             IsOkay = true;
01508:           }
01509:       }
01510:     MessageString << "\n\n";
01511:     return IsOkay;
01512: }
01513: #endif
01514: 
01515: //=========================================================================
01516: 
01517: #if defined(__WXMSW__)
01518: 
01519: // // wxGetInstance() is somehow needed for loadDataResource():
01520: // // (as declared in ./include/wx/msw/private.h):
01521: // WXDLLEXPORT HINSTANCE wxGetInstance();
01522: // NOTE we use GetModuleHandle(NULL) instead of wxGetInstance()
01523: // which may not work under Win16
01524: 
01525: // NOTE semantics not well defined for Win16: there, some function like
01526: // releaseDataResource() or copying the data block would be needed
01527: bool loadDataResource (const wxString & ResourceNameString, 
01528:                        const char * ResourceTypeString,
01529:                        unsigned char ** DataPtr, size_t * DataSize)
01530: {
01531:     bool IsCompleted = false;
01532: 
01533:     for_once
01534:       {
01535:         HRSRC ResourceHandle = ::FindResource (::GetModuleHandle(NULL) /*wxGetInstance()*/, 
01536:                                                ResourceNameString, ResourceTypeString);
01537:         if (ResourceHandle == 0)
01538:           break;
01539: 
01540:         HGLOBAL DataHandle = NULL;
01541:         if (DataPtr != NULL)
01542:           {
01543:             // load and lock data block (if desired, i.e. if DataPtr != NULL)
01544:             DataHandle = ::LoadResource (::GetModuleHandle(NULL) /*wxGetInstance()*/, 
01545:                                          ResourceHandle);
01546:             if (DataHandle == 0)
01547:               break;
01548: 
01549:             *DataPtr = (unsigned char *) ::LockResource (DataHandle);
01550:             if (*DataPtr == NULL)
01551:               break;
01552:           }
01553:             
01554:         if (DataSize != NULL)
01555:           {
01556:             // determine size of the data block (if desired)
01557:             *DataSize = ::SizeofResource (GetModuleHandle (NULL) /*wxGetInstance()*/, 
01558:                                           ResourceHandle);
01559:           }
01560: 
01561:         // BUG for Win16:
01562:         // UnlockResource() must be called for Win16, however; we must
01563:         // probably do this after working with the data
01564: 
01565:         IsCompleted = true;
01566:       }
01567:     
01568:     return IsCompleted;
01569: }
01570: 
01571: // void releaseDataResource ()
01572: // {
01573: //      if (DataPtr != NULL)
01574: //        {
01575: //          // UnlockResource() not needed for WIN32
01576: // #ifndef __WIN32__
01577: //          UnlockResource(DataHandle);
01578: // #endif
01579: //        }
01580:     
01581: //      // needed for Win16?
01582: //      //  GlobalFree(hData);
01583: // }
01584: 
01585: #endif // defined(__WXMSW__)
01586: 
01587: //=========================================================================
01588: 
01589: // bool loadFile (const wxString & FileNameString, 
01590: //                wxByteArray & ByteArray)
01591: // {
01592: //     ByteArray.Clear();
01593: //     ByteArray
01594: //     wxFileInputStream FileInputStream = wxFileInputStream (FilenameString);
01595: // 
01596: //     if (!(FileInputStream -> Ok()))
01597: //       return false;
01598: // 
01599: //     FileInputStream.Read (ByteArray, ByteCount);
01600: // 
01601: // }
01602: 
01603: //-------------------------------------------------------------------------
01604: 
01605: // WARN why conditional compilation only for wxGUI here?
01606: #if wxUSE_GUI
01607: bool loadImageFromMemory (const unsigned char * ImageData, size_t ImageDataSize,
01608:                           wxImage & Image)
01609: {
01610:     wxMemoryInputStream MemoryInputStream (ImageData, ImageDataSize);
01611:     return Image.LoadFile (MemoryInputStream);
01612: }
01613: 
01614: bool loadBitmapFromMemory (const unsigned char * ImageData, size_t ImageDataSize,
01615:                            wxBitmap ** Bitmap)
01616: {
01617:     *Bitmap = NULL;
01618: 
01619:     bool IsOk = false;
01620:     for_once
01621:       {
01622:         wxImage Image;
01623:         if (! loadImageFromMemory (ImageData, ImageDataSize, Image))
01624:           break;
01625: 
01626:         *Bitmap = new wxBitmap (Image);
01627:         if (*Bitmap == NULL)
01628:           break;
01629: 
01630:         IsOk = true;
01631:       }
01632: 
01633:     return IsOk;
01634: }
01635: #endif // wxUSE_GUI
01636: 
01637: #if defined(__WXMSW__)
01638: 
01639: #if wxUSE_GUI
01640: bool loadImageFromResource (const wxString & ImageDataResourceNameString, 
01641:                             wxImage & Image)
01642: {
01643:     unsigned char * DataPtr = NULL;
01644:     size_t DataSize = 0;
01645:     if (!loadDataResource (ImageDataResourceNameString, RT_RCDATA,
01646:                            & DataPtr, & DataSize))
01647:       return false;
01648: 
01649:     return loadImageFromMemory (DataPtr, DataSize, Image);
01650: }
01651: 
01652: bool loadBitmapFromResource (const wxString & ImageDataResourceNameString, 
01653:                              wxBitmap ** Bitmap)
01654: {
01655:     bool IsOk = false;
01656: 
01657:     *Bitmap = NULL;
01658: 
01659:     for_once
01660:       {
01661:         unsigned char * DataPtr = NULL;
01662:         size_t DataSize = 0;
01663:         if (!loadDataResource (ImageDataResourceNameString, RT_RCDATA,
01664:                                & DataPtr, & DataSize))
01665:           break;
01666:     
01667:         if (!loadBitmapFromMemory (DataPtr, DataSize, Bitmap))
01668:           break;
01669: 
01670:         IsOk = true;
01671:       }
01672: 
01673:     if (!IsOk)
01674:       *Bitmap = new wxBitmap ();
01675: 
01676:     return IsOk;
01677: }
01678: #endif // wxUSE_GUI
01679: 
01680: #endif // defined(__WXMSW__)
01681: 
01682: //=========================================================================
01683: 
01684: #if (M_WxExtLib_IsUseGraphicsHelper == 1)
01685: #  if wxUSE_GUI
01686: 
01687: // resizeImageVGrid()
01688: // Todo:
01689: // - support wxImage having alpha/transparency channel (wxWidgets 
01690: //   version approx. >= 2.5)
01691: // - check version numbers wxImage/wxCHECK_VERSION switching
01692: bool resizeImageVGrid (const wxImage & InputImage,
01693:                        wxImage & OutputImage,
01694:                        int OutputWidth, int OutputHeight)
01695: {
01696:     if (!InputImage.Ok())
01697:       return false;
01698: 
01699: #if wxCHECK_VERSION (2, 5, 0)
01700:     if (!OutputImage.Create (OutputWidth, OutputHeight, false /* IsClear */))
01701:       return false;
01702: #else
01703:     // overload resolution for older version may accidently interpret 'false' 
01704:     // as pointer and so use Create() with initialization of allocated bytes:
01705:     OutputImage.Create (OutputWidth, OutputHeight);
01706: #endif
01707: 
01708:     if (!OutputImage.Ok())
01709:       return false;
01710: 
01711:     const unsigned char * InputImageData = InputImage.GetData();
01712:     unsigned char * OutputImageData = OutputImage.GetData();
01713: 
01714: #if wxCHECK_VERSION (2, 5, 0)
01715:     if (InputImage.HasAlpha())
01716:       return false;
01717: #endif
01718: 
01719:     if (!resizeImageVGrid (InputImageData, InputImage.GetWidth() * 3,
01720:                            InputImage.GetWidth(), InputImage.GetHeight(),
01721:                            true /* IsRGB */ , false /* IsAlpha */,
01722:                            OutputImageData, OutputImage.GetWidth() * 3,
01723:                            OutputImage.GetWidth(), OutputImage.GetHeight()))
01724:       return false;
01725: 
01726:     return true;
01727: }
01728: #  endif
01729: #endif
01730: 
01731: //=========================================================================
01732: 
01733: // doTextLineWrap()
01734: // - text extents are calculated for the font currently set for the DC
01735: // Possible improvements:
01736: // - Insert e.g. '\r\n' or '\r\r\n' when having a 'soft' line break (not forced)
01737: //   instead of just '\n'. This way, the soft line breaks could be un-done
01738: //   again (because then they would be distinguishable from the hard line breaks).
01739: //   This could be useful if a control want's to re-do line wrapping 
01740: //   e.g. after a size change notification.
01741: void doTextLineWrap (const wxString & InputString, 
01742:                      int MaxLineWidth,
01743:                      wxDC & DC,
01744:                      wxString & ResultString)
01745: {
01746:     wxString CurrentLineString;
01747:     // pre-allocate line-string to improve performance:
01748:     CurrentLineString.Alloc (512);
01749: 
01750:     const char * CurrentCharPtr = InputString.c_str();
01751:     // const char * LineStartCharPtr = CurrentCharPtr;
01752:     const char * LastBreakCharPtr = NULL;
01753: 
01754:     int CurrentLineCharCount = 0;
01755:     int LastBreakCharCount = 0;
01756: 
01757:     bool IsJustAfterWrap;
01758:     bool IsAfterWrap = false;
01759:     while (1)
01760:       {
01761:         IsJustAfterWrap = false;
01762:         bool IsBreakAllowed = false;
01763:         bool IsBreakForced = false;
01764: 
01765:         int CurrentChar = *CurrentCharPtr;
01766: 
01767:         if (IsAfterWrap)
01768:           {
01769:             if (!(CurrentChar == '\0'
01770:                   || wxIsspace (CurrentChar))
01771:                 || CurrentChar == '\n')
01772:               IsAfterWrap = false;
01773:           }
01774: 
01775:         if (!IsAfterWrap)
01776:           {
01777:             if (CurrentChar == '\0'
01778:                 || wxIsspace (CurrentChar))
01779:               IsBreakAllowed = true;
01780: 
01781:             if (CurrentChar == '\n'
01782:                 || CurrentChar == '\0')
01783:               IsBreakForced = true;
01784:           }
01785: 
01786:         if (IsBreakAllowed
01787:             || IsBreakForced)
01788:           {
01789:             int Width = 0;
01790:             int Height = 0;
01791:             // NOTE there is also wxWindow::GetTextExtent, maybe 
01792:             // one could optionally use this function instead of wxDC::GetTextExtent
01793:             DC.GetTextExtent (CurrentLineString, & Width, & Height);
01794:         
01795:             bool IsOverfull = (Width > MaxLineWidth);
01796: 
01797:             if (IsOverfull
01798:                 || IsBreakForced)
01799:               {
01800:                 const char * ActualBreakCharPtr = NULL;
01801:                 if (IsOverfull)
01802:                   {
01803:                     ActualBreakCharPtr = LastBreakCharPtr;
01804:                     if (ActualBreakCharPtr == NULL)
01805:                       ActualBreakCharPtr = CurrentCharPtr;
01806:                   }
01807:                 else
01808:                   {
01809:                     ActualBreakCharPtr = CurrentCharPtr;
01810:                   }
01811: 
01812:                 if (IsOverfull
01813:                     && LastBreakCharPtr != NULL)
01814:                   {
01815:                     CurrentLineString.Truncate (LastBreakCharCount);
01816:                   }
01817: 
01818:                 ResultString.Append (CurrentLineString);
01819:                 ResultString.Append ("\n");
01820:                 
01821:                 // set string to empty but retain allocated memory:
01822:                 CurrentLineString.Empty ();
01823: 
01824:                 // reposition pointers
01825:                 // LineStartCharPtr = ActualBreakCharPtr;
01826:                 CurrentCharPtr = ActualBreakCharPtr;
01827:                 CurrentChar = *CurrentCharPtr;
01828:                 LastBreakCharPtr = NULL;
01829:                 LastBreakCharCount = 0;
01830:                 CurrentLineCharCount = 0;
01831: 
01832:                 if (CurrentChar == '\n')
01833:                   {
01834:                     ++CurrentCharPtr;
01835:                     CurrentChar = *CurrentCharPtr;
01836:                   }
01837: 
01838:                 IsAfterWrap = true;
01839:                 IsJustAfterWrap = true;
01840:               }
01841:             else
01842:               {
01843:                 LastBreakCharPtr = CurrentCharPtr;
01844:                 LastBreakCharCount = CurrentLineCharCount;
01845:               }
01846:           }
01847: 
01848:         if (CurrentChar == '\0')
01849:           break;
01850: 
01851:         if (!IsAfterWrap)
01852:           {
01853:             CurrentLineString.Append ((char) CurrentChar);
01854:             ++CurrentLineCharCount;
01855:           }
01856: 
01857:         if (!IsJustAfterWrap)
01858:           {
01859:             ++CurrentCharPtr;
01860:           }
01861:       }
01862: }
01863: 
01864: //-------------------------------------------------------------------------
01865: 
01866: void doTextLineWrap (const wxString & InputString, 
01867:                      int MaxLineWidth,
01868:                      wxWindow * Window,
01869:                      wxString & ResultString)
01870: {
01871:    wxClientDC ClientDC (Window);
01872:    const wxFont & Font = Window -> GetFont ();
01873: 
01874:    ClientDC.SetFont (Font);
01875:    doTextLineWrap (InputString, MaxLineWidth, ClientDC, ResultString);
01876: 
01877:    // WARN don't know if resetting old font is required
01878: }
01879: 
01880: //=========================================================================
01881: 
01882: bool wxVerifyWindowPtr (wxWindow * ParentWindow, wxWindow * SearchedWindow)
01883: {
01884:     wxWindowListNode * Node = NULL;
01885: 
01886:     if (ParentWindow == SearchedWindow)
01887:       return true;
01888: 
01889:     // search list of windows recursively, starting from specified
01890:     // ParentWindow, depth-first search
01891:     for (Node = ParentWindow->GetChildren().GetFirst();
01892:          Node != NULL;
01893:          Node = Node->GetNext())
01894:       {
01895:         wxWindow * Window = Node->GetData();
01896:         bool IsFound = wxVerifyWindowPtr (Window, SearchedWindow);
01897:         if (IsFound)
01898:           return true;
01899:       }
01900: 
01901:     return false;
01902: }
01903: 
01904: //=========================================================================
01905: 
01906: wxFocusRestorer::wxFocusRestorer ()
01907: {
01908:     m_OldFocusWindow = wxWindow::FindFocus ();
01909:     
01910:     // save HWND?
01911:     // HWND m_OldFocusHwnd = OldFocusWindow != NULL ? GetHwndOf (OldFocusWindow) : NULL;
01912: }
01913: 
01914: wxFocusRestorer::~wxFocusRestorer ()
01915: {
01916:     if (m_OldFocusWindow != NULL)
01917:       {
01918:         wxWindow * CurrentFocusWindow = wxWindow::FindFocus ();
01919: 
01920:         // TEST: set focus window only if it appears to have changed
01921:         // to avoid flicker (if this is the reason for flicker, maybe
01922:         // it isn't)
01923:         if (CurrentFocusWindow != m_OldFocusWindow)
01924:           m_OldFocusWindow -> SetFocus();
01925:       }
01926: }
01927: 
01928: //=========================================================================
01929: 
01930: #if wxUSE_GUI
01931: wxMultiLineText::wxMultiLineText ()
01932: {
01933:     m_TextCtrl = NULL;
01934:     m_HtmlWindow = NULL;
01935:     m_StaticText = NULL;
01936: 
01937:     m_MultiLineTextStyle = 0;
01938: }
01939: 
01940: void wxMultiLineText::create (wxWindow * ParentWindow,
01941:                               int WindowIdent,
01942:                               int CtrlStyle,
01943:                               const wxSize & MinSize,
01944:                               int MultiLineTextStyle)
01945: {
01946:     wxSize UsedSize = MinSize;
01947: 
01948:     m_MultiLineTextStyle = MultiLineTextStyle;
01949: 
01950:     // determine what kind of borders to use:
01951:     if (! (CtrlStyle & wxBORDER_NONE)
01952:         && !(CtrlStyle & wxBORDER_SIMPLE))
01953:       {
01954:         // default is wxSUNKEN_BORDER:
01955:         CtrlStyle |= wxSUNKEN_BORDER;
01956:       }
01957: 
01958:     // determine if wxTextCtrl or wxHtmlWindow should be used:
01959:     bool IsCreateTextCtrl = true;
01960: 
01961: #if ((defined __WXMOTIF__) || defined(__WXGTK__))
01962:     // with Lesstif/Motif?, we don't want to use wxTextCtrl 
01963:     // because it uses a fixed-size typewriter-like font 
01964:     // and setting colours is not possible
01965:     //
01966:     // GTK (1.2.7) wxTextCtrl ignores setting foreground, background 
01967:     // colours or not using sunken border
01968:     // 
01969:     // default for Motif/Lesstif, GTK: use wxHtmlWindow
01970:     IsCreateTextCtrl = false;
01971: #endif
01972: 
01973:     if (MultiLineTextStyle & wxFORCE_HTMLWINDOW)
01974:       IsCreateTextCtrl = false;
01975: 
01976:     if (MultiLineTextStyle & wxFORCE_TEXTCTRL)
01977:       IsCreateTextCtrl = true;
01978: 
01979:     if (MultiLineTextStyle & wxHTML_MODE)
01980:       IsCreateTextCtrl = false;
01981: 
01982:     // create the desired control type
01983:     if (IsCreateTextCtrl)
01984:       {
01985:         // borders: wxTextCtrl seems to normally have a border.
01986:         // No border can be requested with wxBORDER_NONE.
01987:         
01988:         long TextCtrlStyle = wxTE_MULTILINE | wxTE_LINEWRAP | wxTE_READONLY;
01989:         /* | wxVSCROLL | wxTE_RICH | wxBORDER_NONE */
01990:         // if (! (CtrlStyle & wxSUNKEN_BORDER))
01991:         //  TextCtrlStyle |= wxBORDER_NONE;
01992:         TextCtrlStyle |= CtrlStyle;
01993:         
01994:         m_TextCtrl = new wxTextCtrl (ParentWindow, WindowIdent, _T(""),
01995:                                      wxDefaultPosition, UsedSize,
01996:                                      TextCtrlStyle,
01997:                                      wxDefaultValidator);
01998: 
01999:         m_TextCtrl -> SetBackgroundColour (ParentWindow -> GetBackgroundColour());
02000:       }
02001:     else
02002:       {
02003:         // borders: wxHtmlWindow seems to support
02004:         // wxSIMPLE_BORDER, wxSUNKEN_BORDER, (no border if no flag specified),
02005:         // maybe others
02006:         m_HtmlWindow = new wxHtmlWindow (ParentWindow, WindowIdent, 
02007:                                          wxDefaultPosition, 
02008:                                          UsedSize,
02009:                                          CtrlStyle);
02010:         m_HtmlWindow -> SetBorders (2);
02011:         m_HtmlWindow -> SetBackgroundColour (ParentWindow -> GetBackgroundColour());
02012:       }
02013: 
02014: //  // wxStaticText apparently ignores wxVSCROLL (at least under
02015: //  // this X11 and this Lesstif), so it isn't very useful for our cause
02016: //  // of displaying, possibly very long, multi-line text
02017: //     m_StaticText = new wxStaticText (ParentWindow, WindowIdent, _T(""),
02018: //                                   wxDefaultPosition, UsedSize,
02019: //                                   /* WindowStyle */ wxVSCROLL);
02020:     
02021: }
02022: 
02023: //-------------------------------------------------------------------------
02024: 
02025: void wxMultiLineText::setText (const wxString & String)
02026: {
02027:     if (m_TextCtrl != NULL)
02028:       {
02029: #if defined(__WXMSW__)
02030:         // the RichEdit supports line wrapping
02031:         m_TextCtrl -> SetValue (String);
02032: #else
02033:         // under X11, the wxTextCtrl doesn't support wrapping of long
02034:         // lines by itself, here we call doTextLineWrap()
02035:         // (note: from wxWindows 2.6 (2.5.x) on, the wxX11/wxUniv wxTextCtrl 
02036:         // will have support for line wrap)
02037:         //
02038:         // GTK 1.x: the wxTextCtrl supports wxTE_LINEWRAP, but
02039:         // wxTextCtrl::GetNumberOfLines() only counts newlines
02040:         // (but we are interessted in the number of lines after 
02041:         // doing the wrapping) - because of this problem, we use
02042:         // doTextLineWrap() for GTK as well
02043:         // 
02044:         wxSize ClientSize = m_TextCtrl -> GetClientSize();
02045:         wxString ResultString;
02046: 
02047:         int MaxLineWidth = ClientSize.GetWidth();
02048:         // HACK quick hack to account for possibly existing 
02049:         // scrollbars:
02050:         if (MaxLineWidth >= 25)
02051:           MaxLineWidth -= 25;
02052: 
02053: #if defined(__WXMOTIF__)
02054:         // the Lesstif wxTextCtrl has lot's of bordering around the
02055:         // space actually usable for text, so subtract a little from
02056:         // the horizontal size
02057:         MaxLineWidth -= 20;
02058: #endif
02059: 
02060:         // NOTE: the wxUniversal wxTextCtrl now (version 2.5.2 tested) has support 
02061:         // for wrapping long lines, so calling doTextLineWrap() may not be required 
02062:         // for this newer wxWindows versions
02063:         // Also, this new wrapping mechanism has support for partial re-wrapping,
02064:         // which is not available with doTextLineWrap().
02065:         // (however, must check semantics of GetNumberOfLines())
02066:         doTextLineWrap (String, MaxLineWidth, 
02067:                         m_TextCtrl,
02068:                         ResultString);
02069:         m_TextCtrl -> SetValue (ResultString);
02070: #endif
02071:       }
02072:     else if (m_HtmlWindow != NULL)
02073:       {
02074:         // WARN should add charset name in HTML <head> for currently used charset
02075:         wxString HtmlString = "<html><body bgcolor=\"" 
02076:           + formatColourToHtmlParam (m_HtmlWindow -> GetBackgroundColour())
02077:           + "\" text=\""
02078:           + formatColourToHtmlParam (m_HtmlWindow -> GetForegroundColour())
02079:           + "\">\n"
02080:           + "";
02081:         if (m_MultiLineTextStyle & wxHTML_MODE)
02082:           {
02083:             HtmlString += String;
02084:           }
02085:         else
02086:           {
02087:             HtmlString += convertAsciiToHtml (String, true, 
02088:                                               wxAsciiToHtml_ConvertLeadingSpaces);
02089:           }
02090:         HtmlString += "</body></html>";
02091:         m_HtmlWindow -> SetPage (HtmlString);
02092:       }
02093:     else if (m_StaticText != NULL)
02094:       {
02095:         m_StaticText -> SetLabel (String);
02096:       }
02097: }
02098: 
02099: //-------------------------------------------------------------------------
02100: 
02101: wxWindow * wxMultiLineText::getWindow ()
02102: {
02103:    if (m_TextCtrl != NULL)
02104:      return m_TextCtrl;
02105:    else if (m_HtmlWindow != NULL)
02106:      return m_HtmlWindow;
02107:    else if (m_StaticText != NULL)
02108:      return m_StaticText;
02109:    else
02110:      return NULL;
02111: }
02112: 
02113: wxTextCtrl * wxMultiLineText::getTextCtrl ()
02114: {
02115:     return m_TextCtrl;
02116: }
02117: 
02118: wxHtmlWindow * wxMultiLineText::getHtmlWindow ()
02119: {
02120:     return m_HtmlWindow;
02121: }
02122: 
02123: wxStaticText * wxMultiLineText::getStaticText ()
02124: {
02125:     return m_StaticText;
02126: }
02127: 
02128: //-------------------------------------------------------------------------
02129: 
02130: void wxMultiLineText::setTextCtrl (wxTextCtrl * TextCtrl, int MultiLineTextStyle)
02131: {
02132:     m_TextCtrl = TextCtrl;
02133:     m_StaticText = NULL;
02134:     m_HtmlWindow = NULL;
02135: 
02136:     m_MultiLineTextStyle = MultiLineTextStyle;
02137: }
02138: 
02139: void wxMultiLineText::getStaticText (wxStaticText * StaticText, int MultiLineTextStyle)
02140: {
02141:     m_TextCtrl = NULL;
02142:     m_StaticText = StaticText;
02143:     m_HtmlWindow = NULL;
02144: 
02145:     m_MultiLineTextStyle = MultiLineTextStyle;
02146: }
02147: 
02148: void wxMultiLineText::setHtmlWindow (wxHtmlWindow * HtmlWindow, int MultiLineTextStyle)
02149: {
02150:     m_TextCtrl = NULL;
02151:     m_StaticText = NULL;
02152:     m_HtmlWindow = HtmlWindow;
02153: 
02154:     m_MultiLineTextStyle = MultiLineTextStyle;
02155: }
02156: #endif // wxUSE_GUI
02157: 
02158: //=========================================================================
02159: 
02160: #if wxUSE_GUI
02161: 
02162: IMPLEMENT_DYNAMIC_CLASS(wxTransparentStaticText, wxStaticText)
02163: 
02164: BEGIN_EVENT_TABLE (wxTransparentStaticText, wxStaticText)
02165: #if defined (__WXMSW__)
02166:     EVT_ERASE_BACKGROUND (wxTransparentStaticText::OnEraseBackground)
02167:     EVT_PAINT(wxTransparentStaticText::OnPaint)
02168: #else
02169:     // see notes below regarding transparency support in other ports
02170:     // than wxMSW
02171: #endif
02172: END_EVENT_TABLE()
02173: 
02174: //-------------------------------------------------------------------------
02175: 
02176: wxTransparentStaticText::wxTransparentStaticText ()
02177: {
02178: }
02179: 
02180: bool wxTransparentStaticText::Create(wxWindow * ParentWindow,
02181:                                      wxWindowID ControlIdent,
02182:                                      const wxString& LabelString,
02183:                                      const wxPoint& Position,
02184:                                      const wxSize& Size,
02185:                                      long Style,
02186:                                      ETransparentStaticTextFlags Flags,
02187:                                      const wxString& Name)
02188: {
02189:     m_TransparentStaticTextFlags = Flags;
02190: 
02191:     bool IsOk = wxStaticText::Create (ParentWindow, ControlIdent, LabelString,
02192:                                       Position, Size, Style, Name);
02193: 
02194:     return IsOk;
02195: }
02196: 
02197: //-------------------------------------------------------------------------
02198: 
02199: void wxTransparentStaticText::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02200: {
02201:     // background is painted in OnPaint(), to avoid flicker
02202: 
02203:     // doesn't exist:
02204:     // wxWindow::OnEraseBackground (EraseEvent);
02205: }
02206: 
02207: void wxTransparentStaticText::OnPaint (wxPaintEvent & PaintEvent)
02208: {
02209: #if defined(__WXMSW__)
02210:     // wxMSW port: wxStaticText doesn't seem to support text in transparency
02211:     // mode, so implement our own paint function
02212: 
02213:     wxPaintDC PaintWxDC (this);
02214: 
02215:     wxRect WindowRect = GetClientRect();
02216: 
02217:     if (m_TransparentStaticTextFlags & IsOpaque)
02218:       {
02219:         // wxDC & DC = * EraseEvent.GetDC();
02220: 
02221:         PaintWxDC.SetBrush (wxBrush (GetBackgroundColour(), wxSOLID));
02222:         PaintWxDC.SetPen (* wxTRANSPARENT_PEN);
02223:         PaintWxDC.DrawRectangle (WindowRect);
02224:       }
02225: 
02226:     // other settings which might be important for drawing:
02227:     // - SetMapMode(), SetUserScale()
02228:     // - SetTextForeground()
02229:     // - SetTextBackground()
02230:     // - SetClippingRegion()
02231: 
02232:     // PaintWxDC.SetPen (m_Pen);
02233:     // PaintWxDC.SetBrush (m_Brush);
02234:     // PaintWxDC.DrawRectangle (WindowRect);
02235:     // PaintWxDC.DrawRoundedRectangle (WindowRect, -4.0);
02236: 
02237:     // WARN required to set these values back?
02238:     PaintWxDC.SetBackgroundMode (wxTRANSPARENT);
02239:     PaintWxDC.SetTextForeground (GetForegroundColour ());
02240:     PaintWxDC.SetTextBackground (GetBackgroundColour ());
02241:     PaintWxDC.SetFont (GetFont ());
02242: 
02243:     // DC::DrawText() seems to ignore ampersand characters, so use
02244:     // Win32 API DrawText() instead
02245:     // PaintWxDC.DrawText (wxGetWindowText(GetHWND()), WindowRect.GetX(), WindowRect.GetY());
02246:     wxString WindowTextString = GetLabel();
02247: 
02248:     // const char * WindowTextCharPtr = WindowTextString.c_str();
02249:     int CharCount = wxStrlen (WindowTextString);
02250: 
02251:     // GetPixel returns a COLORREF in Win32
02252:     COLORREF ForegroundColorRef = GetForegroundColour().GetPixel();
02253: 
02254:     HDC PaintDC = (HDC) PaintWxDC.GetHDC();
02255:     COLORREF PreviousForegroundColorRef = SetTextColor (PaintDC, ForegroundColorRef);
02256:     int PreviousBkMode = SetBkMode (PaintDC, TRANSPARENT);
02257:  
02258:     // BUG TODO 
02259:     // HDC SetFont
02260:     // test/compile with other wx ports
02261: 
02262:     RECT Rect = {WindowRect.GetX(), WindowRect.GetY(), 
02263:                  WindowRect.GetWidth(), WindowRect.GetHeight() };
02264:     // TODO consider other DT_* flags
02265:     ::DrawText (PaintDC, WindowTextString,
02266:                 CharCount, & Rect, DT_SINGLELINE /* | DT_CENTER */);
02267: 
02268:     SetBkMode (PaintDC, PreviousBkMode);
02269:     SetTextColor (PaintDC, PreviousForegroundColorRef);
02270: #else
02271: 
02272: #ifndef __WXGTK__
02273:     // except for wxGTK, support for transparent text-drawing for the
02274:     // different ports (wxMOTIF, wxUniversal etc.) in unkown/untested,
02275:     // so add a warning here, at least
02276:     // sure, above code for wxMSW can't be used in these ports anyway,
02277:     // since it uses the Win32 API
02278: 
02279:     #pragma message ("Please check transparency support of wxStaticText in this wx-port");
02280: #endif
02281:     // ???
02282:     // for wxGTK, neither wxStaticText nor wxWindow implements a method
02283:     // OnPaint we could call, so resort to simply not defining OnPaint()
02284:     // in wxGTK (and other ports), thus using the default implementation
02285:     // of OnPaint() (see above for message handler definitions)
02286:     // wxStaticText::OnPaint (PaintEvent);
02287:     // wxWindow::OnPaint (PaintEvent);
02288: 
02289: #if wxCHECK_VERSION (2, 5, 3)
02290:     wxUnusedVar (PaintEvent);
02291: #endif
02292: #endif
02293: }
02294: #endif // wxUSE_GUI
02295: 
02296: //=========================================================================
02297: 
02298: #if wxUSE_GUI
02299: 
02300: IMPLEMENT_DYNAMIC_CLASS(wxColourBarWindow, wxPanel)
02301: 
02302: BEGIN_EVENT_TABLE (wxColourBarWindow, wxPanel)
02303:     EVT_ERASE_BACKGROUND (wxColourBarWindow::OnEraseBackground)
02304:     EVT_PAINT(wxColourBarWindow::OnPaint)
02305: END_EVENT_TABLE()
02306: 
02307: //-------------------------------------------------------------------------
02308: 
02309: wxColourBarWindow::wxColourBarWindow ()
02310: {
02311:     m_Brush = *wxTRANSPARENT_BRUSH;
02312:     m_Pen = *wxTRANSPARENT_PEN;
02313:     m_RoundedCornerRadius = 0.;
02314: }
02315: 
02316: wxColourBarWindow::wxColourBarWindow (wxWindow * ParentWindow, int ControlIdent,
02317:                                       const wxPoint & Position, 
02318:                                       const wxSize & Size,
02319:                                       long Style, const wxString& Name)
02320:   : wxPanel (ParentWindow, ControlIdent, 
02321:               Position, Size,
02322:               Style, Name)
02323: {
02324:     m_Brush = *wxTRANSPARENT_BRUSH;
02325:     m_Pen = *wxTRANSPARENT_PEN;
02326:     m_RoundedCornerRadius = 0.;
02327: }
02328: 
02329: wxColourBarWindow::wxColourBarWindow (wxWindow * ParentWindow, int ControlIdent,
02330:                                       const wxColour & Colour,
02331:                                       const wxPoint & Position, 
02332:                                       const wxSize & Size,
02333:                                       long Style, const wxString& Name)
02334:   : wxPanel (ParentWindow, ControlIdent, 
02335:               Position, Size,
02336:               Style, Name)
02337: {
02338:     m_Brush.SetColour (Colour);
02339:     m_Brush.SetStyle (wxSOLID);
02340:     m_RoundedCornerRadius = 0.;
02341:     m_Pen = *wxTRANSPARENT_PEN;
02342: }
02343: 
02344: //-------------------------------------------------------------------------
02345: 
02346: void wxColourBarWindow::setBrush (const wxBrush & Brush)
02347: {
02348:     m_Brush = Brush;
02349: }
02350: 
02351: void wxColourBarWindow::setRoundedCornerRadius (double RoundedCornerRadius)
02352: {
02353:     m_RoundedCornerRadius = RoundedCornerRadius;
02354: }
02355: 
02356: void wxColourBarWindow::setPen (const wxPen & Pen)
02357: {
02358:     m_Pen = Pen;
02359: }
02360: 
02361: //-------------------------------------------------------------------------
02362: 
02363: void wxColourBarWindow::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02364: {
02365:     // wxPanel::OnEraseBackground (EraseEvent);
02366: }
02367: 
02368: void wxColourBarWindow::OnPaint (wxPaintEvent & WXUNUSED(PaintEvent))
02369: {
02370:     wxPaintDC PaintWxDC (this);
02371: 
02372:     wxRect WindowRect = GetClientRect();
02373: 
02374:     PaintWxDC.SetPen (m_Pen);
02375:     PaintWxDC.SetBrush (m_Brush);
02376: 
02377:     if (m_RoundedCornerRadius == 0.)
02378:       {
02379:         PaintWxDC.DrawRectangle (WindowRect);
02380:       }
02381:     else
02382:       {
02383:         PaintWxDC.DrawRoundedRectangle (WindowRect, m_RoundedCornerRadius);
02384:       }
02385: }
02386: #endif // wxUSE_GUI
02387: 
02388: //=========================================================================
02389: 
02390: #if (M_WxExtLib_IsUseGraphicsHelper == 1)
02391: #   if wxUSE_GUI
02392: 
02393: IMPLEMENT_DYNAMIC_CLASS(wxScaledImageWindow, wxPanel)
02394: 
02395: BEGIN_EVENT_TABLE (wxScaledImageWindow, wxPanel)
02396:     EVT_ERASE_BACKGROUND (wxScaledImageWindow::OnEraseBackground)
02397:     EVT_PAINT(wxScaledImageWindow::OnPaint)
02398: END_EVENT_TABLE()
02399: 
02400: //-------------------------------------------------------------------------
02401: 
02402: wxScaledImageWindow::wxScaledImageWindow ()
02403: {
02404:     // m_OriginalImage = wxNullImage;
02405:     m_IsCacheOkay = false;
02406: }
02407: 
02408: wxScaledImageWindow::wxScaledImageWindow (wxWindow * ParentWindow, int ControlIdent,
02409:                                           const wxPoint & Position, 
02410:                                           const wxSize & Size,
02411:                                           long Style, const wxString& Name)
02412:   : wxPanel (ParentWindow, ControlIdent, 
02413:              Position, Size,
02414:              Style, Name)
02415: {
02416:     // m_OriginalImage = wxNullImage;
02417:     m_IsCacheOkay = false;
02418: }
02419: 
02420: wxScaledImageWindow::wxScaledImageWindow (wxWindow * ParentWindow, int ControlIdent,
02421:                                           const wxImage & Image,
02422:                                           const wxPoint & Position, 
02423:                                           const wxSize & Size,
02424:                                           long Style, const wxString& Name)
02425:   : wxPanel (ParentWindow, ControlIdent, 
02426:              Position, Size,
02427:              Style, Name)
02428: {
02429:     m_OriginalImage = Image;
02430:     m_IsCacheOkay = false;
02431: }
02432: 
02433: //-------------------------------------------------------------------------
02434: 
02435: void wxScaledImageWindow::setImage (const wxImage & Image)
02436: {
02437:     m_OriginalImage = Image;
02438:     m_IsCacheOkay = false;
02439: }
02440: 
02441: //-------------------------------------------------------------------------
02442: 
02443: void wxScaledImageWindow::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02444: {
02445:     // wxPanel::OnEraseBackground (EraseEvent);
02446: }
02447: 
02448: void wxScaledImageWindow::OnPaint (wxPaintEvent & WXUNUSED(PaintEvent))
02449: {
02450:     wxPaintDC PaintWxDC (this);
02451: 
02452:     wxRect WindowRect = GetClientRect();
02453:     bool IsOkay = false;
02454: 
02455:     if ((!m_IsCacheOkay)
02456:         || (WindowRect != m_PreviousClientRect))
02457:       {
02458:         m_PreviousClientRect = WindowRect;
02459:         wxImage ScaledImage;
02460:         IsOkay = resizeImageVGrid (m_OriginalImage, 
02461:                                    ScaledImage,
02462:                                    WindowRect.GetWidth(), WindowRect.GetHeight());
02463:         
02464:         if (IsOkay)
02465:           {
02466:             m_ScaledBitmap = wxBitmap (ScaledImage);
02467:             m_IsCacheOkay = true;
02468:           }
02469:       }
02470:     else
02471:       {
02472:         IsOkay = true;
02473:       }
02474: 
02475:     if (IsOkay)
02476:       {
02477:         PaintWxDC.DrawBitmap (m_ScaledBitmap, 0 /* x */, 0 /* y */, true /* transparent */);
02478:       }
02479:     else
02480:       {
02481:         PaintWxDC.SetPen (wxPen (*wxBLACK, 1, wxTRANSPARENT));
02482:         PaintWxDC.SetBrush (wxBrush (wxColour (0xA0, 0xA0, 0xF0), wxSOLID));
02483:         PaintWxDC.DrawRectangle (WindowRect);
02484:       }
02485: }
02486: 
02487: #   endif // wxUSE_GUI
02488: #endif
02489: 
02490: //=========================================================================
02491: 
02492: #if wxUSE_GUI
02493: IMPLEMENT_DYNAMIC_CLASS(wxItemWindow, wxWindow)
02494: 
02495: BEGIN_EVENT_TABLE (wxItemWindow, wxWindow)
02496:     EVT_ERASE_BACKGROUND (wxItemWindow::OnEraseBackground)
02497:     EVT_PAINT(wxItemWindow::OnPaint)
02498: END_EVENT_TABLE()
02499: 
02500: //-------------------------------------------------------------------------
02501: 
02502: wxItemWindow::wxItemWindow ()
02503: {
02504:     m_IsSelectable = false;
02505:     m_IsFocusable = false;
02506:     m_StatusMessageTarget = NULL;
02507: 
02508:     init ();
02509: }
02510: 
02511: wxItemWindow::wxItemWindow (wxWindow * ParentWindow, int ControlIdent,
02512:                                     const wxPoint & Position, 
02513:                                     const wxSize & Size,
02514:                                     bool IsSelectable, bool IsFocusable,
02515:                                     wxStatusMessageTarget * StatusMessageTarget,
02516:                                     long Style, const wxString& Name)
02517:   : wxWindow (ParentWindow, ControlIdent, 
02518:               Position, Size,
02519:               Style, Name)
02520: {
02521:     m_StatusMessageTarget = StatusMessageTarget;
02522:     m_IsSelectable = IsSelectable;
02523:     m_IsFocusable = IsFocusable;
02524: 
02525:     init ();
02526: }
02527: 
02528: void wxItemWindow::init ()
02529: {
02530:     m_IsSelected = false;
02531:     m_IsFocused = false;
02532:     m_IsBorder = false;
02533:     m_IsUsingFocusedBackgroundBrush = false;
02534: }
02535: 
02536: //-------------------------------------------------------------------------
02537: 
02538: void wxItemWindow::setFocusedBackgroundBrush (const wxBrush & Brush)
02539: {
02540:     m_IsUsingFocusedBackgroundBrush = true;
02541:     m_FocusedBackgroundBrush = Brush;
02542: }
02543: 
02544: //-------------------------------------------------------------------------
02545: 
02546: void wxItemWindow::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02547: {
02548:     // wxWindow::OnEraseBackground (EraseEvent);
02549: }
02550: 
02551: void wxItemWindow::OnPaint (wxPaintEvent & WXUNUSED(PaintEvent))
02552: {
02553:     // wxRect WindowRect = GetRect ();
02554:     // wxSize ClientSize = GetClientSize();
02555: 
02556:     wxPaintDC PaintWxDC (this);
02557: 
02558:     wxRect WindowRect = GetClientRect();
02559: 
02560:     // NOTE BorderWidth must be <= FocusBorderWidth (if m_IsFocusable)
02561:     // or <= SelectionBorderWidth (if m_IsSelectable && !m_IsFocusable)
02562:     enum { FocusBorderWidth = 3, SelectionBorderWidth = 3, BorderWidth = 1 };
02563: 
02564:     // calculate rectangles for borders and item
02565:     wxRect ItemRect = WindowRect;
02566:     wxRect SelectionIndicationRect = WindowRect;
02567:     if (m_IsBorder)
02568:       {
02569:         if (!m_IsFocusable && !m_IsSelectable)
02570:           {
02571:             ItemRect.Inflate (-BorderWidth -1, -BorderWidth -1);
02572:             SelectionIndicationRect.Inflate (-BorderWidth -1, -BorderWidth -1);
02573:           }
02574:       }
02575: 
02576:     if (m_IsFocusable)
02577:       {
02578:         ItemRect.Inflate (-FocusBorderWidth -1, -FocusBorderWidth -1);
02579:         // ItemRect.Offset (FocusBorderWidth, FocusBorderWidth);
02580:         SelectionIndicationRect.Inflate (-FocusBorderWidth -1, -FocusBorderWidth -1);
02581:         // SelectionIndicationRect.Offset (FocusBorderWidth, FocusBorderWidth);
02582:       }
02583: 
02584:     if (m_IsSelectable)
02585:       {
02586:         ItemRect.Inflate (-SelectionBorderWidth, -SelectionBorderWidth);
02587:         // ItemRect.Offset (SelectionBorderWidth, SelectionBorderWidth);
02588:       }
02589: 
02590:     wxBrush NormalBackgroundBrush = wxBrush (GetBackgroundColour(), wxSOLID);
02591:     const wxBrush * BackgroundBrush = NULL;
02592:     if (m_IsFocusable 
02593:         && m_IsFocused
02594:         && m_IsUsingFocusedBackgroundBrush)
02595:       {
02596:         BackgroundBrush = & m_FocusedBackgroundBrush;
02597:       }
02598:     else
02599:       {
02600:         BackgroundBrush = & NormalBackgroundBrush;
02601:       }
02602: 
02603:     // draw background "behind" borders and rectangles (if there are any 
02604:     // rectangles to be drawn)
02605:     // NOTE this creates a minimal flicker if rectangles are drawn on the
02606:     // rectangle drawn here
02607:     if (WindowRect != ItemRect)
02608:       {
02609:         wxRegion BackgroundRegion (WindowRect);
02610:         BackgroundRegion.Subtract (ItemRect);
02611:         wxRegionIterator BackgroundRegionIterator (BackgroundRegion);
02612:         PaintWxDC.SetBrush (* BackgroundBrush);
02613:         PaintWxDC.SetPen (* wxTRANSPARENT_PEN);
02614:         while (BackgroundRegionIterator.HaveRects ())
02615:           {
02616:             PaintWxDC.DrawRectangle (BackgroundRegionIterator.GetRect());
02617:             ++BackgroundRegionIterator;
02618:           }
02619:       }
02620:     
02621:     // draw borders and rectangles around item
02622:     if (m_IsBorder)
02623:       {
02624:         if ((!m_IsFocusable && !m_IsSelectable)
02625:             || (!m_IsFocusable && m_IsSelectable && !m_IsSelected)
02626:             || (m_IsFocusable && !m_IsFocused))
02627:           {
02628:             // draw gray rectangle to indicate area
02629:             PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02630:             PaintWxDC.SetPen (wxPen (wxColour (0xD0, 0xD0, 0xD0), BorderWidth, wxSOLID));
02631:             PaintWxDC.DrawRectangle (WindowRect.GetX(), 
02632:                                      WindowRect.GetY(),
02633:                                      WindowRect.GetWidth(), 
02634:                                      WindowRect.GetHeight());
02635:           }
02636:       }
02637: 
02638:     if (m_IsFocusable)
02639:       {
02640:         if (m_IsFocused)
02641:           {
02642:             // draw blue rectangle around image to indicate selection:
02643:             // and draw background with a very light gray
02644:             // PaintWxDC.SetBrush (wxBrush (wxColour (0xF0, 0xF0, 0xF0), wxSOLID));
02645:             if (!m_IsUsingFocusedBackgroundBrush)
02646:               {
02647:                 PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02648:               }
02649:             else
02650:               {
02651:                 PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02652:                 // PaintWxDC.SetBrush (m_FocusedBackgroundBrush);
02653:               }
02654:             PaintWxDC.SetPen (wxPen (wxColour (192, 32, 32), FocusBorderWidth, wxSOLID));
02655:             PaintWxDC.DrawRectangle (WindowRect.GetX(), 
02656:                                      WindowRect.GetY(),
02657:                                      WindowRect.GetWidth(), 
02658:                                      WindowRect.GetHeight());
02659:           }
02660:       }
02661: 
02662:     if (m_IsSelectable)
02663:       {
02664:         if (m_IsSelected)
02665:           {
02666:             // draw blue rectangle around image to indicate selection:
02667:             PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02668:             PaintWxDC.SetPen (wxPen (wxColour (32, 0, 160), SelectionBorderWidth, wxSOLID));
02669:             PaintWxDC.DrawRectangle (SelectionIndicationRect.GetX(), 
02670:                                      SelectionIndicationRect.GetY(),
02671:                                      SelectionIndicationRect.GetWidth(), 
02672:                                      SelectionIndicationRect.GetHeight());
02673:           }
02674:       }
02675: 
02676:     // draw item
02677:     handleItemPaint (PaintWxDC, ItemRect, BackgroundBrush);
02678: }
02679: 
02680: void wxItemWindow::handleItemPaint (wxPaintDC & PaintWxDC,
02681:                                     const wxRect & ItemRect,
02682:                                     const wxBrush * BackgroundBrush)
02683: {
02684:     PaintWxDC.SetBrush (* BackgroundBrush);
02685:     PaintWxDC.SetPen (* wxTRANSPARENT_PEN);
02686:     PaintWxDC.DrawRectangle (ItemRect);
02687: }
02688: #endif // wxUSE_GUI
02689: 
02690: //=========================================================================
02691: 
02692: #if defined(__WXMSW__)
02693: 
02694: #if wxUSE_GUI
02695: void drawDIBFitted (wxDC & WxDC, int X, int Y, int Width, int Height,
02696:                     WXHDIB DIBHandle,
02697:                     const wxBrush * BackgroundBrush)
02698: {
02699:     for_once
02700:       {
02701:         if (DIBHandle == NULL)
02702:           break;
02703: 
02704:         // get DIB width and height:
02705:         BITMAPINFO * BitmapInfo = (LPBITMAPINFO) GlobalLock (DIBHandle);
02706:         if (BitmapInfo == NULL)
02707:           break;
02708: 
02709:         BITMAPINFOHEADER * BitmapInfoHeader = (LPBITMAPINFOHEADER) BitmapInfo;
02710: 
02711:         int ImageWidth = BitmapInfoHeader -> biWidth;
02712:         int ImageHeight = BitmapInfoHeader -> biHeight;
02713:         int ColorPaletteSize = getActualUsedColorCount (BitmapInfo) * sizeof (RGBQUAD);
02714: 
02715:         unsigned char * BitmapData = ((unsigned char *) BitmapInfo)
02716:           + BitmapInfoHeader -> biSize
02717:           + ColorPaletteSize;
02718: 
02719:         wxRect Rect (X, Y, Width, Height);
02720:         wxSize Size (ImageWidth, ImageHeight);
02721:         wxRect FittedRect;
02722:         fitInside (Rect, Size, FittedRect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
02723: 
02724:         FittedRect.Inflate (-1);
02725: 
02726:         // draw background around image if desired
02727:         if (BackgroundBrush != NULL)
02728:           {
02729:             wxRegion BackgroundRegion (X, Y, Width, Height);
02730:             BackgroundRegion.Subtract (FittedRect);
02731:             wxRegionIterator BackgroundRegionIterator (BackgroundRegion);
02732:             while (BackgroundRegionIterator.HaveRects ())
02733:               {
02734:                 WxDC.SetBrush (* BackgroundBrush);
02735:                 WxDC.SetPen (* wxTRANSPARENT_PEN);
02736:                 WxDC.DrawRectangle (BackgroundRegionIterator.GetRect());
02737:                 ++BackgroundRegionIterator;
02738:               }
02739:           }
02740:     
02741:         // draw DIB
02742:         HDC DCHandle = (HDC) WxDC.GetHDC();
02743:         ::SetStretchBltMode (DCHandle, COLORONCOLOR);
02744:         ::StretchDIBits (DCHandle,
02745:                          FittedRect.GetX(), FittedRect.GetY(), 
02746:                          FittedRect.GetWidth(), FittedRect.GetHeight(),
02747:                          0, 0, ImageWidth, ImageHeight,
02748:                          (void *) BitmapData,
02749:                          BitmapInfo,
02750:                          DIB_RGB_COLORS, SRCCOPY);
02751: 
02752:         FittedRect.Inflate (1);
02753: 
02754:         WxDC.SetBrush (*wxTRANSPARENT_BRUSH);
02755:         WxDC.SetPen (*wxBLACK_PEN);
02756:         WxDC.DrawRectangle (FittedRect.GetX(), FittedRect.GetY(),
02757:                             FittedRect.GetWidth(), FittedRect.GetHeight());
02758: 
02759:         GlobalUnlock (DIBHandle);
02760:     }
02761: }
02762: #endif // wxUSE_GUI
02763: 
02764: #endif
02765: 
02766: //=========================================================================
02767: 
02768: #if defined(__WXMSW__)
02769: 
02770: #if wxUSE_GUI
02771: wxImageProxy::wxImageProxy ()
02772: {
02773:     m_DIBFromFile = NULL;
02774: }
02775: 
02776: wxImageProxy::~wxImageProxy ()
02777: {
02778:     freeDIB ();
02779: }
02780: 
02781: void wxImageProxy::freeDIB ()
02782: {
02783:     if (m_DIBFromFile != NULL)
02784:       {
02785:         GlobalFree (m_DIBFromFile);
02786:         m_DIBFromFile = NULL;
02787:       }
02788: }
02789: 
02790: void wxImageProxy::discard ()
02791: {
02792:     freeDIB ();
02793: }
02794: 
02795: void wxImageProxy::draw (wxDC & PaintWxDC, int X, int Y, int Width, int Height,
02796:                          EResolutionIdent ResolutionIdent,
02797:                          const wxBrush * BackgroundBrush)
02798: {
02799:     for_once
02800:       {
02801:         WXHDIB DIBHandle = NULL;
02802:         getDIB (ResolutionIdent, DIBHandle);
02803:         if (DIBHandle == NULL)
02804:           break;
02805: 
02806:         drawDIBFitted (PaintWxDC, X, Y, Width, Height,
02807:                        DIBHandle,
02808:                        BackgroundBrush);
02809:       }
02810: }
02811: #endif // wxUSE_GUI
02812: 
02813: #endif // defined(__WXMSW__)
02814: 
02815: //=========================================================================
02816: 
02817: #if defined(__WXMSW__)
02818: 
02819: #if wxUSE_GUI
02820: wxBitmapPaintHelper::wxBitmapPaintHelper (const wxString & ResourceIdentString)
02821: {
02822:     loadBitmap (ResourceIdentString);
02823: };
02824: 
02825: wxBitmapPaintHelper::wxBitmapPaintHelper (const wxString & ResourceIdentString, HDC PaintDCHandle)
02826: {
02827:     loadBitmap (ResourceIdentString);
02828:     prepare (PaintDCHandle);
02829: };
02830: 
02831: wxBitmapPaintHelper::wxBitmapPaintHelper (wxBitmap & Bitmap)
02832: {
02833:     setBitmap (Bitmap);
02834: };
02835: 
02836: wxBitmapPaintHelper::wxBitmapPaintHelper (wxBitmap & Bitmap, HDC PaintDCHandle)
02837: {
02838:     setBitmap (Bitmap);
02839:     prepare (PaintDCHandle);
02840: };
02841: 
02842: wxBitmapPaintHelper::wxBitmapPaintHelper (int Width, int Height)
02843: {
02844:     createBitmap (Width, Height);
02845: };
02846: 
02847: wxBitmapPaintHelper::wxBitmapPaintHelper (int Width, int Height, HDC PaintDCHandle)
02848: {
02849:     createBitmap (Width, Height);
02850:     prepare (PaintDCHandle);
02851: };
02852: 
02853: wxBitmapPaintHelper::~wxBitmapPaintHelper ()
02854: {
02855:     release ();
02856: };
02857: 
02858: void wxBitmapPaintHelper::setBitmap (wxBitmap & Bitmap)
02859: {
02860:     m_BitmapRef = & Bitmap;
02861:     m_BitmapHandle = (HBITMAP) m_BitmapRef -> GetHBITMAP ();
02862: }
02863: 
02864: void wxBitmapPaintHelper::loadBitmap (const wxString & ResourceIdentString)
02865: {
02866:     // m_BitmapHandle = ::LoadBitmap (GetModuleHandle(NULL), MAKEINTRESOURCE(ResourceIdent));
02867:     m_Bitmap.LoadFile (ResourceIdentString, wxBITMAP_TYPE_BMP_RESOURCE);
02868:     m_BitmapRef = & m_Bitmap;
02869:     m_BitmapHandle = (HBITMAP) m_BitmapRef -> GetHBITMAP ();
02870: }
02871: 
02872: void wxBitmapPaintHelper::createBitmap (int Width, int Height)
02873: {
02874:     m_Bitmap.Create (Width, Height);
02875:     m_BitmapRef = & m_Bitmap;
02876:     m_BitmapHandle = (HBITMAP) m_BitmapRef -> GetHBITMAP ();
02877: }
02878: 
02879: void wxBitmapPaintHelper::prepare (HDC PaintDCHandle)
02880: {
02881:     m_MemoryDCHandle = ::CreateCompatibleDC (PaintDCHandle);
02882:     m_PreviousBitmapHandle = (HBITMAP) ::SelectObject (m_MemoryDCHandle, m_BitmapHandle);
02883: }
02884: 
02885: void wxBitmapPaintHelper::release ()
02886: {
02887:     ::SelectObject (m_MemoryDCHandle, m_PreviousBitmapHandle);
02888:     ::DeleteDC (m_MemoryDCHandle);
02889: }
02890: 
02891: int wxBitmapPaintHelper::getWidth ()
02892: {
02893:     return m_BitmapRef -> GetWidth ();
02894: }
02895: 
02896: int wxBitmapPaintHelper::getHeight ()
02897: {
02898:     return m_BitmapRef -> GetHeight ();
02899: }
02900: #endif // wxUSE_GUI
02901: 
02902: #endif // defined(__WXMSW__)
02903: 
02904: //=========================================================================
02905: 
02906: #if defined(__WXMSW__)
02907: 
02908: #if wxUSE_GUI
02909: int getActualUsedColorCount (BITMAPINFO * BitmapInfo)
02910: {
02911:     int ColorsUsed = BitmapInfo -> bmiHeader.biClrUsed;
02912:     // (for BI_RGB):
02913:     // biClrUsed == 0 is interpreted differently depending on the
02914:     // bit depth used:
02915:     // - for color depths from 1..8 bpp: if biClrUsed is set to zero
02916:     //   this means that a palette for all possible colors is there
02917:     // - for color depths 16, 24 or 32 bpp: if biClrUsed is set to 
02918:     //   zero this means that no palette is used (but biClrUsed
02919:     //   may be set to non-zero if a palette is there for 
02920:     //   output optimization purposes)
02921:     if (ColorsUsed == 0 
02922:         && BitmapInfo -> bmiHeader.biBitCount >= 1 
02923:         && BitmapInfo -> bmiHeader.biBitCount <= 8) // FUZZY 8
02924:       ColorsUsed = (1 << BitmapInfo -> bmiHeader.biBitCount);
02925: 
02926:     return ColorsUsed;
02927: }
02928: #endif // wxUSE_GUI
02929: 
02930: #endif // defined(__WXMSW__)
02931: 
02932: //=========================================================================
02933: 
02934: void WxBeep (int MilliSeconds)
02935: {
02936:     wxMinimalTimeInterval MinimalTimeInterval;
02937:     MinimalTimeInterval.setMinimalTimeInterval (MilliSeconds);
02938:     
02939:     while (!MinimalTimeInterval.check ())
02940:       {
02941:         wxBell ();
02942:       }
02943: }
02944: 
02945: //=========================================================================
02946: 
02947: void doRotateMirrorCoord (int RotationAngle, 
02948:                           bool IsHorizontallyMirrored, 
02949:                           bool IsVerticallyMirrored,
02950:                           const wxPoint & CentrePoint,
02951:                           const wxPoint & InputPoint,
02952:                           wxPoint & OutputPoint,
02953:                           bool IsRotateCenter)
02954: {
02955:     wxPoint DistanceAsPoint = InputPoint - CentrePoint;
02956: 
02957:     wxPoint RotatedDistanceAsPoint = DistanceAsPoint;
02958:     switch (RotationAngle)
02959:       {
02960:       case 90:
02961:         RotatedDistanceAsPoint.x = DistanceAsPoint.y;
02962:         RotatedDistanceAsPoint.y = -DistanceAsPoint.x;
02963:         break;
02964:       case 180:
02965:         RotatedDistanceAsPoint.x = -DistanceAsPoint.x;
02966:         RotatedDistanceAsPoint.y = -DistanceAsPoint.y;
02967:         break;
02968:       case 270:
02969:         RotatedDistanceAsPoint.x = -DistanceAsPoint.y;
02970:         RotatedDistanceAsPoint.y = DistanceAsPoint.x;
02971:         break;
02972:       }
02973:     
02974:     // PERFORMANCE NOTE doing the negation is possibly faster than 
02975:     // multiplicating with (-1)
02976:     wxPoint MirroredDistanceAsPoint = RotatedDistanceAsPoint;
02977:     if (IsHorizontallyMirrored)
02978:       {
02979:         MirroredDistanceAsPoint.x = -RotatedDistanceAsPoint.x;
02980:       }
02981:     if (IsVerticallyMirrored)
02982:       {
02983:         MirroredDistanceAsPoint.y = -RotatedDistanceAsPoint.y;
02984:       }
02985: 
02986:     wxPoint NewCentrePoint;
02987:     if (IsRotateCenter
02988:         && (RotationAngle == 90 || RotationAngle == 270))
02989:       {
02990:         NewCentrePoint.x = CentrePoint.y;
02991:         NewCentrePoint.y = CentrePoint.x;
02992:       }
02993:     else
02994:       {
02995:         NewCentrePoint.x = CentrePoint.x;
02996:         NewCentrePoint.y = CentrePoint.y;
02997:       }
02998:     OutputPoint = NewCentrePoint + MirroredDistanceAsPoint;
02999: }
03000: 
03001: //=========================================================================
03002: 
03003: wxRotationMirrorState::wxRotationMirrorState()
03004: {
03005:     m_IsHorizontallyMirrored = false;
03006:     m_IsVerticallyMirrored = false;
03007:     m_RotationAngle = 0;
03008: 
03009:     m_IsUpdateRequired = true;
03010: }
03011: 
03012: wxRotationMirrorState::~wxRotationMirrorState()
03013: {
03014: }
03015: 
03016: void wxRotationMirrorState::reset()
03017: {
03018:     m_IsHorizontallyMirrored = false;
03019:     m_IsVerticallyMirrored = false;
03020:     m_RotationAngle = 0;
03021: 
03022:     m_IsUpdateRequired = true;
03023: }
03024: 
03025: //-------------------------------------------------------------------------
03026: 
03027: void wxRotationMirrorState::mirror (bool IsHorizontallyMirrored, bool IsVerticallyMirrored)
03028: {
03029: //  handleMirrorRotation (m_RotationAngle,
03030: //                        IsHorizontallyMirrored,
03031: //                        IsVerticallyMirrored);
03032: 
03033:     if (IsHorizontallyMirrored)
03034:       {
03035:         m_IsHorizontallyMirrored = !m_IsHorizontallyMirrored;
03036:       }
03037:     if (IsVerticallyMirrored)
03038:       {
03039:         m_IsVerticallyMirrored = !m_IsVerticallyMirrored;
03040:       }
03041: 
03042:     m_IsUpdateRequired = true;
03043: }
03044: 
03045: void wxRotationMirrorState::rotate (int RotationAngle)
03046: {
03047:     m_RotationAngle += RotationAngle;
03048:     m_RotationAngle = (((int) m_RotationAngle) / 90) * 90;
03049:     if (m_RotationAngle < 0)
03050:       m_RotationAngle += 360;
03051:     m_RotationAngle %= 360;
03052: 
03053:     handleMirrorRotation (RotationAngle,
03054:                           m_IsHorizontallyMirrored,
03055:                           m_IsVerticallyMirrored);
03056: 
03057:     m_IsUpdateRequired = true;
03058: }
03059: 
03060: void wxRotationMirrorState::handleMirrorRotation(int RotationAngle,
03061:                                                 bool & IsHorizontallyMirrored,
03062:                                                 bool & IsVerticallyMirrored) 
03063: {
03064:     if (RotationAngle < 0)
03065:       RotationAngle += 360;
03066:     RotationAngle %= 360;
03067:     if (RotationAngle == 90 
03068:         || RotationAngle == 270)
03069:       {
03070:         if ((IsHorizontallyMirrored && !IsVerticallyMirrored)
03071:             || (!IsHorizontallyMirrored && IsVerticallyMirrored))
03072:           {
03073:             // swap mirroring axes
03074:             bool TempVerticallyMirrored = IsVerticallyMirrored;
03075:             IsVerticallyMirrored = IsHorizontallyMirrored;
03076:             IsHorizontallyMirrored = TempVerticallyMirrored;
03077:           }
03078:       }
03079: }
03080: 
03081: void wxRotationMirrorState::getNormalizedState(int & RotationAngle,
03082:                                               bool & IsHorizontallyMirrored,
03083:                                               bool & IsVerticallyMirrored) 
03084: {
03085:     IsHorizontallyMirrored = m_IsHorizontallyMirrored;
03086:     IsVerticallyMirrored = m_IsVerticallyMirrored;
03087:     RotationAngle = m_RotationAngle;
03088: 
03089:     // normalize to reduce number of required image transformations:
03090:     if (IsHorizontallyMirrored 
03091:         && IsVerticallyMirrored)
03092:       {
03093:         RotationAngle += 180;
03094:         RotationAngle %= 360;
03095:         IsHorizontallyMirrored = false;
03096:         IsVerticallyMirrored = false;
03097:       }
03098: }
03099: 
03100: //-------------------------------------------------------------------------
03101: 
03102: void wxRotationMirrorState::assign (const wxRotationMirrorState & RHSRotationMirrorState)
03103: {
03104:     m_RotationAngle = RHSRotationMirrorState.m_RotationAngle;
03105:     m_IsHorizontallyMirrored = RHSRotationMirrorState.m_IsHorizontallyMirrored;
03106:     m_IsVerticallyMirrored = RHSRotationMirrorState.m_IsVerticallyMirrored;
03107: 
03108:     m_IsUpdateRequired = true;
03109: }
03110: 
03111: void wxRotationMirrorState::subtract (const wxRotationMirrorState & LHSRotationMirrorState,
03112:                                       const wxRotationMirrorState & RHSRotationMirrorState)
03113: {
03114:     reset();
03115: 
03116:     int RotationAngleDifference = LHSRotationMirrorState.m_RotationAngle
03117:       - RHSRotationMirrorState.m_RotationAngle;
03118: 
03119:     wxRotationMirrorState LHS;
03120:     wxRotationMirrorState RHS;
03121:     LHS.assign (LHSRotationMirrorState);
03122:     RHS.assign (RHSRotationMirrorState);
03123:     
03124:     // rotate LHS to rotation angle of RHS, then determine differences in
03125:     // mirroring, then apply mirroring and finally rotate
03126:     LHS.rotate (- RotationAngleDifference);
03127:     m_IsHorizontallyMirrored = RHS.m_IsHorizontallyMirrored != LHS.m_IsHorizontallyMirrored;
03128:     m_IsVerticallyMirrored = RHS.m_IsVerticallyMirrored != LHS.m_IsVerticallyMirrored;
03129:     rotate (RotationAngleDifference);
03130:     
03131:     m_IsUpdateRequired = true;
03132: }
03133: 
03134: //=========================================================================
03135: 
03136: #ifdef M_WxExtLib_IsFilteredDIBEnabled
03137: 
03138: #if defined(__WXMSW__)
03139: 
03140: #if wxUSE_GUI
03141: wxFilteredDIB::wxFilteredDIB ()
03142: {
03143:     m_Brightness = 0.;
03144:     m_Contrast = 0.;
03145:     m_RedGamma = 1.;
03146:     m_GreenGamma = 1.;
03147:     m_BlueGamma = 1.;
03148:     m_IsInverted = false;
03149:     m_IsColorAdjustmentModified = true;
03150: 
03151:     // m_IsPaletteBasedColorAdjustmentEnabled = true;
03152:     m_IsOriginalColorPaletteRemembered = false;
03153:     m_IsModifiedColorPaletteRemembered = false;
03154: 
03155:     m_IsImageMagickFilteringRequired = false;
03156:     m_IsFilteringModified = true;
03157: 
03158:     m_PreviousRotationMirrorState.reset ();
03159:     m_RotationMirrorState.reset();
03160:     m_RotationMirrorState.m_IsUpdateRequired = true;
03161: 
03162:     m_SourceDIBHandle = NULL;
03163:     m_IsOwningSourceImage = false;
03164:     m_ResultDIBHandle = NULL;
03165:     m_IsOwningResultImage = true;
03166: 
03167:     m_FilteredDIBBitsPerPixel = 24;
03168: }
03169: 
03170: wxFilteredDIB::~wxFilteredDIB ()
03171: {
03172:     freeResultImage ();
03173:     freeSourceImage ();
03174: }
03175: 
03176: //-------------------------------------------------------------------------
03177: 
03178: void wxFilteredDIB::setBrightnessContrast (double Brightness, double Contrast)
03179: {
03180:     m_Brightness = Brightness;
03181:     m_Contrast = Contrast;
03182:     m_IsColorAdjustmentModified = true;
03183: }
03184: 
03185: void wxFilteredDIB::setColorAdjustment (double RedGamma, double GreenGamma,
03186:                                        double BlueGamma)
03187: {
03188:     m_RedGamma = RedGamma;
03189:     m_GreenGamma = GreenGamma;
03190:     m_BlueGamma = BlueGamma;
03191:     m_IsColorAdjustmentModified = true;
03192: }
03193: 
03194: void wxFilteredDIB::setInversion (bool IsInverted)
03195: {
03196:     m_IsInverted = IsInverted;
03197:     m_IsColorAdjustmentModified = true;
03198: }
03199: 
03200: //-------------------------------------------------------------------------
03201: 
03202: bool wxFilteredDIB::rememberPalette (WXHDIB DIBHandle,
03203:                                        wxFilteredDIBColorPaletteArray & ColorPaletteByteArray)
03204: {
03205:     int DIBColorPaletteEntryCount = ::GetActualUsedColorCountInDIBHandle (DIBHandle);
03206: 
03207:     ColorPaletteByteArray.Clear ();
03208: 
03209:     if (DIBColorPaletteEntryCount == 0)
03210:       return false;
03211: 
03212:     ColorPaletteByteArray.Insert ((BYTE) 0, /* array index */ 0,
03213:                                   DIBColorPaletteEntryCount);
03214: 
03215:     // HACK WARN access of items in m_OriginalColorPaletteByteArray
03216:     ::ImportExportColorPaletteIntoDIB ((BYTE *) (& ColorPaletteByteArray.Item(0)),
03217:                                        DIBColorPaletteEntryCount,
03218:                                        DIBHandle,
03219:                                        false);
03220: 
03221:     return true;
03222: }
03223: 
03224: bool wxFilteredDIB::restorePalette (WXHDIB DIBHandle,
03225:                                       wxFilteredDIBColorPaletteArray & ColorPaletteByteArray)
03226: {
03227:     int ColorPaletteEntryCount = ColorPaletteByteArray.GetCount();
03228:     
03229:     if (ColorPaletteEntryCount != 0)
03230:       {
03231:         // HACK WARN access of items in m_OriginalColorPaletteByteArray
03232:         ::ImportExportColorPaletteIntoDIB ((BYTE *) (& ColorPaletteByteArray.Item(0)),
03233:                                            ColorPaletteEntryCount,
03234:                                            DIBHandle,
03235:                                            true);
03236:       }
03237: 
03238:     return true;
03239: }
03240: 
03241: void wxFilteredDIB::rememberOriginalPalette ()
03242: {
03243:     rememberPalette (m_SourceDIBHandle,
03244:                      m_OriginalColorPaletteByteArray);
03245:     m_IsOriginalColorPaletteRemembered = true;
03246: }
03247: 
03248: void wxFilteredDIB::rememberModifiedPalette ()
03249: {
03250:     rememberPalette (m_SourceDIBHandle,
03251:                      m_ModifiedColorPaletteByteArray);
03252:     m_IsModifiedColorPaletteRemembered = true;
03253: }
03254: 
03255: void wxFilteredDIB::setOriginalPaletteIntoSourceImage ()
03256: {
03257:     if (m_IsOriginalColorPaletteRemembered)
03258:       {
03259:         restorePalette (m_SourceDIBHandle,
03260:                         m_OriginalColorPaletteByteArray);
03261:       }
03262: }
03263: 
03264: void wxFilteredDIB::setModifiedPaletteIntoSourceImage ()
03265: {
03266:     if (m_IsModifiedColorPaletteRemembered)
03267:       {
03268:         restorePalette (m_SourceDIBHandle,
03269:                         m_ModifiedColorPaletteByteArray);
03270:       }
03271: }
03272: 
03273: bool wxFilteredDIB::getIsUsePaletteAlienation ()
03274: {
03275:     return false;
03276: }
03277: 
03278: bool wxFilteredDIB::applyPaletteAlienation (wxFilteredDIBColorPaletteArray & ColorPaletteByteArray)
03279: {
03280:     return false;
03281: }
03282: 
03283: //-------------------------------------------------------------------------
03284: 
03285: void wxFilteredDIB::resetRotationMirror ()
03286: {
03287:     m_RotationMirrorState.reset();
03288: }
03289: 
03290: void wxFilteredDIB::rotate (int RotationAngle)
03291: {
03292:     m_RotationMirrorState.rotate (RotationAngle);
03293: }
03294: 
03295: void wxFilteredDIB::mirror (bool IsHorizontallyMirrored, bool IsVerticallyMirrored)
03296: {
03297:     m_RotationMirrorState.mirror (IsHorizontallyMirrored, IsVerticallyMirrored);
03298: }
03299: 
03300: //-------------------------------------------------------------------------
03301: 
03302: void wxFilteredDIB::setIsFilteringModified ()
03303: {
03304:     m_IsFilteringModified = true;
03305: }
03306: 
03307: void wxFilteredDIB::setIsImageMagickFilteringRequired (bool IsRequired)
03308: {
03309:     m_IsImageMagickFilteringRequired = IsRequired;
03310:     m_IsFilteringModified = true;
03311: }
03312: 
03313: //-------------------------------------------------------------------------
03314: 
03315: void wxFilteredDIB::setSourceImage (const WXHDIB & SourceDIBHandle)
03316: {
03317:     m_SourceDIBHandle = SourceDIBHandle;
03318:     m_IsColorAdjustmentModified = true;
03319:     m_IsFilteringModified = true;
03320: }
03321: 
03322: void wxFilteredDIB::getResultImage (WXHDIB & ResultDIBHandle)
03323: {
03324:     if (m_ResultDIBHandle == NULL)
03325:       ResultDIBHandle = m_SourceDIBHandle;
03326:     else
03327:       ResultDIBHandle = m_ResultDIBHandle;
03328: }
03329: 
03330: void wxFilteredDIB::setIsOwningSourceImage (bool IsOwningSourceImage)
03331: {
03332:     m_IsOwningSourceImage = IsOwningSourceImage;
03333: }
03334: 
03335: void wxFilteredDIB::setIsOwningResultImage (bool IsOwningResultImage)
03336: {
03337:     m_IsOwningResultImage = IsOwningResultImage;
03338: }
03339: 
03340: //-------------------------------------------------------------------------
03341: 
03342: void wxFilteredDIB::updateResultImage()
03343: {
03344:     if (! (m_IsColorAdjustmentModified
03345:            || m_IsFilteringModified
03346:            || m_RotationMirrorState.m_IsUpdateRequired))
03347:       return;
03348: 
03349:     // rotation mirror optmization: avoid applying color adjustment and filtering
03350:     // if only rotation or mirroring has changed - this assumes that rotation 
03351:     // and mirroring doesn't change image contents (apart from rotation and 
03352:     // mirroring)
03353:     bool IsRotationMirrorOnly = m_RotationMirrorState.m_IsUpdateRequired
03354:       && ! m_IsColorAdjustmentModified
03355:       && ! m_IsFilteringModified;
03356: 
03357:     for_once
03358:       {
03359:         if (!IsRotationMirrorOnly)
03360:           freeResultImage ();
03361: 
03362:         // obtain original DIB
03363:         if (m_SourceDIBHandle == NULL)
03364:             break;
03365: 
03366:         //-------------------------------------------------------------------------
03367:         // try to apply color adjustment to palette DIBs
03368: 
03369:         bool IsPaletteBasedColorAdjustmentDone = false;
03370: 
03371:         if (m_IsPaletteBasedColorAdjustmentEnabled
03372:             && (! IsRotationMirrorOnly))
03373:           {
03374:             // do palette modification using an ImageMagick filter - to this end, 
03375:             // convert to 'image', then run filtering, then write result back
03376:             // into the DIB palette
03377:             ExceptionInfo exceptionInfo;
03378:             GetExceptionInfo (& exceptionInfo);
03379:     
03380:             Image * PaletteMagickImage = NULL;
03381: 
03382:             if (!m_IsOriginalColorPaletteRemembered)
03383:               {
03384:                 rememberOriginalPalette ();
03385:               }
03386:             else
03387:               {
03388:                 setOriginalPaletteIntoSourceImage ();
03389:               }
03390: 
03391:             // WARN DIBColorPaletteEntryCount may be only palette for optimization 
03392:             // purposes, which would have to be ignored
03393:             int DIBColorPaletteEntryCount = ::GetActualUsedColorCountInDIBHandle (m_SourceDIBHandle);
03394:             bool IsPaletteImage = DIBColorPaletteEntryCount > 0;
03395:             if (IsPaletteImage)
03396:               {
03397:                 // use m_ModifiedColorPaletteByteArray as temporary buffer
03398:                 // to apply palette alienation and modification
03399:                 rememberPalette (m_SourceDIBHandle, m_ModifiedColorPaletteByteArray);
03400: 
03401:                 if (IsPaletteImage
03402:                     && getIsUsePaletteAlienation())
03403:                   {
03404:                     applyPaletteAlienation (m_ModifiedColorPaletteByteArray);
03405:                   }
03406: 
03407:                 const char * MapString = "BGRA"; // or maybe RGBO
03408:                 RGBQUAD * PaletteRGBAArray = (RGBQUAD *) & (m_ModifiedColorPaletteByteArray[0]);
03409:                 // transfer color values from palette to ImageMagick Image: 
03410:                 // the whole palette is put into a single row with DIBColorPaletteEntryCount
03411:                 // "pixels"
03412:                 PaletteMagickImage = ConstituteImage (DIBColorPaletteEntryCount, 
03413:                                                       /* Height */ 1, 
03414:                                                       MapString, 
03415:                                                       CharPixel, 
03416:                                                       PaletteRGBAArray,
03417:                                                       & exceptionInfo);
03418:                 //
03419:                 //            bool IsPaletteImage = ::DIBPaletteToImage (m_SourceDIBHandle, 
03420:                 //                                                       & PaletteMagickImage,
03421:                 // & exceptionInfo);
03422:                 
03423:                 if (PaletteMagickImage == NULL)
03424:                   break;
03425: 
03426:                 // note that applyColorAdjustment() is an in-place operation
03427:                 applyColorAdjustment (& PaletteMagickImage, & exceptionInfo);
03428:                 if (PaletteMagickImage == NULL)
03429:                   break;
03430:             
03431:                 bool IsOk = ::ImageToDIBPalette (PaletteMagickImage, 
03432:                                                  m_SourceDIBHandle,
03433:                                                  & exceptionInfo);
03434:                 ::DestroyImage (PaletteMagickImage);
03435:                 PaletteMagickImage = NULL;
03436: 
03437:                 // WARN should add exception/error handling/parsing after 
03438:                 // each function
03439: 
03440:                 if (IsOk == false)
03441:                   break;
03442:                 
03443:                 IsPaletteBasedColorAdjustmentDone = true;
03444: 
03445:                 rememberModifiedPalette ();
03446:               }
03447:           }
03448: 
03449:         WXHDIB IntermediateDIBHandle = m_SourceDIBHandle; 
03450:         WXHDIB PreviousIntermediateDIBHandle = m_SourceDIBHandle;
03451:         
03452:         //-------------------------------------------------------------------------
03453:         // convert to ImageMagick image and apply color adjustment and ImageMagick filters
03454: 
03455:         if ((m_IsImageMagickFilteringRequired
03456:              || !IsPaletteBasedColorAdjustmentDone)
03457:             && (!IsRotationMirrorOnly))
03458:           {
03459:             // do ImageMagick filtering - to this end, convert to 'image'
03460:             // then run filtering, then convert back to DIB
03461:             ExceptionInfo exceptionInfo;
03462:             GetExceptionInfo (& exceptionInfo);
03463:     
03464:             Image * MagickImage = ::DIBToImage (PreviousIntermediateDIBHandle, 
03465:                                                 & exceptionInfo);
03466:             if (MagickImage == NULL)
03467:               break;
03468: 
03469:             // check not to do color adjustment twice
03470:             if (! IsPaletteBasedColorAdjustmentDone)
03471:               {
03472:                 applyColorAdjustment (& MagickImage, & exceptionInfo);
03473:               }
03474:     
03475:             applyImageMagickFiltering (& MagickImage, & exceptionInfo);
03476:             if (MagickImage == NULL)
03477:               break;
03478:             
03479:             IntermediateDIBHandle = ::ImageToDIB (MagickImage, 
03480:                                                   m_FilteredDIBBitsPerPixel,
03481:                                                   & exceptionInfo);
03482:             ::DestroyImage (MagickImage);
03483:             MagickImage = NULL;
03484:             if (IntermediateDIBHandle == NULL)
03485:               break;
03486: 
03487:             // WARN should add exception/error handling/parsing after 
03488:             // each function
03489:             // throwException (exceptionInfo);
03490:             // if (image)
03491:             //    throwException (image->exception);
03492:           }
03493: 
03494:         // clean up of temporary DIB's
03495:         if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03496:             && PreviousIntermediateDIBHandle != m_SourceDIBHandle)
03497:           {
03498:             freeImage (PreviousIntermediateDIBHandle);
03499:           }
03500:         PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03501: 
03502:         //-------------------------------------------------------------------------
03503:         // rotate and mirror:
03504: 
03505:         int RotationAngle;
03506:         bool IsHorizontallyMirrored;
03507:         bool IsVerticallyMirrored;
03508:         if (IsRotationMirrorOnly)
03509:           {
03510:             wxRotationMirrorState RelativeRotationMirrorState;
03511: 
03512:             RelativeRotationMirrorState.subtract (m_RotationMirrorState,
03513:                                                   m_PreviousRotationMirrorState);
03514: 
03515:             RelativeRotationMirrorState.getNormalizedState (RotationAngle, 
03516:                                                             IsHorizontallyMirrored, 
03517:                                                             IsVerticallyMirrored);
03518: 
03519:             // setup DIB handle for input to rotation function
03520:             if (m_ResultDIBHandle != NULL)
03521:               {
03522:                 // if NULL, PreviousIntermediateDIBHandle should be set to
03523:                 // m_SourceDIBHandle
03524:                 PreviousIntermediateDIBHandle = m_ResultDIBHandle;
03525:               }
03526:           }
03527:         else
03528:           {
03529:             m_RotationMirrorState.getNormalizedState (RotationAngle, 
03530:                                                       IsHorizontallyMirrored, 
03531:                                                       IsVerticallyMirrored);
03532:           }
03533: 
03534:         if (RotationAngle != 0
03535:             || IsHorizontallyMirrored
03536:             || IsVerticallyMirrored)
03537:           {
03538:             bool IsNewRotatedDIBHandle = false;
03539:             applyImageRotationMirroring (RotationAngle,
03540:                                          IsHorizontallyMirrored,
03541:                                          IsVerticallyMirrored,
03542:                                          PreviousIntermediateDIBHandle,
03543:                                          IntermediateDIBHandle,
03544:                                          IsNewRotatedDIBHandle);
03545: 
03546:             // release temporary memory
03547:             // if (IsNewFilteredDIBHandle)
03548:             //  freeImage (FilteredDIBHandle);
03549:             if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03550:                 && PreviousIntermediateDIBHandle != m_SourceDIBHandle)
03551:               {
03552:                 freeImage (PreviousIntermediateDIBHandle);
03553:               }
03554:             PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03555:           }
03556: 
03557:         if (PreviousIntermediateDIBHandle != m_SourceDIBHandle)
03558:           {
03559:             m_ResultDIBHandle = PreviousIntermediateDIBHandle;
03560:           }
03561:         else
03562:           {
03563:             m_ResultDIBHandle = NULL;
03564:           }
03565: 
03566:         m_IsColorAdjustmentModified = false;
03567:         m_IsFilteringModified = false;
03568:         m_RotationMirrorState.m_IsUpdateRequired = false;
03569:         m_PreviousRotationMirrorState.assign (m_RotationMirrorState);
03570: 
03571:         handleResultImageChanged ();
03572:       }
03573: }
03574: 
03575: //-------------------------------------------------------------------------
03576: 
03577: void wxFilteredDIB::handleResultImageChanged ()
03578: {
03579: }
03580: 
03581: //-------------------------------------------------------------------------
03582: 
03583: void wxFilteredDIB::applyColorAdjustment (struct _Image ** MagickImagePtrPtr,
03584:                                             struct _ExceptionInfo * exceptionInfo)
03585: {
03586:     for_once
03587:       {
03588:         Image * MagickImage = *MagickImagePtrPtr;
03589:         if (MagickImage == NULL)
03590:           break;
03591: 
03592:         if (m_IsInverted)
03593:           NegateImage (MagickImage, 0);
03594: 
03595:         // WARN ContrastImage() seems to use only the sign of 
03596:         // the 'sharpen' parameter
03597:         ContrastImage (MagickImage, (m_Contrast * 100));
03598: 
03599:         // support for brightness currently done by modifying the gamma
03600:         // of each channel
03601:         double RedGamma = m_Brightness + m_RedGamma;
03602:         double GreenGamma = m_Brightness + m_GreenGamma;
03603:         double BlueGamma = m_Brightness + m_BlueGamma;
03604: 
03605:         levelGamma (RedGamma);
03606:         levelGamma (GreenGamma);
03607:         levelGamma (BlueGamma);
03608: 
03609:         GammaImageChannel (MagickImage, RedChannel, RedGamma);
03610:         GammaImageChannel (MagickImage, GreenChannel, GreenGamma);
03611:         GammaImageChannel (MagickImage, BlueChannel, BlueGamma);
03612:       }
03613: }
03614: 
03615: void wxFilteredDIB::levelGamma (double & Gamma)
03616: {
03617:     if (Gamma < 1.)
03618:       {
03619:         Gamma = 1. - (1. - Gamma) * 0.75;
03620:       }
03621:     else if (Gamma > 1.)
03622:       {
03623:         Gamma = 1. + (Gamma - 1.) * 1.75;
03624:       }
03625:     if (Gamma < 0.1)
03626:       {
03627:         Gamma = 0.1;
03628:       }
03629: }
03630: 
03631: void wxFilteredDIB::applyImageMagickFiltering (struct _Image ** IMImage,
03632:                                                  struct _ExceptionInfo * exceptionInfo)
03633: {
03634: }
03635: 
03636: void wxFilteredDIB::applyImageRotationMirroring (int RotationAngle,
03637:                                                    bool IsHorizontallyMirrored,
03638:                                                    bool IsVerticallyMirrored,
03639:                                                    WXHDIB & InputDIBHandle,
03640:                                                    WXHDIB & OutputDIBHandle,
03641:                                                    bool & IsNewOutputDIBHandle)
03642: {
03643:     WXHDIB IntermediateDIBHandle = InputDIBHandle; 
03644:     WXHDIB PreviousIntermediateDIBHandle = InputDIBHandle;
03645: 
03646:     // rotate image data if required
03647:     switch (RotationAngle)
03648:       {
03649:       case 90:
03650:         IntermediateDIBHandle = applyDIBRotation (PreviousIntermediateDIBHandle, 90);
03651:         break;
03652:       case 180:
03653:         IntermediateDIBHandle = applyDIBRotation (PreviousIntermediateDIBHandle, 180);
03654:         break;
03655:       case 270:
03656:         IntermediateDIBHandle = applyDIBRotation (PreviousIntermediateDIBHandle, 270);
03657:         break;
03658:       }
03659: 
03660:     // clean up of temporary DIB's
03661:     if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03662:         && PreviousIntermediateDIBHandle != InputDIBHandle)
03663:       {
03664:         freeImage (PreviousIntermediateDIBHandle);
03665:       }
03666:     PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03667: 
03668:     // apply horizontal mirroring if required
03669:     if (IsHorizontallyMirrored)
03670:       {
03671:         IntermediateDIBHandle = applyDIBMirroring (PreviousIntermediateDIBHandle, false);
03672:       }
03673: 
03674:     // clean up of temporary DIB's
03675:     if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03676:         && PreviousIntermediateDIBHandle != InputDIBHandle)
03677:       {
03678:         freeImage (PreviousIntermediateDIBHandle);
03679:       }
03680:     PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03681: 
03682:     // apply vertical mirroring if required
03683:     if (IsVerticallyMirrored)
03684:       {
03685:         IntermediateDIBHandle = applyDIBMirroring (PreviousIntermediateDIBHandle, true);
03686:       }
03687: 
03688:     // clean up of temporary DIB's
03689:     if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03690:         && PreviousIntermediateDIBHandle != InputDIBHandle)
03691:       {
03692:         freeImage (PreviousIntermediateDIBHandle);
03693:       }
03694:     PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03695: 
03696:     // set output variables
03697:     OutputDIBHandle = PreviousIntermediateDIBHandle;
03698:     IsNewOutputDIBHandle = InputDIBHandle != OutputDIBHandle;
03699: }
03700: 
03701: //-------------------------------------------------------------------------
03702: 
03703: void wxFilteredDIB::freeSourceImage()
03704: {
03705:     if (m_IsOwningSourceImage)
03706:       {
03707:         freeImage (m_SourceDIBHandle);
03708:       }
03709: }
03710: 
03711: void wxFilteredDIB::freeResultImage()
03712: {
03713:     if (m_IsOwningResultImage)
03714:       {
03715:         freeImage (m_ResultDIBHandle);
03716:       }
03717: }
03718: 
03719: void wxFilteredDIB::freeImage (WXHDIB & DIBHandle)
03720: {
03721:     if (DIBHandle != NULL)
03722:       {
03723:         GlobalFree (DIBHandle);
03724:         DIBHandle = NULL;
03725:       }
03726: }
03727: #endif // wxUSE_GUI
03728: 
03729: #endif // defined(__WXMSW__)
03730: 
03731: #endif
03732: 
03733: //=========================================================================
03734: 
03735: wxChoiceManager::wxChoiceManager ()
03736: {
03737:     m_FocusedSourceItemIndex = -1;
03738:     m_FocusedChoiceItemIndex = -1;
03739: }
03740: 
03741: void wxChoiceManager::OnSelect ()
03742: {
03743:     selectIntoChoice (getChoiceFocus(), getSourceFocus());
03744: }
03745: 
03746: void wxChoiceManager::OnDeselect ()
03747: {
03748:     deselectFromChoice (getChoiceFocus());
03749: }
03750: 
03751: void wxChoiceManager::OnClearSelection ()
03752: {
03753:     int ChoiceItemCount = getChoiceItemCount ();
03754:     for (int ChoiceItemIndex=0; ChoiceItemIndex<ChoiceItemCount; ++ChoiceItemIndex)
03755:       {
03756:         deselectFromChoice (ChoiceItemIndex, false);
03757:       }
03758:     updateChoiceView ();
03759: }
03760: 
03761: void wxChoiceManager::OnSourceLeftMouseButton (int SourceItemIndex)
03762: {
03763:     bool IsNewlyFocused = getSourceFocus () != SourceItemIndex;
03764:         
03765:     if (IsNewlyFocused)
03766:       setSourceFocus (SourceItemIndex);
03767: 
03768:     handleSelection (IsNewlyFocused, getChoiceFocus (), SourceItemIndex);
03769: }
03770: 
03771: void wxChoiceManager::OnSourceRightMouseButton (int SourceItemIndex)
03772: {
03773:     int DocumentIdent = getSourceDocument (SourceItemIndex);
03774:     deselectFromChoice (findChoiceItemIndex (DocumentIdent));
03775: }
03776: 
03777: void wxChoiceManager::OnChoiceLeftMouseButton (int ChoiceItemIndex)
03778: {
03779:     bool IsNewlyFocused = getChoiceFocus () != ChoiceItemIndex;
03780: 
03781:     if (IsNewlyFocused)
03782:       setChoiceFocus (ChoiceItemIndex);
03783: 
03784:     handleSelection (IsNewlyFocused, ChoiceItemIndex, getSourceFocus());
03785: }
03786: 
03787: void wxChoiceManager::OnChoiceRightMouseButton (int ChoiceItemIndex)
03788: {
03789:     deselectFromChoice (ChoiceItemIndex);
03790: }
03791: 
03792: //-------------------------------------------------------------------------
03793: 
03794: void wxChoiceManager::handleSelection (bool IsNewlyFocused, int ChoiceItemIndex,
03795:                                          int SourceItemIndex)
03796: {
03797:     bool IsChoiceHavingDocument =  getChoiceDocument (ChoiceItemIndex) != -1;
03798:     bool IsDocumentAlreadyAssigned = findChoiceItemIndex (getSourceDocument (SourceItemIndex)) != -1;
03799:     
03800:     if ((!IsNewlyFocused || (!IsChoiceHavingDocument && !IsDocumentAlreadyAssigned))
03801:         && SourceItemIndex != -1 
03802:         && ChoiceItemIndex != -1)
03803:       {
03804:         selectIntoChoice (ChoiceItemIndex, SourceItemIndex);
03805:       }
03806: }
03807: 
03808: //-------------------------------------------------------------------------
03809: 
03810: void wxChoiceManager::selectIntoChoice (int ChoiceItemIndex, int SourceItemIndex,
03811:                                                  bool IsUpdateChoiceView)
03812: {
03813:     int ChoiceItemCount = getChoiceItemCount();
03814: 
03815:     if (ChoiceItemIndex != -1 && SourceItemIndex != -1)
03816:       {
03817:         // create entries of -1 if necessary
03818:         if (ChoiceItemIndex >= ChoiceItemCount)
03819:           {
03820:             insertChoiceDocument (-1, ChoiceItemCount, ChoiceItemIndex + 1 - ChoiceItemCount);
03821:           }
03822: 
03823:         deselectFromChoice (ChoiceItemIndex, 
03824:                              /* IsUpdateChoiceView */ false);
03825: 
03826:         setSelection (SourceItemIndex, true);
03827:         int DocumentIdent = getSourceDocument (SourceItemIndex);
03828:         setChoiceDocument (ChoiceItemIndex, DocumentIdent);
03829: 
03830:         if (IsUpdateChoiceView)
03831:           updateChoiceView ();
03832:       }
03833: }
03834: 
03835: void wxChoiceManager::deselectFromChoice (int ChoiceItemIndex, 
03836:                                                    bool IsUpdateChoiceView)
03837: {
03838:     if (ChoiceItemIndex != -1 && ChoiceItemIndex < getChoiceItemCount())
03839:       {
03840:         int DocumentIdent = getChoiceDocument (ChoiceItemIndex);
03841: 
03842:         if (DocumentIdent != -1)
03843:           {
03844:             int SourceItemIndex = findSourceItemIndex (DocumentIdent);
03845:             setChoiceDocument (ChoiceItemIndex, -1);
03846:             int OtherChoiceItemIndex = findChoiceItemIndex (DocumentIdent);
03847:             setSelection (SourceItemIndex, OtherChoiceItemIndex != -1);
03848: 
03849:             if (IsUpdateChoiceView)
03850:               updateChoiceView ();
03851:           }
03852:       }
03853: }
03854: 
03855: //-------------------------------------------------------------------------
03856: 
03857: int wxChoiceManager::getSourceFocus ()
03858: {
03859:     return m_FocusedSourceItemIndex;
03860: }
03861: 
03862: void wxChoiceManager::setSourceFocus (int NewFocusedItemIndex)
03863: {
03864:     if (NewFocusedItemIndex == m_FocusedSourceItemIndex)
03865:       return;
03866: 
03867:     if (m_FocusedSourceItemIndex != -1)
03868:       {
03869:         updateSourceFocus (m_FocusedSourceItemIndex, false);
03870:       }
03871:     m_FocusedSourceItemIndex = NewFocusedItemIndex;
03872: 
03873:     if (m_FocusedSourceItemIndex != -1)
03874:       {
03875:         updateSourceFocus (m_FocusedSourceItemIndex, true);
03876:       }
03877: }
03878: 
03879: int wxChoiceManager::getChoiceFocus ()
03880: {
03881:     return m_FocusedChoiceItemIndex;
03882: }
03883: 
03884: void wxChoiceManager::setChoiceFocus (int NewFocusedItemIndex)
03885: {
03886:     if (NewFocusedItemIndex == m_FocusedChoiceItemIndex)
03887:       return;
03888: 
03889:     if (m_FocusedChoiceItemIndex != -1)
03890:       {
03891:         updateChoiceFocus (m_FocusedChoiceItemIndex, false);
03892:       }
03893:     m_FocusedChoiceItemIndex = NewFocusedItemIndex;
03894: 
03895:     if (m_FocusedChoiceItemIndex != -1)
03896:       {
03897:         updateChoiceFocus (m_FocusedChoiceItemIndex, true);
03898:       }
03899: }
03900: 
03901: void wxChoiceManager::redoSelections ()
03902: {
03903:     int SourceItemCount = getSourceItemCount ();
03904:     for (int SourceItemIndex=0; SourceItemIndex<SourceItemCount; ++SourceItemIndex)
03905:       {
03906:         int DocumentIdent = getSourceDocument (SourceItemIndex);
03907:         setSelection (SourceItemIndex, findChoiceItemIndex (DocumentIdent) != -1);
03908:       }
03909:     updateChoiceView ();
03910: }
03911: 
03912: void wxChoiceManager::setSelection (int SourceItemIndex, bool IsSelect)
03913: {
03914:     if (SourceItemIndex == -1)
03915:       return;
03916: 
03917:     updateSelection (SourceItemIndex, IsSelect);
03918: }
03919: 
03920: //-------------------------------------------------------------------------
03921: 
03922: int wxChoiceManager::findSourceItemIndex (int DocumentIdent)
03923: {
03924:     int SourceDocumentCount = getSourceItemCount();
03925: 
03926:     for (int SourceDocumentIndex=0; SourceDocumentIndex<SourceDocumentCount; ++SourceDocumentIndex)
03927:       {
03928:         if (getSourceDocument (SourceDocumentIndex) == DocumentIdent)
03929:           return SourceDocumentIndex;
03930:       }
03931: 
03932:     return -1;
03933: }
03934: 
03935: int wxChoiceManager::findChoiceItemIndex (int DocumentIdent)
03936: {
03937:     int ChoiceDocumentCount = getChoiceItemCount ();
03938: 
03939:     for (int ChoiceDocumentIndex=0; ChoiceDocumentIndex<ChoiceDocumentCount; ++ChoiceDocumentIndex)
03940:       {
03941:         if (getChoiceDocument (ChoiceDocumentIndex) == DocumentIdent)
03942:           return ChoiceDocumentIndex;
03943:       }
03944: 
03945:     return -1;
03946: }
03947: 
03948: //=========================================================================
03949: 
03950: wxDefaultParentWindowFunc s_GlobalDefaultParentWindowFunc = NULL;
03951: 
03952: void wxSetGlobalDefaultParentWindowFunc (wxDefaultParentWindowFunc Func)
03953: {
03954:     s_GlobalDefaultParentWindowFunc = Func;
03955: }
03956: 
03957: wxDefaultParentWindowFunc wxGetGlobalDefaultParentWindowFunc ()
03958: {
03959:     return s_GlobalDefaultParentWindowFunc;
03960: }
03961: 
03962: wxWindow * wxGetDefaultParentWindow (wxWindow * ParentWindow)
03963: {
03964:     if (ParentWindow != NULL)
03965:       return ParentWindow;
03966: 
03967:     if (s_GlobalDefaultParentWindowFunc != NULL)
03968:       {
03969:         return s_GlobalDefaultParentWindowFunc (ParentWindow);
03970:       }
03971: 
03972:     // return ParentWindow, which is NULL here
03973:     return ParentWindow;
03974: }
03975: 
03976: //=========================================================================
03977: 
  [main]    [up]  
DaicasWeb v.1.50.0102  //   Daniel Käps  //   April 12, 2007  //   Impressum / Imprint 
http://www.daicas.net/WxExtLib/src/WxMisc.cpp.html