camresource.cpp

Go to the documentation of this file.
00001 // $Id: camresource.cpp 1702 2006-08-16 15:21:09Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 #include "camtypes.h"
00100 
00101 //#include "camconfig.h"
00102 //#include "camresource.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00103 
00104 #if !defined(EXCLUDE_FROM_XARLIB)
00105 #include "cartctl.h"
00106 #include "drawctl.h"
00107 #include "colourmat.h"
00108 #endif
00109 
00110 //#include "camelot.h"
00111 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 
00113 #define PRELOAD_BITMAPS 0
00114 
00115 CC_IMPLEMENT_DYNCREATE(CamResource, CCObject)
00116 
00117 // Declare smart memory handling in Debug builds
00118 #define new CAM_DEBUG_NEW
00119 
00120 ResIDToString * CamResource::pHash = NULL;
00121 ResIDToString * CamResource::pObjectNameHash = NULL;
00122 wxFileSystem * CamResource::pwxFileSystem = NULL;
00123 wxBitmap * CamResource::pSplashBitmap= NULL;
00124 wxAdvSplashScreen * CamResource::pSplashScreen = NULL;
00125 wxString * CamResource::pResourcePath = NULL;
00126 CamResourceRemember * CamResource::pFirstRemember=NULL;
00127 BOOL CamResource::HaveCheckedResourcePath = FALSE;
00128 wxLocale * CamResource::m_pLocale = NULL;
00129 wxHelpProvider * CamResource::m_pHelpProvider = NULL;
00130 BOOL CamResource::s_GenerateXRCCheck = FALSE;
00131 
00132 ResourceStringToBitmap * CamResource::pBitmapHash = NULL;
00133 
00134 TCHAR * CamResource::DefaultString = _T("[Resource string not found]");
00135 TCHAR * CamResource::DefaultObjectName = _T("[Object name not Found]");
00136 
00137 wxArrayString CamResource::BitmapExtensions;
00138 
00139 #if 0
00140 #if !defined(EXCLUDE_FROM_XARLIB)
00141 // Bodge for the toolbar bitmap
00142 wxImage                 imageBevelTool;
00143 wxImage                 imageBezTool;
00144 wxImage                 imageBlendTool;
00145 wxImage                 imageContourTool;
00146 wxImage                 imageElipTool;
00147 wxImage                 imageFHandTool;
00148 wxImage                 imageGradTool;
00149 wxImage                 imageLiveEffectTool;
00150 wxImage                 imageMouldTool;
00151 wxImage                 imagePenTool;
00152 wxImage                 imagePush;
00153 wxImage                 imageRectTool;
00154 wxImage                 imageRegShapeTool;
00155 wxImage                 imageSelTool;
00156 wxImage                 imageShadrwTool;
00157 wxImage                 imageSlicetool;
00158 wxImage                 imageTextTool;
00159 wxImage                 imageTransTool;
00160 wxImage                 imageZoomTool;
00161 #endif
00162 #endif
00163 
00164 /********************************************************************************************
00165 
00166 >   static inline ResourceID CamResource::GetResourceID(const TCHAR * Resource)
00167 
00168 
00169     Author:     Alex_Bligh <alex@alex.org.uk>
00170     Created:    02/12/2005
00171     Inputs:     Resource - textual name of the resource to lookup
00172     Outputs:    
00173     Returns:    the resource ID of the resource
00174     Purpose:    Converts a textual resource identified (_R(IDS_BLOBBY) or whatever) to a numeric
00175                 resource ID. This ALWAYS succeeds as it creates a new one if there is not
00176                 one in the current table. Can be called from static initialization phase
00177                 so BE CAREFUL with this call. No fancy TRACE() stuff etc. please.
00178     Errors:     -
00179     SeeAlso:    -
00180 
00181 ********************************************************************************************/
00182 
00183 /********************************************************************************************
00184 
00185 >   static inline TCHAR * CamResource::GetText(ResourceID Resource)
00186 
00187 
00188     Author:     Alex_Bligh <alex@alex.org.uk>
00189     Created:    02/12/2005
00190     Inputs:     Resource - resource ID of text to look up
00191     Outputs:    
00192     Returns:    the text of the resource, or a default string
00193     Purpose:    Converts a ResourceID to a text string, returning a default string on failure
00194     Errors:     -
00195     SeeAlso:    -
00196 
00197 ********************************************************************************************/
00198 
00199 /********************************************************************************************
00200 
00201 >   static inline TCHAR * CamResource::GetTextFail(ResourceID Resource)
00202 
00203 
00204     Author:     Alex_Bligh <alex@alex.org.uk>
00205     Created:    02/12/2005
00206     Inputs:     Resource - resource ID of text to look up
00207     Outputs:    
00208     Returns:    the text of the resource, or 0 if not found
00209     Purpose:    Converts a ResourceID to a text string, returning NULL on failure
00210     Errors:     -
00211     SeeAlso:    -
00212 
00213 ********************************************************************************************/
00214 
00215 /********************************************************************************************
00216 
00217 >   static inline TCHAR * CamResource::GetObjectName(ResourceID Resource)
00218 
00219 
00220     Author:     Alex_Bligh <alex@alex.org.uk>
00221     Created:    02/12/2005
00222     Inputs:     Resource - resource ID of object name to look up
00223     Outputs:    
00224     Returns:    the object name of the resource, or a default string
00225     Purpose:    Converts a ResourceID to an object name, returning a default string on failure
00226     Errors:     -
00227     SeeAlso:    -
00228 
00229 ********************************************************************************************/
00230 
00231 /********************************************************************************************
00232 
00233 >   static inline TCHAR * CamResource::GetObjectNameFail(ResourceID Resource)
00234 
00235 
00236     Author:     Alex_Bligh <alex@alex.org.uk>
00237     Created:    02/12/2005
00238     Inputs:     Resource - resource ID of object name to look up
00239     Outputs:    
00240     Returns:    the object name of the resource, or 0 if not found
00241     Purpose:    Converts a ResourceID to an object name, returning NULL on failure
00242     Errors:     -
00243     SeeAlso:    -
00244 
00245 ********************************************************************************************/
00246 
00247 #define CRFNH_BUCKETS 1024
00248 
00249 class CamResourceFixNameEntry
00250 {
00251 public:
00252     static UINT32 MakeHash(const TCHAR * k)
00253     {
00254         UINT32 hash = 0;
00255 
00256         while( *k )
00257         {
00258             hash += *k++;
00259             hash += (hash << 10);
00260             hash ^= (hash >> 6);
00261         }
00262         hash += (hash << 3);
00263         hash ^= (hash >> 11);
00264 
00265         return (hash + (hash << 15)) % CRFNH_BUCKETS;
00266     }
00267 
00268     typedef CamResourceFixNameEntry * pCamResourceFixNameEntry;
00269     
00270     static const TCHAR * Find(const TCHAR * from, const TCHAR * to = NULL)
00271     {
00272         // Ensure we have an array
00273         if (!pArray)
00274         {
00275             pArray=new pCamResourceFixNameEntry[CRFNH_BUCKETS];
00276             UINT32 i;
00277             for (i=0; i<CRFNH_BUCKETS; i++) pArray[i]=NULL;
00278         }
00279         if (!pArray) return from;
00280         UINT32 h = MakeHash(from);
00281         pCamResourceFixNameEntry * pPoint = &(pArray[h]);
00282         while (*pPoint) // while we have a valid pointer to a "next" item
00283         {
00284             if (!camStrcmp( (*pPoint)->MapFrom, from ) ) return ( (*pPoint)->MapTo );
00285             pPoint = &((*pPoint)->pNext);
00286         }
00287 
00288         // no match - if they have not asked us to insert, return it unaltered
00289         if (!to) return from;
00290         // We now knonw pPoint is a pointer to a NULL CamResourceFixedNameEntry *, where we will insert ourselves
00291         *pPoint = new(CamResourceFixNameEntry);
00292         if (*pPoint)
00293         {
00294             // No need to strdup these as we know this map is only created with constants, because
00295             // the map is created in init phase
00296             (*pPoint)->MapFrom = from;
00297             (*pPoint)->MapTo = to;
00298         }
00299         return to;
00300     }
00301 
00302     static void MakeResources() // Iterates through the hash and calls GetResourceID on them
00303     {
00304         if (pArray)
00305         {
00306             INT32 i;
00307             for (i=0; i<CRFNH_BUCKETS; i++)
00308             {
00309                 pCamResourceFixNameEntry p=pArray[i];
00310                 while (p)
00311                 {
00312                     CamResource::GetResourceID(p->MapFrom);
00313                     p = p->pNext;
00314                 }
00315             }
00316         }
00317     }
00318 
00319     const TCHAR * MapFrom;
00320     const TCHAR * MapTo;
00321     CamResourceFixNameEntry * pNext;
00322     
00323     static pCamResourceFixNameEntry *pArray;
00324 
00325     CamResourceFixNameEntry() {MapFrom =NULL ; MapTo = NULL ; pNext = NULL;}
00326 };
00327 
00328 CamResourceFixNameEntry::pCamResourceFixNameEntry *CamResourceFixNameEntry::pArray = NULL;
00329 
00330 /********************************************************************************************
00331 
00332 >   static const TCHAR * CamResource::FixObjectName(const TCHAR * ObjectName)
00333 
00334 
00335     Author:     Alex_Bligh <alex@alex.org.uk>
00336     Created:    02/12/2005
00337     Inputs:     ObjectName - the object name of the resource to fix up
00338     Outputs:    
00339     Returns:    The fixed up object name
00340     Purpose:    Renames some of the resources from Windows to wx Style
00341                 This must match the mapping in rc2xml.pl. This allows wx to do
00342                 intelligent things with (say) the _R(ID_OK) button on dialogs, but for
00343                 us to still be able to use _R(IDOK) in Camelot rather than having
00344                 to write _R(wxID_OK) which is actually what we mean (but that would
00345                 be unkernel-like. Note this is called at static init time so the
00346                 obvious route of using a wxHash isn't going to work, sadly
00347     Errors:     -
00348     SeeAlso:    -
00349 
00350 ********************************************************************************************/
00351 
00352 #define FNOMAP(x,y) CamResourceFixNameEntry::Find(_T(x),_T(y))
00353 
00354 const TCHAR * CamResource::FixObjectName(const TCHAR * ObjectName)
00355 {
00356     if (!CamResourceFixNameEntry::pArray)
00357     {
00358         // Don't delete the comments or normalize.pl will unhelpfully convert the bits in quotes
00359         FNOMAP("IDOK", "wxID_OK"); //NORESOURCEFIX
00360         FNOMAP("IDCANCEL", "wxID_CANCEL"); //NORESOURCEFIX
00361         FNOMAP("IDAPPLY", "wxID_APPLY"); //NORESOURCEFIX
00362         FNOMAP("ID_APPLY_NOW", "wxID_APPLY"); //NORESOURCEFIX
00363         FNOMAP("ID_CC_APPLY_NOW", "wxID_APPLY"); //NORESOURCEFIX
00364         FNOMAP("ID_FILE_OPEN", "wxID_OPEN"); //NORESOURCEFIX
00365         FNOMAP("ID_FILE_CLOSE", "wxID_CLOSE"); //NORESOURCEFIX
00366         FNOMAP("ID_FILE_SAVE", "wxID_SAVE"); //NORESOURCEFIX
00367         FNOMAP("ID_FILE_SAVE_AS", "wxID_SAVEAS"); //NORESOURCEFIX
00368         FNOMAP("ID_APP_EXIT", "wxID_EXIT"); //NORESOURCEFIX
00369         FNOMAP("ID_FILE_PRINT", "wxID_PRINT"); //NORESOURCEFIX
00370         FNOMAP("ID_FILE_PRINT_PREVIEW", "wxID_PREVIEW"); //NORESOURCEFIX
00371         FNOMAP("ID_FILE_PRINT_SETUP", "wxID_PRINT_SETUP"); //NORESOURCEFIX
00372         FNOMAP("ID_APP_ABOUT", "wxID_ABOUT"); //NORESOURCEFIX
00373         FNOMAP("ID_EDIT_UNDO", "wxID_UNDO"); //NORESOURCEFIX
00374         FNOMAP("ID_EDIT_CUT", "wxID_CUT"); //NORESOURCEFIX
00375         FNOMAP("ID_EDIT_COPY", "wxID_COPY"); //NORESOURCEFIX
00376         FNOMAP("ID_EDIT_PASTE", "wxID_PASTE"); //NORESOURCEFIX
00377         FNOMAP("IDYES", "wxID_YES"); //NORESOURCEFIX
00378         FNOMAP("IDNO", "wxID_NO"); //NORESOURCEFIX
00379         FNOMAP("IDHELP", "wxID_HELP"); //NORESOURCEFIX
00380         
00381         CamResourceFixNameEntry::MakeResources();
00382     }
00383     const TCHAR * ret= CamResourceFixNameEntry::Find(ObjectName);
00384     if (pObjectNameHash && ret !=ObjectName) // don't do during static init
00385     {
00386         TRACEUSER("amb",_T("**Mapped %s to %s"),ObjectName,ret);
00387     }
00388     return ret;
00389 }
00390 
00391 /********************************************************************************************
00392 
00393 >   static void CamResource::RememberDuringStaticInit(const TCHAR * ObjectName)
00394 
00395 
00396     Author:     Alex_Bligh <alex@alex.org.uk>
00397     Created:    19/12/2005
00398     Inputs:     ObjectName - the name of the object to remember
00399     Outputs:    -
00400     Returns:    -
00401     Purpose:    Remembers an objectname that has been GetResourceID'd prior to
00402                 the ObjectHash existing
00403     Errors:     -
00404     SeeAlso:    -
00405 
00406 As GetResourceID is called during StaticInit, the ObjectHash won't be set up. wxHash cannot
00407 safely be used in static initialization (no, I don't really know why, it seems to work),
00408 so we remember a list of these, then blat them out back through GetResourceID during
00409 ::Init.
00410 
00411 ********************************************************************************************/
00412 
00413 void CamResource::RememberDuringStaticInit(const TCHAR * ObjectName)
00414 {
00415     TCHAR * text = camStrdup(ObjectName);
00416     if (!text) return;  // we can't error, we can't trace, so meekly forget it
00417     CamResourceRemember * pRem = new CamResourceRemember;
00418     if (!pRem) return;  // we can't error, we can't trace, so meekly forget it
00419     
00420     pRem->text = text;  // fill in text
00421     
00422     // Now add to our linked list, and return
00423     pRem->next = pFirstRemember?pFirstRemember:NULL;
00424     pFirstRemember=pRem;
00425     return;
00426 }
00427 
00428 /********************************************************************************************
00429 
00430 >   static void CamResource::AddStringResource(const TCHAR * name, const TCHAR * text, ResourceID r=0)
00431 
00432 
00433     Author:     Alex_Bligh <alex@alex.org.uk>
00434     Created:    02/12/2005
00435     Inputs:     name - object name to add
00436                 text - text asssociated with it
00437                 r - numeric ResourceID or 0 to allocate it
00438     Outputs:    None
00439     Returns:    None
00440     Purpose:    Initialize resources
00441     Errors:     via wxMessageBox
00442     SeeAlso:    -
00443 
00444 Read controls out of this window, and put into string table. Then process children
00445 recursively.
00446 
00447 ********************************************************************************************/
00448 
00449 void CamResource::AddStringResource(const TCHAR * name, const TCHAR * text, ResourceID r)
00450 {
00451     ResourceID r2=GetResourceID(name);
00452     if (r)
00453     {
00454         if (r != r2)
00455         {
00456             TRACE(_T("Possible duplicate label %s\n"),text);
00457         }
00458     }
00459     else
00460     {
00461         r = r2;
00462     }
00463 
00464     if (!name || !text)
00465     {
00466         TRACE(_T("Resource ID %d is blank\n"),r);
00467         ERROR3("Resource is blank");
00468     }
00469     else
00470     {
00471         ResIDToString::iterator i=pHash->find(r);
00472         if (i!=pHash->end())
00473         {
00474             TRACE(_T("Resource ID %d name <%s> has duplicate definitions: <%s> and <%s>\n"),r,name,text,i->second);
00475         }
00476         else
00477         {
00478             const TCHAR * tcopy = camStrdup(text);
00479             (*pHash)[r] = tcopy;
00480 
00481             const TCHAR * t = GetText(r);
00482             if (t!=tcopy)
00483             {
00484                 ERROR3("Resource string does not match local copy");
00485             }       
00486         }
00487     }
00488 }
00489 
00490 /********************************************************************************************
00491 
00492 >   static BOOL CamResource::ReadStringTableFile()
00493 
00494 
00495     Author:     Alex_Bligh <alex@alex.org.uk>
00496     Created:    02/12/2005
00497     Inputs:     None
00498     Outputs:    None
00499     Returns:    TRUE if succeeded, FALSE if fails
00500     Purpose:    Initialize resources
00501     Errors:     via wxMessageBox
00502     SeeAlso:    -
00503 
00504 We can't use the CCLexFile stuff because it has not yet been initiated.
00505 
00506 ********************************************************************************************/
00507 
00508 BOOL CamResource::ReadStringTableFile()
00509 {
00510     TRACET(_T("ReadStringTableFile() called"));
00511     CamResource res;
00512     INT32 count=0;
00513 
00514     wxFSFile* f = res.OpenwxFSFile(_T("strings.lst"));  // NB destructor of 'res' deletes this
00515     if (!f)
00516     {
00517         TRACE(_T("Could not load strings.lst"));
00518         return FALSE;
00519     }
00520 
00521     wxInputStream * s = f->GetStream();
00522     if (!s)
00523     {
00524         TRACE(_T("Could not load strings.lst - no stream"));
00525         return FALSE;
00526     }
00527 
00528     while (!s->Eof())
00529     {
00530 #define MAX_TAG_LENGTH 1024
00531         char buf[MAX_TAG_LENGTH];
00532         
00533         char c=0;       // Deliberate - file is not Unicode for now
00534         INT32 l=0;
00535         while (!s->Eof() && (c=s->GetC()) && (c != '\n') && (c != '\t') && (l<MAX_TAG_LENGTH))
00536         {
00537             buf[l++]=c;
00538         }
00539         buf[l++]=0;
00540         buf[MAX_TAG_LENGTH-1]=0;
00541         if (buf[0])
00542         {
00543             wxString name(buf, wxConvUTF8);
00544     
00545             if (c == '\n')
00546             {
00547                 buf[0]=0;
00548             }
00549             else
00550             {
00551                 l=0;
00552                 while (!s->Eof() && (c=s->GetC()) && (c != '\n') && (l<MAX_TAG_LENGTH))
00553                 {
00554                     buf[l++]=c;
00555                 }
00556                 buf[MAX_TAG_LENGTH-1]=0;
00557             }
00558             buf[l++]=0;
00559             wxString text(buf, wxConvUTF8);
00560 
00561             // Now de-XMLize it
00562             wxString otext;
00563             UINT32 n=0;
00564             while (n<text.Length())
00565             {
00566                 wxChar tc=text.GetChar(n++);
00567                 if (tc==_T('&'))
00568                 {
00569                     // It's an ampersand escape sequence. Read till a semicolon
00570                     wxString seq;
00571                     while (tc !=_T(';') && n<text.Length())
00572                     {
00573                         tc=text.GetChar(n++);
00574                         seq+=tc;
00575                     }
00576                     
00577                     if (seq == _T("amp;"))
00578                     {
00579                         tc=_T('&');
00580                     }
00581                     else if (seq == _T("lt;"))
00582                     {
00583                         tc=_T('<');
00584                     }
00585                     else if (seq == _T("gt;"))
00586                     {
00587                         tc=_T('>');
00588                     }
00589                     else if (seq == _T("quot;"))
00590                     {
00591                         tc=_T('"');
00592                     }
00593                     else if ((seq.Length()>3) && (seq.GetChar(0)==_T('#')) && (seq.GetChar(1)==_T('x')))
00594                     {
00595                         tc=_T('?');
00596                         UINT32 code=tc;
00597                         // It's an alphanumeric form of a unicode character in hex
00598 #if wxUSE_UNICODE
00599                         sscanf((const char*)seq.mb_str(wxConvUTF8), "#x%x;", &code);
00600 #else
00601                         sscanf((const char*)seq.c_str(), "#x%x;", &code);   
00602 #endif
00603                         tc=(TCHAR)(code);
00604                     }
00605                     else if ((seq.Length()>2) && (seq.GetChar(0)==_T('#')) && ((seq.GetChar(1)>=_T('0')) && (seq.GetChar(1)<=_T('9'))))
00606                     {
00607                         tc=_T('?');
00608                         UINT32 code=tc;
00609                         // It's an alphanumeric form of a unicode character in decimal
00610 #if wxUSE_UNICODE
00611                         sscanf((const char*)seq.mb_str(wxConvUTF8), "#%d;", &code);
00612 #else
00613                         sscanf((const char*)seq.c_str(), "#%d;", &code);                        
00614 #endif
00615                         tc=(TCHAR)(code);
00616                     }
00617                     else
00618                     {
00619                         TRACE(_T("CamResource::ReadStringTableFile - Unknown XML escape sequence [&%s] in %s, %s"),seq.c_str(),name.c_str(),text.c_str());
00620                         otext+=_T('&')+seq;
00621                         tc=0; // don't add
00622                     }
00623                 }
00624                 if (tc)
00625                 {
00626                     otext+=tc;
00627                 }
00628             }
00629 
00630             // Here we could translate it using wxGetTranslation
00631             // Or we could muck around on non UTF-8 encodings
00632             // but that would be really boring.
00633             count++;
00634             AddStringResource(name.c_str(), ::wxGetTranslation(otext.c_str()));
00635         }
00636     }
00637 
00638     TRACE(_T("Added %d strings"),count);
00639     if (count<1000) return FALSE; // some bad thing has happened.
00640 
00641     return TRUE;
00642 }
00643 
00644 /********************************************************************************************
00645 
00646 >   static void CamResource::ProcessWindowAndChildren(wxWindow * pWindow)
00647 
00648 
00649     Author:     Alex_Bligh <alex@alex.org.uk>
00650     Created:    02/12/2005
00651     Inputs:     pWindow - pointer to window to process
00652     Outputs:    None
00653     Returns:    None
00654     Purpose:    Initialize resources
00655     Errors:     via wxMessageBox
00656     SeeAlso:    -
00657 
00658 Read controls out of this window, and put into string table. Then process children
00659 recursively.
00660 
00661 ********************************************************************************************/
00662 
00663 
00664 void CamResource::ProcessWindowAndChildren(wxWindow * pWindow)
00665 {
00666     // Process this one
00667     if (pWindow->IsKindOf(CLASSINFO(wxStaticText)))
00668     {
00669         ResourceID r=(ResourceID) pWindow->GetId();
00670 
00671 //      Don't be so foolish as to think the following would work. Oh no. What this would
00672 //      do is return a temporary wxString, take the address of it's data member, then
00673 //      mark it as discardable on the stack leaving the data member to be overwritten.
00674 //      Ho de ho de ho.
00675 //      const TCHAR * name = pWindow->GetName().c_str();
00676 //      const TCHAR * text = pWindow->GetLabel().c_str();
00677 
00678         wxString sname = pWindow->GetName();
00679         wxString stext = pWindow->GetLabel();
00680 
00681         AddStringResource((const TCHAR *)sname.c_str(),(const TCHAR *)stext.c_str(), r);
00682 
00683     }
00684 
00685     // Now process children if any
00686     wxWindowList::Node * pNode = pWindow->GetChildren().GetFirst();
00687     while (pNode)
00688     {
00689         ProcessWindowAndChildren(pNode->GetData());
00690         pNode = pNode->GetNext();
00691     }
00692     return;
00693 }
00694 
00695 /********************************************************************************************
00696 
00697 >   static BOOL CamResource::InitXmlResource()
00698 
00699 
00700     Author:     Alex_Bligh <alex@alex.org.uk>
00701     Created:    02/12/2005
00702     Inputs:     None
00703     Outputs:    None
00704     Returns:    TRUE if succeeded, FALSE if fails
00705     Purpose:    Initialize resources
00706     Errors:     via wxMessageBox
00707     SeeAlso:    -
00708 
00709 ********************************************************************************************/
00710 
00711 BOOL CamResource::InitXmlResource()
00712 {
00713     TRACET(_T("CamResource::InitXmlResource() called, doing Load() of strings.xrc"));
00714 
00715     if (!wxXmlResource::Get()->Load(GetResourceFilePath(_T("strings.xrc"))))
00716     {
00717         TRACE(_T("Could not load strings.xrc"));
00718         return FALSE;
00719     }
00720 
00721     TRACET(_T("CamResource::InitXmlResource() called - loaded strings"));
00722 
00723     return true;
00724 }
00725 
00726 /********************************************************************************************
00727 
00728 >   static wxString CamResource::GetResourceFilePath( const wxString &str, BOOL AllowOverride = TRUE )
00729 
00730 
00731     Author:     Alex_Bligh <alex@alex.org.uk>
00732     Created:    02/12/2005
00733     Inputs:     str - the string to look up
00734     Outputs:    
00735     Returns:    the path to load it from
00736     Purpose:    Destructor
00737     Errors:     -
00738     SeeAlso:    -
00739 
00740 By default this will return the MemoryFS path, however, if & when we support overriding
00741 of resources in a resource directory, this will under the appopriate circumstances
00742 use a differnt path. Note this can only be called AFTER the resource system is initialized.
00743 
00744 If an empty string is specified, it returns the overridden resource path (if one exists)
00745 (so long as the override is set to TRUE), or failing that the memory resource path
00746 
00747 ********************************************************************************************/
00748 
00749 wxString CamResource::GetResourceFilePath( const wxString &str, BOOL AllowOverride )
00750 {
00751     // If we are given a full path, then return. For the time being that's anything with a colon or a slash in it
00752     // as the resources file is flat
00753     if ( ((str.Find(_T(':')))>=0) || ((str.Find(_T('/')))>=0) || ((str.Find(_T('\\')))>=0) )
00754     {
00755         return str;
00756     }
00757 
00758     wxString mfn = _T("memory:resources#zip:");
00759 
00760     if (AllowOverride && pResourcePath && pwxFileSystem)
00761     {
00762         wxString fn = *pResourcePath + _T('/');
00763 
00764         // If we have not run the check on the checksum do it now.
00765         if (!HaveCheckedResourcePath)
00766         {
00767             if (CheckResourcePath(mfn+_T("xrc.check"),fn+_T("xrc.check")))
00768             {
00769                 HaveCheckedResourcePath = TRUE;
00770             }
00771             else
00772             {
00773                 wxMessageBox(_T("Ignoring resource path specified on command line due to bad resource checksum"), _T("Resource loading error"));
00774                 delete (pResourcePath);
00775                 pResourcePath = NULL;
00776             }
00777         }
00778 
00779         if (str.IsEmpty() && pResourcePath)
00780             return fn;
00781 
00782         fn += str;
00783 
00784         if (pResourcePath) // may have been cleared
00785         {
00786             wxFSFile * pTwxFSFile = pwxFileSystem->OpenFile(fn);
00787             if (pTwxFSFile)
00788             {
00789                 // we found it, so close it & return
00790                 delete pTwxFSFile;
00791                 return fn;
00792             }
00793         }
00794     }
00795     return mfn + str;
00796 }
00797 
00798 
00799 /********************************************************************************************
00800 
00801 >   static void * CamResource::LoadFile( const wxString &str1, UINT32 * pSize )
00802 
00803 
00804     Author:     Alex_Bligh <alex@alex.org.uk>
00805     Created:    02/12/2005
00806     Inputs:     str1 - filename to load
00807     Outputs:    size - the size of the file
00808     Returns:    A pointer to the file (free with free()) or NULL
00809     Purpose:    -
00810     Errors:     -
00811     SeeAlso:    -
00812 
00813 ********************************************************************************************/
00814 
00815 void * CamResource::LoadFile( const wxString &str1, UINT32* pSize )
00816 {
00817     wxFSFile * pTwxFSFile1 = pwxFileSystem->OpenFile(str1);
00818     if (!pTwxFSFile1)
00819     {
00820         delete pTwxFSFile1;
00821         return NULL;
00822     }
00823 
00824     wxInputStream * pStream1 = pTwxFSFile1->GetStream(); // we don't have to delete this ourselves
00825     if (!pStream1)
00826     {
00827         delete (pTwxFSFile1);
00828         return NULL;
00829     }
00830 
00831     UINT32 size1=pStream1->GetSize();
00832 
00833     if (!size1)
00834     {
00835         delete (pTwxFSFile1);
00836         return NULL;
00837     }
00838 
00839     void * mem1 = malloc(size1+4); // safety
00840     if (!mem1)
00841     {
00842         delete (pTwxFSFile1);
00843         return NULL;
00844     }
00845 
00846     memset(mem1, 0, size1);
00847     pStream1->Read(mem1, size1); // throws exceptions if can't read
00848     
00849     delete (pTwxFSFile1); // Closes it
00850 
00851     if (pSize)
00852         *pSize=size1;
00853     return mem1;
00854 }
00855 
00856 /********************************************************************************************
00857 
00858 >   static BOOL CamResource::CheckResourcePath( const wxString &str1, const wxString &str2 )
00859 
00860 
00861     Author:     Alex_Bligh <alex@alex.org.uk>
00862     Created:    02/12/2005
00863     Inputs:     str1, str2 - filenames to check
00864     Outputs:    
00865     Returns:    TRUE if the files are identical, else false
00866     Purpose:    -
00867     Errors:     -
00868     SeeAlso:    -
00869 
00870 This routine compares two small files. If they are equal, it returns true, else it
00871 returns false. This allows checking of the checksum. This is reasonably resilient to
00872 some fool creating a huge xrc.check as we only read the files if the lengths are
00873 equal, which means we never read more than the size of the file bound into the
00874 executable.
00875 
00876 ********************************************************************************************/
00877 
00878 BOOL CamResource::CheckResourcePath( const wxString &str1, const wxString &str2 )
00879 {
00880     if (!pwxFileSystem) return FALSE;
00881 
00882     UINT32 size1=0;
00883     UINT32 size2=0;
00884     void * mem1=LoadFile(str1, &size1);
00885     void * mem2=LoadFile(str2, &size2);
00886 
00887     if (!mem1)
00888     {
00889         if (mem2)
00890             free(mem2);
00891         return FALSE; // and we can't generate an xrc.check
00892     }
00893 
00894     BOOL same = mem2 && ( size1 == size2) && !memcmp(mem1, mem2, size1);
00895 
00896     if (!same && s_GenerateXRCCheck)
00897     {
00898         wxMessageBox(_T("You have requested XaraLX to generate a checksum for resources which may not match the binary in question. "
00899                         "A checksum will be generated, but the program may not be stable."), _T("XaraLX Resource system warning"));
00900 
00901         wxFile f;
00902         f.Create(str2, wxFile::write);
00903         if (!f.IsOpened() || (f.Write(mem1, size1) != size1))
00904         {
00905             wxMessageBox(_T("Failed to write xrc.check file ")+str2, _T("XaraLX resource system"));
00906         }
00907         f.Close();
00908         same=TRUE;
00909     }
00910 
00911 
00912     if (mem1)
00913         free (mem1);
00914 
00915     if (mem2)
00916         free (mem2);
00917 
00918     return same;
00919 }
00920 
00921 
00922 /********************************************************************************************
00923 
00924 >   void  CamResource::SetResourceFilePath( const wxString &str )
00925 
00926 
00927     Author:     Alex_Bligh <alex@alex.org.uk>
00928     Created:    02/12/2005
00929     Inputs:     str - the string to set
00930     Outputs:    
00931     Returns:    the path to load it from
00932     Purpose:    Destructor
00933     Errors:     -
00934     SeeAlso:    -
00935 
00936 This sets the override resource path - this function can be called before
00937 CamResource::Init()
00938 
00939 ********************************************************************************************/
00940 
00941 
00942 void CamResource::SetResourceFilePath( const wxString &str )
00943 {
00944     if (pResourcePath)
00945     {
00946         delete (pResourcePath);
00947         pResourcePath = NULL;
00948     }
00949 
00950     HaveCheckedResourcePath=FALSE;
00951 
00952     if (!str.IsEmpty())
00953     {
00954         pResourcePath = new(wxString);
00955         if (pResourcePath) *pResourcePath = str;
00956     }
00957     return;
00958 }
00959 
00960 
00961 #if !defined(EXCLUDE_FROM_XARLIB)
00962 
00963 /********************************************************************************************
00964 
00965 >   static BOOL CamResource::AddBitmaps(wxString &Path)
00966 
00967 
00968     Author:     Alex_Bligh <alex@alex.org.uk>
00969     Created:    01/01/2005
00970     Inputs:     Path - the path to add
00971     Outputs:    None
00972     Returns:    TRUE if succeeded, FALSE if fails
00973     Purpose:    Add all bitmaps in the path
00974     Errors:     via wxMessageBox
00975     SeeAlso:    -
00976 
00977 ********************************************************************************************/
00978 
00979 BOOL CamResource::AddBitmaps(wxString &Path)
00980 {
00981     ERROR2IF(!pBitmapHash, FALSE, "No bitmap hash");
00982     ERROR2IF(!pwxFileSystem, FALSE, "No filesystem");
00983 
00984     TRACEUSER("amb",_T("Adding bitmaps from %s"),Path.c_str());
00985 
00986     wxString fn = pwxFileSystem->FindFirst(Path+_T("*.*"), wxFILE); // This isn't an MSDOS-ism - we are looking for files with an extension
00987     while (!fn.IsEmpty())
00988     {
00989         wxString LeafName = fn.Mid(Path.Length());
00990 
00991         if (IsBitmapName(LeafName))
00992         {
00993     
00994             ResourceStringToBitmap::iterator i=pBitmapHash->find(LeafName);
00995     
00996             if (i==pBitmapHash->end())  // ignore if we already have an entry
00997             {
00998 #if PRELOAD_BITMAPS 
00999                 wxImage * pBitmap=new wxImage;
01000                 if (!pBitmap)
01001                     return FALSE;
01002     
01003     //          TRACE(_T("Loading bitmap %s"),fn.c_str());
01004                 if (LoadwxImage(*pBitmap, LeafName))
01005                     (*pBitmapHash)[camStrdup(LeafName.c_str())]=pBitmap;
01006                 else
01007                 {
01008                     ERROR3_PF((_T("Could not load bitmap %s"),fn.c_str()));
01009                     delete pBitmap;
01010                 }
01011 #else
01012                 (*pBitmapHash)[camStrdup(LeafName.c_str())]=NULL; // Mark as there, but needs to be loaded
01013 #endif
01014             }
01015         }
01016     
01017         fn = pwxFileSystem->FindNext();
01018     }
01019     return TRUE;
01020 }
01021 
01022 /********************************************************************************************
01023 
01024 >   static BOOL CamResource::IsBitmapName(const wxString &str)
01025 
01026 
01027     Author:     Alex_Bligh <alex@alex.org.uk>
01028     Created:    24/01/2005
01029     Inputs:     str - sting to look at
01030     Outputs:    None
01031     Returns:    TRUE if the extension is a bitmap type
01032     Purpose:    Determine whether or not a path points to a bitmap
01033     Errors:     -
01034     SeeAlso:    -
01035 
01036 ********************************************************************************************/
01037 
01038 BOOL CamResource::IsBitmapName(const wxString &str)
01039 {
01040     wxString ext=GetBitmapExtension(str);
01041     return (BitmapExtensions.Index(ext) != wxNOT_FOUND);
01042 }
01043 
01044 /********************************************************************************************
01045 
01046 >   static wxString CamResource::GetBitmapExtension(const wxString &str);
01047 
01048 
01049     Author:     Alex_Bligh <alex@alex.org.uk>
01050     Created:    24/01/2005
01051     Inputs:     str - sting to look at
01052     Outputs:    None
01053     Returns:    Empty string if none found, else the extenstion
01054     Purpose:    Determines the extension of a bitmap
01055     Errors:     -
01056     SeeAlso:    -
01057 
01058 ********************************************************************************************/
01059 
01060 wxString CamResource::GetBitmapExtension(const wxString &str)
01061 {
01062     // Find the rightmost dot
01063     INT32 i=str.Find(_T('.'), TRUE);
01064     if (i<0)
01065         return wxEmptyString;
01066     else
01067         return str.Mid(i+1);
01068 }
01069 
01070 /********************************************************************************************
01071 
01072 >   static wxString CamResource::GetBitmapBaseName(const wxString &str);
01073 
01074 
01075     Author:     Alex_Bligh <alex@alex.org.uk>
01076     Created:    24/01/2005
01077     Inputs:     str - sting to look at
01078     Outputs:    None
01079     Returns:    Empty string if none found, else the BaseName (without flags or extension)
01080     Purpose:    Determines the extension of a bitmap
01081     Errors:     -
01082     SeeAlso:    -
01083 
01084 ********************************************************************************************/
01085 
01086 wxString CamResource::GetBitmapBaseName(const wxString &str)
01087 {
01088     // Find the rightmost dot
01089     INT32 i=str.Find(_T('.'), TRUE);
01090     if (i<0)
01091         return wxEmptyString;
01092     wxString barestr = str.Left(i);
01093 
01094     // Find the rightmost "-";
01095     i=barestr.Find(_T('-'), TRUE);
01096     if (i<0)
01097         return barestr;
01098 
01099     // Now check all characters after the "-" are alphanumeric
01100     INT32 j;
01101     for (j=i+1; j<(INT32)barestr.Length(); j++)
01102     {
01103         wxChar c=barestr[j];
01104         if ((c<_T('a')) || (c>_T('z')))
01105             return barestr;
01106     }
01107     return barestr.Left(i);
01108 }
01109 
01110 /********************************************************************************************
01111 
01112 >   static wxString CamResource::GetBitmapFlagString(const wxString &str)
01113 
01114 
01115     Author:     Alex_Bligh <alex@alex.org.uk>
01116     Created:    24/01/2005
01117     Inputs:     str - sting to look at
01118     Outputs:    None
01119     Returns:    Empty string if none found, else the flags string (without the '-')
01120     Purpose:    Determines the extension of a bitmap
01121     Errors:     -
01122     SeeAlso:    -
01123 
01124 ********************************************************************************************/
01125 
01126 wxString CamResource::GetBitmapFlagString(const wxString &str)
01127 {
01128     // Find the rightmost dot
01129     INT32 i=str.Find(_T('.'), TRUE);
01130     if (i<0)
01131         return wxEmptyString;
01132     wxString barestr = str.Left(i);
01133 
01134     // Find the rightmost "-";
01135     i=barestr.Find(_T('-'), TRUE);
01136     if (i<0)
01137         return wxEmptyString;
01138 
01139     // Now check all characters after the "-" are alphanumeric
01140     INT32 j;
01141     for (j=i+1; j<(INT32)barestr.Length(); j++)
01142     {
01143         wxChar c=barestr[j];
01144         if ((c<_T('a')) || (c>_T('z')))
01145             return wxEmptyString;
01146     }
01147     return barestr.Mid(i+1);
01148 }
01149 
01150 
01151 /********************************************************************************************
01152 
01153 >   static void CamResource::MakeVariantBitmaps(ResourceStringToBitmap::iterator * it=NULL)
01154 
01155 
01156     Author:     Alex_Bligh <alex@alex.org.uk>
01157     Created:    01/01/2005
01158     Inputs:     it - iterator
01159     Outputs:    None
01160     Returns:    None
01161     Purpose:    Make variant copies of all bitmaps
01162     Errors:     -
01163     SeeAlso:    -
01164 
01165 If "it" is set, it will look at a single source bitmap, and make variants of that. Else it will walk
01166 the table.
01167 
01168 ********************************************************************************************/
01169 
01170 void CamResource::MakeVariantBitmaps(ResourceStringToBitmap::iterator * it)
01171 {
01172     if (!pBitmapHash)
01173         return;
01174 
01175     // Do this entire lot for each flag
01176     CamArtFlags flag=CAF_CACHE_MAX;
01177     while ((flag=(CamArtFlags)(flag>>1)) !=0 )
01178     {
01179         if ((flag==CAF_GREYED) || (flag==CAF_SELECTED)) // We don't know how to produce anything else, so ignore
01180         {
01181 
01182             // a convenient place to store the new grey bitmaps without breaking the iterator
01183             ResourceStringToBitmap NewHash;
01184             NewHash.clear();
01185         
01186             ResourceStringToBitmap::iterator current;
01187             if (it)
01188                 current=*it;
01189             else
01190                 current = pBitmapHash->begin();
01191     
01192             // iterate through the old hash (if needs be)
01193             while (current != pBitmapHash->end())
01194             {
01195                 if (current->second) // don't bother with bitmaps we have yet to demand load
01196                 {
01197                     wxString fn(current->first);
01198                     //TRACEUSER("amb",_T("Trying to grey bitmap %s"),fn.c_str());
01199         
01200                     // If it's a .png, but without the particular flag set
01201                     if (IsBitmapName(fn) && !(CamArtProvider::GetBitmapFlags(fn) & flag))
01202                     {
01203                         // Find the greyed name of the bitmap
01204                         wxString gfn=MakeBitmapString(GetBitmapBaseName(fn),
01205                                                     CamArtProvider::MakeBitmapFlagString((CamArtFlags)
01206                                                                                         (CamArtProvider::GetBitmapFlags(fn) |
01207                                                                                             flag)),
01208                                                                                             GetBitmapExtension(fn));
01209                         ResourceStringToBitmap::iterator i=pBitmapHash->find(gfn.c_str());
01210                         if (i==pBitmapHash->end())  // ignore if we already have an entry
01211                         {
01212 //                          TRACEUSER("amb",_T("Greying bitmap %s to bitmap %s"),fn.c_str(),gfn.c_str());
01213                             // We want to do this, but it doesn't actually copy the image data (boo hiss)
01214                             // wxImage *pBitmap=new wxImage(*(current->second));
01215                             //wxBitmap b(*(current->second));
01216                             wxImage *pBitmap = new wxImage;
01217                             if (pBitmap)
01218                             {
01219                                 *pBitmap=current->second->Copy();
01220                                 // WX bug - on 2.6.2 this does not copy the alpha channel. Work aroud it
01221                                 if (current->second->HasAlpha() && !pBitmap->HasAlpha())
01222                                 {
01223                                     // This will never happen if wxWidgets is fixed
01224                                     pBitmap->SetAlpha();
01225                                     memcpy( pBitmap->GetAlpha(), current->second->GetAlpha(), pBitmap->GetWidth()*pBitmap->GetHeight());
01226                                 }
01227                                 switch (flag)
01228                                 {
01229                                     case CAF_GREYED:
01230                                         MakeGreyImage(*pBitmap);
01231                                         break;
01232                                     case CAF_SELECTED:
01233                                         MakeHotImage(*pBitmap);
01234                                         break;
01235                                     default:
01236                                         ERROR3("Unsupported automatic variant");
01237                                         break;
01238                                 }
01239                                 NewHash[camStrdup(gfn.c_str())] = pBitmap;
01240                             }
01241                         }   
01242                     }
01243                 }
01244         
01245                 if (it)
01246                 {
01247                     break; // jump out loop
01248                 }
01249                 else
01250                 {
01251                     ++current;
01252                 }
01253             }
01254         
01255             // Now dump the new hash into the old hash
01256             for( current = NewHash.begin(); current != NewHash.end(); ++current )
01257                 (*pBitmapHash)[current->first]=current->second;
01258         }
01259     }
01260 
01261     return;
01262 }
01263 
01264 /********************************************************************************************
01265 
01266 >   static wxImage* CamResource::GetCachedBitmap(const TCHAR * pName)
01267 
01268 
01269     Author:     Alex_Bligh <alex@alex.org.uk>
01270     Created:    01/01/2005
01271     Inputs:     pName - pointer to name of bitmap (leaf name)
01272     Outputs:    None
01273     Returns:    a pointer to the bitmap
01274     Purpose:    Returns a pointer to the preloaded bitmap
01275     Errors:     via wxMessageBox
01276     SeeAlso:    -
01277 
01278 ********************************************************************************************/
01279 
01280 wxImage* CamResource::GetCachedBitmap(const TCHAR * pName)
01281 {
01282     if (!pBitmapHash) return NULL;
01283     ResourceStringToBitmap::iterator i=pBitmapHash->find(pName);
01284     if (i==pBitmapHash->end())
01285     {
01286         // We know this file does not exist in the resources. However, we might be able to
01287         // make one if it's greyed and we can get the ungreyed version
01288 
01289         wxString fn(pName);
01290 
01291         // Clear each of the flags in sequence
01292         BOOL Found=FALSE;
01293         // Do this entire lot for each flag
01294         CamArtFlags flag=CAF_CACHE_MAX;
01295         while ((flag=(CamArtFlags)(flag>>1)) !=0 )
01296         {
01297             if ((flag==CAF_GREYED) || (flag!=CAF_SELECTED)) // We don't know how to produce anything else, so ignore
01298             {
01299 
01300                 if (IsBitmapName(fn) && (CamArtProvider::GetBitmapFlags(fn) & flag))
01301                 {
01302                     // Find the ungreyed name of the bitmap
01303                     wxString ugfn=MakeBitmapString(GetBitmapBaseName(fn),
01304                                                 CamArtProvider::MakeBitmapFlagString((CamArtFlags)
01305                                                                                         (CamArtProvider::GetBitmapFlags(fn) &
01306                                                                                         ~flag)),
01307                                                                                         GetBitmapExtension(fn));
01308                     Found = TRUE; // we should at least look for another bitmap
01309     
01310                     // Recursively call ourself to load the ungreyed bitmap. We don't care about the result, but this
01311                     // will insert the greyed version into the cache as a byproduct
01312     
01313 #ifdef _DEBUG
01314                     static INT32 recursion=0;
01315                     recursion++;
01316                     ERROR3IF(recursion>16,"Too much recursion in CamResource::GetCachedBitmap");
01317 #endif
01318                     GetCachedBitmap(ugfn.c_str());
01319 #ifdef _DEBUG
01320                     recursion--;
01321 #endif
01322                 }
01323             }
01324         }
01325         if (!Found)
01326             return NULL;
01327 
01328         i=pBitmapHash->find(pName); // reset iterator
01329         if (i==pBitmapHash->end())
01330             return NULL; // we couldn't find a greyed version
01331     }
01332 
01333     if (!i->second)
01334     {
01335         // There is no bitmap there, but the name is there. We must be demand loading
01336 
01337         wxImage * pBitmap = new wxImage;
01338         if (!pBitmap) return NULL;
01339 
01340         if (!LoadwxImage(*pBitmap, pName))
01341         {
01342             ERROR3_PF((_T("Could not load bitmap %s"), pName));
01343             delete pBitmap;
01344             return NULL;
01345         }
01346 
01347         // Add it to the cache
01348         i->second=pBitmap;
01349 
01350         // Generate variant versions if we should
01351         MakeVariantBitmaps(&i);
01352 
01353         return pBitmap;
01354     }
01355     return i->second;
01356 }
01357 
01358 
01359 /********************************************************************************************
01360 
01361 >   static BOOL CamResource::LoadBitmaps()
01362 
01363 
01364     Author:     Alex_Bligh <alex@alex.org.uk>
01365     Created:    01/01/2005
01366     Inputs:     None
01367     Outputs:    None
01368     Returns:    TRUE if succeeded, FALSE if fails
01369     Purpose:    Add internal and external bitmaps
01370     Errors:     via wxMessageBox
01371     SeeAlso:    -
01372 
01373 ********************************************************************************************/
01374 
01375 BOOL CamResource::LoadBitmaps()
01376 {
01377     TRACET(_T("LoadBitmaps() called"));
01378     wxString ExternalRes = GetResourceFilePath(wxString(_T("")), TRUE);
01379     wxString InternalRes = GetResourceFilePath(wxString(_T("")), FALSE);
01380     TRACET(_T("LoadBitmaps() adding External bitmaps"));
01381     if (!AddBitmaps(ExternalRes)) return FALSE;
01382     TRACET(_T("LoadBitmaps() adding Internal bitmaps"));
01383     if (InternalRes != ExternalRes)
01384         if (!AddBitmaps(InternalRes)) return FALSE;
01385     TRACET(_T("LoadBitmaps() making grey copies"));
01386     MakeVariantBitmaps(); // make grey copies of each bitmap
01387     TRACET(_T("LoadBitmaps() done"));
01388     return TRUE;
01389 }
01390 
01391 #endif
01392 
01393 /********************************************************************************************
01394 
01395 >   static BOOL CamResource::Init()
01396 
01397 
01398     Author:     Alex_Bligh <alex@alex.org.uk>
01399     Created:    02/12/2005
01400     Inputs:     None
01401     Outputs:    None
01402     Returns:    TRUE if succeeded, FALSE if fails
01403     Purpose:    Initialize resources
01404     Errors:     via wxMessageBox
01405     SeeAlso:    -
01406 
01407 ********************************************************************************************/
01408 
01409 BOOL CamResource::Init()
01410 {
01411     void * pFile=NULL;
01412     UINT32 Length=0;
01413 
01414     TRACET(_T("CamResource::Init() called"));
01415 
01416     pHash = new (ResIDToString);
01417     if (!pHash) return FALSE;
01418     pHash->clear();
01419 
01420     pObjectNameHash = new (ResIDToString);
01421     if (!pObjectNameHash) return FALSE;
01422     pObjectNameHash->clear();
01423 
01424 #if !defined(EXCLUDE_FROM_XARLIB)
01425     pBitmapHash = new (ResourceStringToBitmap);
01426     if (!pBitmapHash) return FALSE;
01427     pBitmapHash->clear();
01428 #endif
01429 
01430     // Now go through ID's translated before we got here
01431     CamResourceRemember * pRem = pFirstRemember;
01432     pFirstRemember = NULL;
01433     while (pRem)
01434     {
01435         if (pRem->text)
01436         {
01437             // Do not comment out the next line. It does something useful (make the inverse object
01438             // map work for static text)
01439             /*ResourceID r =*/ GetResourceID(pRem->text);
01440 //          TRACEUSER("amb",_T("Fixed up static init translation from %s to %d"),pRem->text,r);
01441             free (pRem->text);
01442         }
01443         CamResourceRemember * pORem = pRem;
01444         pRem = pRem->next;
01445         delete pORem;
01446     }
01447 
01448     // Initialize the handlers
01449     wxXmlResource::Get()->InitAllHandlers();
01450 #if !defined(EXCLUDE_FROM_XARLIB)
01451     wxXmlResource::Get()->AddHandler(new wxCamArtControlXmlHandler);
01452     wxXmlResource::Get()->AddHandler(new wxCamDrawControlXmlHandler);
01453 #ifdef wxXTRA_XH_ODCOMBO
01454     wxXmlResource::Get()->AddHandler(new wxOwnerDrawnComboBoxXmlHandler);
01455 //  wxXmlResource::Get()->AddHandler(new wxComboControlXmlHandler);
01456 #endif
01457 #ifdef wxXTRA_XH_SLIDERCOMBO
01458     wxXmlResource::Get()->AddHandler(new wxSliderComboXmlHandler);
01459 #endif
01460 #if WXXTRA_TREEBOOK
01461     wxXmlResource::Get()->AddHandler(new wxTreebookXmlHandler);
01462 #endif
01463     wxXmlResource::Get()->AddHandler(new wxGridComboXmlHandler);
01464 #endif
01465 
01466     if (!pwxFileSystem) pwxFileSystem = new wxFileSystem;
01467     if (!pwxFileSystem)
01468     {
01469         TRACE(_T("Failed to allocate file system"));
01470         return FALSE;
01471     }
01472 
01473     // Check for memory FS. If not present, load the handler:
01474     // No idea for the reason for the additional braces, but let's keep them ther
01475     {
01476         wxMemoryFSHandler::AddFile(_T("XRC_resource/dummy_file"), _T("dummy one"));
01477         wxFSFile *f = pwxFileSystem->OpenFile(_T("memory:XRC_resource/dummy_file"));
01478         wxMemoryFSHandler::RemoveFile(_T("XRC_resource/dummy_file"));
01479         if (f) delete f;
01480         else wxFileSystem::AddHandler(new wxMemoryFSHandler);
01481     }
01482 
01483     TRACET(_T("CamResource::Init() added MemoryFSHandler"));
01484 
01485     wxFileSystem::AddHandler(new wxZipFSHandler);
01486 
01487     TRACET(_T("CamResource::Init() added Zip handler, now doing AddFile() on resources"));
01488 
01489     GetBinaryFileInfo(&pFile, &Length);
01490 
01491     // Do not use a file extension, as unbelievably this adds 3 seconds to startup time pre-splash box
01492     // This is because it tries to initialize the MIME system (sigh)
01493     wxMemoryFSHandler::AddFile(_T("resources"), pFile, Length); // Irritatingly does not return errors
01494 
01495     wxXmlResource::Get()->SetFlags(wxXRC_NO_RELOADING); // reloading fails with assert due to missing timestamps
01496 
01497 #if !defined(EXCLUDE_FROM_XARLIB)
01498     // Add bitmap extenstions
01499     BitmapExtensions.Add(_T("png"));
01500     BitmapExtensions.Add(_T("cur"));
01501 #endif
01502 
01503     // Initialize locale
01504     m_pLocale = new wxLocale();
01505     if (!m_pLocale) return FALSE;
01506     m_pLocale->Init(wxLANGUAGE_DEFAULT, wxLOCALE_LOAD_DEFAULT | wxLOCALE_CONV_ENCODING);
01507     m_pLocale->AddCatalogLookupPathPrefix(GetResourceFilePath(_T("")));
01508     m_pLocale->AddCatalog(_T("XaraLX"));
01509 
01510 #if !defined(EXCLUDE_FROM_XARLIB)
01511     TRACET(_T("CamResource::Init() launching splash screen"));
01512     if (!Splash()) return FALSE;
01513 #endif
01514 
01515 #ifdef XML_STRINGS
01516     TRACET(_T("CamResource::Init() now loading internal resources, calling InitXmlResource"));
01517     // Load the internal resources
01518     // We should offer the possibility of loading them from a non-XML file here
01519     if (!InitXmlResource()) return FALSE;
01520 
01521     wxYield(); // yield again to allow repaint
01522 
01523     TRACET(_T("CamResource::Init() starting to load string table dialog"));
01524 
01525     // Read the string table into the hash map
01526     wxDialog * pStringTable = wxXmlResource::Get()->LoadDialog(NULL, _T("STRINGTABLE"));
01527     if (!pStringTable)
01528     {
01529         // We can hardly internationalize the message box, as we have no strings to play with yet.
01530         wxMessageBox(_T("Could not load resources: Failed to locate string table"), _T("Resource loading error"));
01531         return FALSE;
01532     }   
01533     wxYield(); // yield again to allow repaint
01534 
01535     TRACET(_T("CamResource::Init() starting to process string table"));
01536 
01537     // Now do a depth-first search of this window's children
01538     ProcessWindowAndChildren(pStringTable);
01539 
01540     wxYield(); // yield again to allow repaint
01541 
01542     TRACET(_T("CamResource::Init() and deleting the dialog"));
01543 
01544     delete pStringTable;
01545 #else
01546 
01547     TRACET(_T("CamResource::Init() now loading internal resources, calling ReadStringTableFile()"));
01548     if (!ReadStringTableFile())
01549     {
01550         // We can hardly internationalize the message box, as we have no strings to play with yet.
01551         wxMessageBox(_T("Could not load resources: Failed to locate string table"), _T("Resource loading error"));
01552         return FALSE;
01553     }   
01554 
01555 #endif
01556 
01557     TRACET(_T("CamResource::Init() done processing string table, starting to load bitmaps"));
01558 
01559     wxYield(); // yield again to allow repaint
01560 
01561 #if !defined(EXCLUDE_FROM_XARLIB)
01562     // Note this won't actually load the bitmaps if we are demand loading, but it will at least get a list of them
01563     if (!LoadBitmaps())
01564         return FALSE;
01565 
01566     TRACET(_T("CamResource::Init() done processing bitmaps, starting to load toolbar images"));
01567 
01568     wxYield(); // yield again to allow repaint
01569 
01570 #if 0
01571     LoadwxImage(imageBevelTool, _T("lbeveltool32.png") );
01572     LoadwxImage(imageBezTool, _T("lbeztool32.png") );
01573     LoadwxImage(imageBlendTool, _T("lblendtool32.png") );
01574     LoadwxImage(imageContourTool, _T("lcontourtool32.png") );
01575     LoadwxImage(imageElipTool, _T("leliptool32.png") );
01576     LoadwxImage(imageFHandTool, _T("lfhandtool32.png") );
01577     LoadwxImage(imageGradTool, _T("lgradtool32.png") );
01578     LoadwxImage(imageLiveEffectTool, _T("lliveeffecttool32.png") );
01579     LoadwxImage(imageMouldTool, _T("lmouldtool32.png") );
01580     LoadwxImage(imagePenTool, _T("lpentool32.png") );
01581     LoadwxImage(imagePush, _T("lpushtool32.png") );
01582     LoadwxImage(imageRectTool, _T("lrecttool32.png") );
01583     LoadwxImage(imageRegShapeTool, _T("lregshapetool32.png") );
01584     LoadwxImage(imageSelTool, _T("lselrtool32.png") );
01585     LoadwxImage(imageShadrwTool, _T("lsoftshadowtool32.png") );
01586     LoadwxImage(imageSlicetool, _T("lslicetool32.png") );
01587     LoadwxImage(imageTextTool, _T("ltexttool32.png") );
01588     LoadwxImage(imageTransTool, _T("ltransptool32.png") );
01589     LoadwxImage(imageZoomTool, _T("lzoomtool32.png") );
01590 
01591     TRACET(_T("CamResource::Init() Added images"));
01592 
01593     wxYield(); // yield again to allow repaint
01594 #endif
01595 
01596     m_pHelpProvider = new wxHelpControllerHelpProvider;
01597     if (!m_pHelpProvider)   
01598         return FALSE;
01599     wxHelpProvider::Set(m_pHelpProvider);
01600 
01601     if (!wxXmlResource::Get()->Load(GetResourceFilePath(_T("dialogs.xrc"))))
01602     {
01603         TRACE(_T("Could not load dialogs.xrc"));
01604         return FALSE;
01605     }
01606 
01607     TRACET(_T("CamResource::Init - loaded dialogs"));
01608 
01609     wxYield(); // yield again to allow repaint
01610 #endif
01611 
01612     return TRUE;
01613 }
01614 
01615 
01616 #if !defined(EXCLUDE_FROM_XARLIB)
01617 /********************************************************************************************
01618 
01619 >   static void CamResource::DeleteBitmapHashEntries()
01620 
01621 
01622     Author:     Alex_Bligh <alex@alex.org.uk>
01623     Created:    30/12/2005
01624     Inputs:     -
01625     Outputs:    -
01626     Returns:    -
01627     Purpose:    Delete every bitmap hash table entry
01628     Errors:     -
01629     SeeAlso:    -
01630 
01631 ********************************************************************************************/
01632 
01633 void CamResource::DeleteBitmapHashEntries()
01634 {
01635     if (pBitmapHash)
01636     {
01637         ResourceStringToBitmap::iterator current;
01638 
01639         while (!pBitmapHash->empty())
01640         {
01641             current = pBitmapHash->begin();
01642             wxImage * b=current->second;
01643             TCHAR * s=(TCHAR *)current->first;
01644             pBitmapHash->erase(current);
01645             if (b)
01646                 delete b;
01647             free(s);
01648         }
01649         // for good measure
01650         pBitmapHash->clear();
01651     }
01652 }
01653 #endif  // EXCLUDE_FROM_XARLIB
01654 
01655 
01656 /********************************************************************************************
01657 
01658 >   static BOOL CamResource::DeInit()
01659 
01660 
01661     Author:     Alex_Bligh <alex@alex.org.uk>
01662     Created:    02/12/2005
01663     Inputs:     None
01664     Outputs:    None
01665     Returns:    TRUE if succeeded, FALSE if fails
01666     Purpose:    Initialize resources
01667     Errors:     via wxMessageBox
01668     SeeAlso:    -
01669 
01670 ********************************************************************************************/
01671 
01672 BOOL CamResource::DeInit()
01673 {
01674     if (m_pHelpProvider)
01675     {
01676         wxHelpProvider::Set(NULL);
01677         delete m_pHelpProvider;
01678         m_pHelpProvider = NULL;
01679     }
01680 
01681     if (pwxFileSystem)
01682     {
01683         delete (pwxFileSystem);
01684         pwxFileSystem = NULL;
01685     }
01686 
01687 #if !defined(EXCLUDE_FROM_XARLIB)
01688     if (pBitmapHash)
01689     {
01690         DeleteBitmapHashEntries();
01691         delete pBitmapHash;
01692         pBitmapHash = NULL;
01693     }
01694 #endif  // EXCLUDE_FROM_XARLIB
01695     if (pHash)
01696     {
01697         ResIDToString::iterator current;
01698 
01699         while (!pHash->empty())
01700         {
01701             current = pHash->begin();
01702             ResourceString s=current->second;
01703             pHash->erase(current);
01704             free((void *)s);
01705         }
01706         // for good measure
01707         pHash->clear();
01708         
01709         delete (pHash);
01710         pHash = NULL;
01711     }
01712 
01713     if (pObjectNameHash)
01714     {
01715         ResIDToString::iterator current;
01716 
01717         while (!pObjectNameHash->empty())
01718         {
01719             current = pObjectNameHash->begin();
01720             ResourceString s=current->second;
01721             pObjectNameHash->erase(current);
01722             free((void *)s);
01723         }
01724         // for good measure
01725         pObjectNameHash->clear();
01726         
01727         delete (pObjectNameHash);
01728         pObjectNameHash = NULL;
01729     }
01730 
01731 #if !defined(EXCLUDE_FROM_XARLIB)
01732     if (pSplashScreen)
01733     {
01734         delete (pSplashScreen);
01735         pSplashScreen = NULL;
01736     }
01737 
01738     if (pSplashBitmap)
01739     {
01740         delete (pSplashBitmap);
01741         pSplashBitmap = NULL;
01742     }
01743 #endif  // EXCLUDE_FROM_XARLIB
01744 
01745     if (m_pLocale)
01746     {
01747         delete (m_pLocale);
01748         m_pLocale = NULL;
01749     }
01750 
01751     return TRUE;
01752 }
01753 
01754 
01755 #if !defined(EXCLUDE_FROM_XARLIB)
01756 
01757 /********************************************************************************************
01758 
01759 >   static BOOL CamResource::Splash()
01760 
01761 
01762     Author:     Alex_Bligh <alex@alex.org.uk>
01763     Created:    02/12/2005
01764     Inputs:     None
01765     Outputs:    None
01766     Returns:    TRUE if succeeded, FALSE if fails
01767     Purpose:    Put up a splash screen
01768     Errors:     via wxMessageBox
01769     SeeAlso:    -
01770 
01771 ********************************************************************************************/
01772 
01773 BOOL CamResource::Splash()
01774 {
01775     TRACET(_T("CamResource::Splash() called"));
01776 
01777     if (pSplashBitmap) delete pSplashBitmap;
01778     pSplashBitmap=NULL;
01779 
01780     
01781     pSplashBitmap = new wxBitmap();
01782     if (!pSplashBitmap) return FALSE;
01783 
01784     // We'd like to get the bitmap name from the resources, but, urm, we haven't yet
01785     // loaded them
01786     if (!LoadwxBitmap(*pSplashBitmap, _T("startup-lx.png") ))
01787     {
01788         TRACE(_T("Cannot load splash bitmap - possible resource compilation error?"));
01789         return TRUE;
01790     }
01791 
01792     if (!pSplashBitmap->Ok()) return FALSE;
01793 
01794     pSplashScreen = new wxAdvSplashScreen(*pSplashBitmap,
01795         wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT,
01796         0, NULL, -1, wxDefaultPosition, wxDefaultSize,
01797         wxNO_BORDER
01798 #if 0 && !defined (_DEBUG)
01799         |wxSTAY_ON_TOP // Only stay on top in non-debug builds - too annoying for preinit debugging
01800 #endif
01801           );
01802     if (!pSplashScreen) return FALSE;
01803 
01804     wxYield();
01805 
01806     return TRUE;
01807 }
01808 #endif  // EXCLUDE_FROM_XARLIB
01809 
01810 /********************************************************************************************
01811 
01812 >   static BOOL CamResource::DoneInit(BOOL CanYield=TRUE)
01813 
01814 
01815     Author:     Alex_Bligh <alex@alex.org.uk>
01816     Created:    02/12/2005
01817     Inputs:     None
01818     Outputs:    None
01819     Returns:    TRUE if succeeded, FALSE if fails
01820     Purpose:    Signals to the resouce system initialization is completed. The splah
01821                 screen can thus be removed
01822     Errors:     via wxMessageBox
01823     SeeAlso:    -
01824 
01825 ********************************************************************************************/
01826 
01827 BOOL CamResource::DoneInit(BOOL CanYield /*=TRUE*/)
01828 {
01829     TRACET(_T("CamResource::DoneInit() called"));
01830 #if !defined(EXCLUDE_FROM_XARLIB)
01831     if (pSplashScreen)
01832     {
01833         if (CanYield)
01834             ::wxYield();
01835         pSplashScreen->Destroy();
01836         pSplashScreen = NULL;
01837         if (CanYield)
01838             ::wxYield();
01839     }
01840     if (pSplashBitmap)
01841     {
01842         delete (pSplashBitmap);
01843         pSplashBitmap = NULL;
01844     }
01845 #endif  // EXCLUDE_FROM_XARLIB
01846     return TRUE;
01847 }
01848 
01849 /********************************************************************************************
01850 
01851 >   CamResource::CamResource()
01852 
01853 
01854     Author:     Alex_Bligh <alex@alex.org.uk>
01855     Created:    02/12/2005
01856     Inputs:     -
01857     Outputs:    -
01858     Returns:    -
01859     Purpose:    Constructor
01860     Errors:     -
01861     SeeAlso:    -
01862 
01863 Example of how to use this class:
01864 
01865     CamResource myResource;                             // Allocate a new resource object
01866 
01867     CCLexFile * myFile = myResource.Open(_R(IDB_BLOBBY));   // Open the BLOBBY bitmap
01868                                                         // Could have specified a string
01869                                                         // instead
01870 
01871     myFile->Read( ... )                                 // or whatever
01872 
01873 The user can either close the file, or not. However, operations must NOT be done on the
01874 file once the corresponding resource object is destroyed (as the resource object may have
01875 allocated a memory copy of the image). To prevent damage, the destructor will ALWAYS
01876 close the file and free the resources.
01877 
01878 The caller should NOT delete the open CCLexFile object that is returned. Either use
01879 our Close mechanism, or let the destructor take its course.
01880 
01881 ********************************************************************************************/
01882 
01883 CamResource::CamResource()
01884 {
01885     Size = 0;
01886     pMemory = NULL;
01887     pFile = NULL;
01888     pwxFSFile = NULL;
01889     return;
01890 }
01891 
01892 
01893 /********************************************************************************************
01894 
01895 >   CamResource::~CamResource()
01896 
01897 
01898     Author:     Alex_Bligh <alex@alex.org.uk>
01899     Created:    02/12/2005
01900     Inputs:     -
01901     Outputs:    -
01902     Returns:    -
01903     Purpose:    Destructor
01904     Errors:     -
01905     SeeAlso:    -
01906 
01907 ********************************************************************************************/
01908 
01909 CamResource::~CamResource()
01910 {
01911     Close(); // releases pFile and pMemory
01912 }
01913 
01914 /********************************************************************************************
01915 
01916 >   void CamResource::Close()
01917 
01918 
01919     Author:     Alex_Bligh <alex@alex.org.uk>
01920     Created:    02/12/2005
01921     Inputs:     -
01922     Outputs:    -
01923     Returns:    -
01924     Purpose:    Close the relevant file
01925     Errors:     -
01926     SeeAlso:    -
01927 
01928 ********************************************************************************************/
01929 
01930 void CamResource::Close()
01931 {
01932     if (pFile)
01933     {
01934         pFile->close();
01935         delete (pFile);
01936         pFile = NULL;
01937     }
01938 
01939     if (pwxFSFile)
01940     {
01941         delete (pwxFSFile);
01942         pwxFSFile=NULL;
01943     }
01944 
01945     if (pMemory) free(pMemory);
01946     pMemory = NULL;
01947 
01948     Size = 0; // leave in tidy state
01949 }
01950 
01951 /********************************************************************************************
01952 
01953 >   CCLexFile * CamResource::Open( const TCHAR * pFileName, BOOL ErrorReporting=TRUE, BOOL ExceptionThrowing=FALSE)
01954 
01955 
01956     Author:     Alex_Bligh <alex@alex.org.uk>
01957     Created:    02/12/2005
01958     Inputs:     pFileName - **LEAF** element of filename - e.g. "deffill.bmp"
01959     Outputs:    -
01960     Returns:    Pointer to the open file, or NULL for a failure
01961     Purpose:    Return a pointer to the open file
01962     Errors:     -
01963     SeeAlso:    -
01964 
01965 ********************************************************************************************/
01966 
01967 CCLexFile * CamResource::Open( const TCHAR * pFileName, BOOL ErrorReporting, BOOL ExceptionThrowing)
01968 {
01969     Close();
01970 
01971     // For the time being, we always use a memory file. We load the resource in using the
01972     // wxWidgets VFS code (allowing us to load it out the Zip file), and keep the memory
01973     // around till we need to zap it.
01974 
01975     wxFSFile * pTwxFSFile = pwxFileSystem->OpenFile(GetResourceFilePath(pFileName));
01976     if (!pTwxFSFile)
01977     {
01978         return NULL;
01979     }
01980 
01981     wxInputStream * pStream = pTwxFSFile->GetStream(); // we don't have to delete this ourselves
01982     if (!pStream)
01983     {
01984         delete (pTwxFSFile);
01985         return NULL;
01986     }
01987 
01988     UINT32 newsize=pStream->GetSize();
01989 
01990     if (!newsize)
01991     {
01992         delete (pTwxFSFile);
01993         return NULL;
01994     }
01995 
01996     void * newmem = malloc(newsize+4); // safety
01997     if (!newmem)
01998     {
01999         delete (pTwxFSFile);
02000         return NULL;
02001     }
02002 
02003     memset(newmem, 0, newsize);
02004     pStream->Read(newmem, newsize); // throws exceptions if can't read
02005     
02006     delete (pTwxFSFile);    // which closes it
02007 
02008     CCMemFile * pMemFile=new CCMemFile (newmem, newsize, CCMemRead, ErrorReporting, ExceptionThrowing);
02009     if (!pMemFile)
02010     {
02011         free(newmem);
02012         return NULL;
02013     }
02014 
02015     // OK, we've done it. So we can store the variables we have
02016     pFile = pMemFile;
02017     Size = newsize;
02018     pMemory = newmem;
02019 
02020     return (pFile);
02021 }
02022 
02023 
02024 /********************************************************************************************
02025 
02026 >   CCLexFile * CamResource::Open( ResourceID ID, BOOL ErrorReporting=TRUE, BOOL ExceptionThrowing=FALSE);
02027 
02028 
02029     Author:     Alex_Bligh <alex@alex.org.uk>
02030     Created:    02/12/2005
02031     Inputs:     ResourceID of the file in question
02032     Outputs:    -
02033     Returns:    Pointer to the open file, or NULL for a failure
02034     Purpose:    Return a pointer to the open file
02035     Errors:     -
02036     SeeAlso:    -
02037 
02038 ********************************************************************************************/
02039 
02040 CCLexFile * CamResource::Open( ResourceID ID, BOOL ErrorReporting, BOOL ExceptionThrowing)
02041 {
02042     return Open(GetText(ID), (BOOL) ErrorReporting, (BOOL) ExceptionThrowing);
02043 }
02044 
02045 /********************************************************************************************
02046 
02047 >   wxFSFile * CamResource::OpenwxFSFile( ResourceID ID);
02048 
02049 
02050     Author:     Alex_Bligh <alex@alex.org.uk>
02051     Created:    02/12/2005
02052     Inputs:     ResourceID of the file in question
02053     Outputs:    -
02054     Returns:    Pointer to the open file stream, or NULL for a failure
02055     Purpose:    Return a pointer to the open file
02056     Errors:     -
02057     SeeAlso:    -
02058 
02059 ********************************************************************************************/
02060 
02061 wxFSFile * CamResource::OpenwxFSFile( ResourceID ID )
02062 {
02063     return OpenwxFSFile(GetText(ID));
02064 }
02065 
02066 /********************************************************************************************
02067 
02068 >   wxFSFile * CamResource::OpenwxFSFile( const TCHAR * pFileName );
02069 
02070 
02071     Author:     Alex_Bligh <alex@alex.org.uk>
02072     Created:    02/12/2005
02073     Inputs:     pFileName - pointer to the LEAF filename
02074     Outputs:    -
02075     Returns:    Pointer to the open file stream, or NULL for a failure
02076     Purpose:    Return a pointer to the open file
02077     Errors:     -
02078     SeeAlso:    -
02079 
02080 ********************************************************************************************/
02081 
02082 wxFSFile * CamResource::OpenwxFSFile( const TCHAR * pFileName )
02083 {
02084     wxFSFile * pTwxFSFile = pwxFileSystem->OpenFile(GetResourceFilePath(pFileName));
02085     if (!pTwxFSFile)
02086     {
02087         return NULL;
02088     }
02089 
02090     pwxFSFile=pTwxFSFile;
02091 
02092     return pwxFSFile;
02093 }
02094 
02095 
02096 #if !defined(EXCLUDE_FROM_XARLIB)
02097 
02098 /********************************************************************************************
02099 
02100 >   static void CamResource::MakeGreyImage (wxImage & rImage)
02101 
02102     Author:     Alex_Bligh <alex@alex.org.uk>
02103     Created:    02/12/2005
02104     Inputs:     Image - Image to make grey
02105     Outputs:    
02106     Returns:    -
02107     Purpose:    Static function to grey an image
02108     Errors:     -
02109     SeeAlso:    -
02110 
02111 ********************************************************************************************/
02112 void CamResource::MakeGreyImage (wxImage & rImage)
02113 {
02114     // now we want to grey the thing ourselves
02115     INT32 x;
02116     INT32 y;
02117 
02118     BOOL hasalpha = rImage.HasAlpha();
02119 
02120     // give it an alpha channel
02121     if (!hasalpha) rImage.InitAlpha(); // copies alpha into the mask if it had one.
02122     rImage.SetMask(FALSE); // ignore the mask - we now have alpha
02123 
02124     UINT8 * p = rImage.GetData();
02125     UINT8 * alpha = rImage.GetAlpha();
02126     
02127     INT32 w=rImage.GetWidth();
02128     INT32 h=rImage.GetHeight();
02129 
02130     ColourMatrix Whiten = ColourMatrix::Whiten();
02131     ColourMatrix Grey   = ColourMatrix::Grey();
02132 
02133     // If we do the copy backwards we can avoid copying the data
02134     // Start off pointing at the last pixel
02135     const INT32 size = w * h;
02136     INT32 m = size - 1;
02137     INT32 n = (size - 1) * 3;
02138 
02139     // Don't use SetRGB - it does funny things to the alpha channel
02140     for (y = h-1; y>=0; y--) for (x = w-1 ; x>=0; x--)
02141     {
02142         // packed bytes, same order on each platform
02143         ColourVector togrey;
02144         togrey.SetRGBA (p[n], p[n+1], p[n+2], alpha[m]);
02145 
02146         togrey=togrey.Apply(Grey);
02147 
02148         ColourVector towhiten(0.0,0.0,0.0,0.0); // transparent
02149         // whitened image is displaced by one pixel down and right. So we sample
02150         // from a pixel left and up (this is width + 1 pixels earlier in the image)
02151         if ((y>0) && (x>0))
02152         {
02153             towhiten.SetRGBA(p[n-(w+1)*3],
02154                              p[n-(w+1)*3+1],
02155                              p[n-(w+1)*3+2],
02156                              alpha[m-(w+1)]);
02157         }
02158 
02159         towhiten=towhiten.Apply(Whiten);
02160         ColourVector result = towhiten.ComposeOnTop(togrey);
02161 
02162         // Write the colour back into the image
02163         p[n]=result.GetR();
02164         p[n+1]=result.GetG();
02165         p[n+2]=result.GetB();
02166         alpha[m]=result.GetA();
02167 
02168         // Go to "next" pixel (going backwards)
02169         n-=3;
02170         m--;
02171     }
02172 }
02173 
02174 /********************************************************************************************
02175 
02176 >   static void CamResource::MakeHotImage (wxImage & rImage)
02177 
02178     Author:     Alex_Bligh <alex@alex.org.uk>
02179     Created:    02/12/2005
02180     Inputs:     Image - Image to make hot
02181     Outputs:    
02182     Returns:    -
02183     Purpose:    Static function to make a hot version of an image
02184     Errors:     -
02185     SeeAlso:    -
02186 
02187 ********************************************************************************************/
02188 void CamResource::MakeHotImage (wxImage & rImage)
02189 {
02190     // now we want to grey the thing ourselves
02191     INT32 x;
02192     INT32 y;
02193     INT32 n=0;
02194     INT32 m=0;
02195 
02196     BOOL hasalpha = rImage.HasAlpha();
02197 
02198     // give it an alpha channel
02199     if (!hasalpha) rImage.InitAlpha(); // copies alpha into the mask if it had one.
02200     rImage.SetMask(FALSE); // ignore the mask - we now have alpha
02201 
02202     UINT8 * p = rImage.GetData();
02203     UINT8 * alpha = rImage.GetAlpha();
02204     
02205     INT32 w=rImage.GetWidth();
02206     INT32 h=rImage.GetHeight();
02207 
02208     ColourMatrix Boost = ColourMatrix::Boost();
02209 
02210     // Don't use SetRGB - it does funny things to the alpha channel
02211     for (y = 0; y<h; y++) for (x = 0 ; x<w; x++)
02212     {
02213         // packed bytes, same order on each platform
02214         ColourVector result;
02215         result.SetRGBA (p[n], p[n+1], p[n+2], alpha[m]);
02216 
02217         result=result.Apply(Boost);
02218 
02219         p[n]=result.GetR();
02220         p[n+1]=result.GetG();
02221         p[n+2]=result.GetB();
02222         alpha[m]=result.GetA();
02223 
02224         n+=3;
02225         m++;
02226     }
02227 
02228 }
02229 
02230 /********************************************************************************************
02231 
02232 >   static BOOL CamResource::LoadwxImage (wxImage & rImage, const TCHAR * pFileName, BOOL Grey=FALSE)
02233 
02234     Author:     Alex_Bligh <alex@alex.org.uk>
02235     Created:    02/12/2005
02236     Inputs:     Image - Image to alter. pFileName - pointer to the LEAF filename
02237                 Grey - to grey the image
02238     Outputs:    
02239     Returns:    Success or otherwise
02240     Purpose:    Static function to load a bitmap
02241     Errors:     -
02242     SeeAlso:    -
02243 
02244 ********************************************************************************************/
02245 
02246 BOOL CamResource::LoadwxImage (wxImage & rImage, const TCHAR * pFileName, BOOL Grey)
02247 {
02248     CamResource Resource;
02249     wxFSFile* f=Resource.OpenwxFSFile(pFileName);
02250     if (!f) return FALSE;
02251     wxInputStream * pStream=f->GetStream();
02252     if (!pStream) return FALSE;
02253     if (!rImage.LoadFile(*pStream, wxBITMAP_TYPE_ANY)) return FALSE;
02254 
02255     // Grey the image if required
02256     if (Grey) MakeGreyImage(rImage);
02257 
02258     return TRUE;
02259 }
02260 
02261 /********************************************************************************************
02262 
02263 >   static BOOL CamResource::LoadwxBitmap (wxBitmap & rBitmap, const TCHAR * pFileName, BOOL Grey=FALSE)
02264 
02265     Author:     Alex_Bligh <alex@alex.org.uk>
02266     Created:    02/12/2005
02267     Inputs:     Image - Image to alter. pFileName - pointer to the LEAF filename
02268                 Grey - to Grey the image
02269     Outputs:    
02270     Returns:    Success or otherwise
02271     Purpose:    Static function to load a bitmap
02272     Errors:     -
02273     SeeAlso:    -
02274 
02275 ********************************************************************************************/
02276 
02277 BOOL CamResource::LoadwxBitmap (wxBitmap & rBitmap, const TCHAR * pFileName, BOOL Grey)
02278 {
02279     // Annoyingly, wxBitmap does not support the stream class
02280     wxImage i;
02281     if (!LoadwxImage(i, pFileName)) return FALSE;
02282     wxBitmap b(i, -1); // for now, always use screen depth, not least as GDK doesn't support anything except this & 1bpp
02283     rBitmap = b;
02284     return TRUE;
02285 }
02286 
02287 #endif  // EXCLUDE_FROM_XARLIB
02288 
02289 
02290 #if 0
02291     // OLD CODE FROM CAMELOT.CPP
02292 
02293     m_strResourcePath = CamResource::GetResourcePath();
02294     // Load strings into our string table
02295     // InitStringTable();
02296 
02297 
02298     // Calculate the absolute path to resources
02299     m_strResourcePath = argv[0];
02300 #if defined(__WXMSW__)
02301     m_strResourcePath = m_strResourcePath.BeforeLast( _T('\\') ) + _T("\\Resources\\");
02302 #else
02303     if( -1 == m_strResourcePath.Find('/') )
02304         m_strResourcePath = _T("./Resources/");
02305     else
02306         m_strResourcePath = m_strResourcePath.BeforeLast( _T('/') ) + _T("/Resources/");
02307     {
02308         wxString    strRes( m_strResourcePath + _T("deffill.bmp") );
02309         
02310 #if 0 == wxUSE_UNICODE
02311         FILE *fpResFile = _tfopen( (const TCHAR *)strRes.c_str(), "rb");
02312 #else
02313         // GNU\Linux seems to have no unicode filesystem name support, so we
02314         // just get on and do the needed conversion as efficiently as possible
02315         size_t              cchTmp = camWcstombs( NULL, strRes.c_str(), 0 ) + 1;
02316         PSTR                pszTmp = PSTR( alloca( cchTmp ) );
02317         camWcstombs( pszTmp, strRes.c_str(), cchTmp );
02318     
02319         FILE *fpResFile = fopen( pszTmp, "rb" );
02320 #endif
02321 
02322         if( NULL == fpResFile )
02323         {
02324             wxMessageBox( _T("In order for the  toolbar resources to be locatable "
02325                 "you must either run the XaraLX executable from the current directory or "
02326                 "specify the entire path to it."), _T("Resource loading error") );
02327             
02328             return FALSE;
02329         }
02330         
02331         fclose( fpResFile );
02332     }
02333 #endif
02334 
02335 #endif

Generated on Sat Nov 10 03:48:10 2007 for Camelot by  doxygen 1.4.4