/* AbiHello * Copyright (C) 1999 AbiSource, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include #include "ut_assert.h" #include "ut_debugmsg.h" #include "ut_string.h" #include "ap_Strings.h" ////////////////////////////////////////////////////////////////// // a sub-class to wrap the compiled-in (english) strings // (there will only be one instance of this sub-class) ////////////////////////////////////////////////////////////////// AP_BuiltinStringSet::AP_BuiltinStringSet(XAP_App * pApp, const XML_Char * szLanguageName) : XAP_BuiltinStringSet(pApp,szLanguageName) { #define dcl(id,s) s, static const XML_Char * s_a[] = { dcl(__FIRST__,0) // bogus entry for zero #include "ap_String_Id.h" dcl(__LAST__,0) // bogus entry for end }; m_arrayAP = s_a; #undef dcl } AP_BuiltinStringSet::~AP_BuiltinStringSet(void) { } const XML_Char * AP_BuiltinStringSet::getValue(XAP_String_Id id) const { // if it's in our range, we fetch it. // otherwise, we hand it down to the base class. if ( (id > AP_STRING_ID__FIRST__) && (id < AP_STRING_ID__LAST__) ) return m_arrayAP[id-AP_STRING_ID__FIRST__]; return XAP_BuiltinStringSet::getValue(id); } #ifdef DEBUG bool AP_BuiltinStringSet::dumpBuiltinSet(const char * szFilename) const { // Dump a full set of english strings. The resulting file // can then be translated and later loaded as a DiskStringSet // for the other language. bool bResult = false; // assume failure FILE * fp = NULL; fp = fopen(szFilename, "w"); if (!fp) { UT_DEBUGMSG(("Could not open String file [%s].\n",szFilename)); return false; } UT_DEBUGMSG(("Dumping English strings into String file [%s].\n",szFilename)); // write a comment block as a prolog. // NOTE: this is human readable information only. fprintf(fp,"\n"); fprintf(fp,"\n"); fprintf(fp,"\n"); fprintf(fp,"\n"); fprintf(fp,"\n"); fprintf(fp,"\n"); fprintf(fp,"\n"); // end of prolog. // now we begin the actual document. ////////////////////////////////////////////////////////////////// // declare a static table of all the ids and strings ////////////////////////////////////////////////////////////////// #define dcl(id,s) { #id,s }, static struct { const XML_Char * szId; const XML_Char * szString; } s_mapXAP[] = { #include "xap_String_Id.h" }; static struct { const XML_Char * szId; const XML_Char * szString; } s_mapAP[] = { #include "ap_String_Id.h" }; #undef dcl fprintf(fp,"\n\n", m_pApp->getApplicationName(), "1.0", getLanguageName()); { UT_uint32 k; fprintf(fp,"\n\n"); fprintf(fp,"\n\n"); } fprintf(fp,"\n\n"); if (fp) fclose(fp); return bResult; } #endif // DEBUG ////////////////////////////////////////////////////////////////// // a sub-class to deal with disk-based string sets (translations) // (a unique one of these will be instantiated for each language // that we load -- or rather one for each time the user switches // languages and we load another one from disk) ////////////////////////////////////////////////////////////////// AP_DiskStringSet::AP_DiskStringSet(XAP_App * pApp) : XAP_DiskStringSet(pApp) { setValue(AP_STRING_ID__FIRST__,0); // bogus zero element } AP_DiskStringSet::~AP_DiskStringSet(void) { UT_sint32 kLimit = (UT_sint32)m_vecStringsAP.getItemCount(); UT_sint32 k; for (k=kLimit-1; k>=0; k--) { XML_Char * sz = (XML_Char *)m_vecStringsAP.getNthItem(k); if (sz) free(sz); } } bool AP_DiskStringSet::setValue(XAP_String_Id id, const XML_Char * szString) { if (id < AP_STRING_ID__FIRST__) return XAP_DiskStringSet::setValue(id,szString); XML_Char * szDup = NULL; if (szString && *szString) if (!UT_XML_cloneString(szDup,szString)) return false; void * pOldValue = NULL; bool bResult = (m_vecStringsAP.setNthItem(id-AP_STRING_ID__FIRST__,szDup,&pOldValue) == 0); UT_ASSERT(pOldValue == NULL); // duplicate string for this id return bResult; } const XML_Char * AP_DiskStringSet::getValue(XAP_String_Id id) const { // dispatch to XAP code if not in our range if (id < AP_STRING_ID__FIRST__) return XAP_DiskStringSet::getValue(id); // if it is in our range, look it up in our table UT_uint32 kLimit = m_vecStringsAP.getItemCount(); if (id-AP_STRING_ID__FIRST__ < kLimit) { const XML_Char * szValue = (const XML_Char *) m_vecStringsAP.getNthItem(id-AP_STRING_ID__FIRST__); if (szValue) return szValue; } // if no entry in our table for this string, fallback to the builtin value (if provided). if (m_pFallbackStringSet) return m_pFallbackStringSet->getValue(id); return NULL; } ////////////////////////////////////////////////////////////////// // build a static table to map id by names into numbers ////////////////////////////////////////////////////////////////// #define dcl(id,s) { #id, AP_STRING_ID_##id }, static struct { const XML_Char * szName; XAP_String_Id id; } s_map[] = { #include "ap_String_Id.h" }; #undef dcl ////////////////////////////////////////////////////////////////// bool AP_DiskStringSet::setValue(const XML_Char * szId, const XML_Char * szString) { if (!szId || !*szId || !szString || !*szString) return true; UT_uint32 kLimit = NrElements(s_map); UT_uint32 k; // we use predefined IDs to access the strings, so there is no need to do // case-insensitive comparison (and it is costing us lot of time, particularly on // startup). for (k=0; k