MythTV  0.26-pre
BaseClasses.cpp
Go to the documentation of this file.
00001 /* BaseClasses.cpp
00002 
00003    Copyright (C)  David C. J. Matthews 2004  dm at prolingua.co.uk
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU General Public License
00007    as published by the Free Software Foundation; either version 2
00008    of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018    Or, point your browser to http://www.gnu.org/copyleft/gpl.html
00019 
00020 */
00021 
00022 #include "BaseClasses.h"
00023 #include "ParseNode.h"
00024 #include "Engine.h"
00025 #include "ASN1Codes.h"
00026 #include "Logging.h"
00027 
00028 #ifdef _DEBUG
00029 #undef THIS_FILE
00030 static char THIS_FILE[] = __FILE__;
00031 #define new DEBUG_NEW
00032 #endif
00033 
00034 MHOctetString::MHOctetString()
00035 {
00036     m_nLength = 0;
00037     m_pChars = NULL;
00038 }
00039 
00040 // Construct from a string
00041 MHOctetString::MHOctetString(const char *str, int nLen)
00042 {
00043     if (nLen < 0)
00044     {
00045         nLen = strlen(str);
00046     }
00047 
00048     m_nLength = nLen;
00049 
00050     if (nLen == 0)
00051     {
00052         m_pChars = 0;
00053     }
00054     else
00055     {
00056         m_pChars = (unsigned char *)malloc(nLen);
00057 
00058         if (! m_pChars)
00059         {
00060             throw "Out of memory";
00061         }
00062 
00063         memcpy(m_pChars, str, nLen);
00064     }
00065 }
00066 
00067 MHOctetString::MHOctetString(const unsigned char *str, int nLen)
00068 {
00069     m_nLength = nLen;
00070 
00071     if (nLen == 0)
00072     {
00073         m_pChars = 0;
00074     }
00075     else
00076     {
00077         m_pChars = (unsigned char *)malloc(nLen);
00078 
00079         if (! m_pChars)
00080         {
00081             throw "Out of memory";
00082         }
00083 
00084         memcpy(m_pChars, str, nLen);
00085     }
00086 }
00087 
00088 // Construct a substring.
00089 MHOctetString::MHOctetString(const MHOctetString &str, int nOffset, int nLen)
00090 {
00091     if (nLen < 0)
00092     {
00093         nLen = str.Size() - nOffset;    // The rest of the string.
00094     }
00095 
00096     if (nLen < 0)
00097     {
00098         nLen = 0;
00099     }
00100 
00101     if (nLen > str.Size())
00102     {
00103         nLen = str.Size();
00104     }
00105 
00106     m_nLength = nLen;
00107 
00108     if (nLen == 0)
00109     {
00110         m_pChars = 0;
00111     }
00112     else
00113     {
00114         m_pChars = (unsigned char *)malloc(nLen);
00115 
00116         if (! m_pChars)
00117         {
00118             throw "Out of memory";
00119         }
00120 
00121         memcpy(m_pChars, str.m_pChars + nOffset, nLen);
00122     }
00123 }
00124 
00125 MHOctetString::~MHOctetString()
00126 {
00127     free(m_pChars);
00128 }
00129 
00130 // Copy a string
00131 void MHOctetString::Copy(const MHOctetString &str)
00132 {
00133     free(m_pChars);
00134     m_pChars = NULL;
00135     m_nLength = str.m_nLength;
00136 
00137     if (str.m_pChars)
00138     {
00139         // Allocate a copy of the string.  For simplicity we always add a null.
00140         m_pChars = (unsigned char *)malloc(m_nLength + 1);
00141 
00142         if (m_pChars == NULL)
00143         {
00144             throw "Out of memory";
00145         }
00146 
00147         memcpy(m_pChars, str.m_pChars, m_nLength);
00148         m_pChars[m_nLength] = 0;
00149     }
00150 }
00151 
00152 // Print the string in a suitable format.
00153 // For the moment it uses quoted printable.
00154 void MHOctetString::PrintMe(FILE *fd, int /*nTabs*/) const
00155 {
00156     putc('\'', fd);
00157 
00158     for (int i = 0; i < m_nLength; i++)
00159     {
00160         unsigned char ch = m_pChars[i];
00161 
00162         // Escape a non-printable character or an equal sign or a quote.
00163         if (ch == '=' || ch == '\'' || ch < ' ' || ch >= 127)
00164         {
00165             fprintf(fd, "=%02X", ch);
00166         }
00167         else
00168         {
00169             putc(ch, fd);
00170         }
00171     }
00172 
00173     putc('\'', fd);
00174 }
00175 
00176 // Test strings.
00177 int MHOctetString::Compare(const MHOctetString &str) const
00178 {
00179     int nLength = m_nLength;
00180 
00181     if (nLength > str.m_nLength)
00182     {
00183         nLength = str.m_nLength;
00184     }
00185 
00186     // Test up to the length of the shorter string.
00187     int nTest = 0;
00188 
00189     if (nLength > 0)
00190     {
00191         nTest = memcmp(str.m_pChars, m_pChars, nLength);
00192     }
00193 
00194     // If they differ return the result
00195     if (nTest != 0)
00196     {
00197         return nTest;
00198     }
00199 
00200     // If they are the same then the longer string is greater.
00201     if (m_nLength == str.m_nLength)
00202     {
00203         return 0;
00204     }
00205     else if (m_nLength < str.m_nLength)
00206     {
00207         return -1;
00208     }
00209     else
00210     {
00211         return 1;
00212     }
00213 }
00214 
00215 // Add text to the end of the string.
00216 void MHOctetString::Append(const MHOctetString &str)
00217 {
00218     if (str.m_nLength == 0)
00219     {
00220         return;    // Nothing to do and it simplifies the code
00221     }
00222 
00223     int newLen = m_nLength + str.m_nLength;
00224     // Allocate a new string big enough to contain both and initialised to the first string.
00225     unsigned char *p = (unsigned char *)realloc(m_pChars, newLen);
00226 
00227     if (p == NULL)
00228     {
00229         throw "Out of memory";
00230     }
00231 
00232     m_pChars = p;
00233     // Copy the second string onto the end of the first.
00234     memcpy(m_pChars + m_nLength, str.m_pChars, str.m_nLength);
00235     m_nLength = newLen;
00236 }
00237 
00238 // Colour
00239 void MHColour::Initialise(MHParseNode *p, MHEngine * /*engine*/)
00240 {
00241     if (p->m_nNodeType == MHParseNode::PNInt)
00242     {
00243         m_nColIndex = p->GetIntValue();
00244     }
00245     else
00246     {
00247         p->GetStringValue(m_ColStr);
00248     }
00249 }
00250 
00251 void MHColour::PrintMe(FILE *fd, int nTabs) const
00252 {
00253     if (m_nColIndex >= 0)
00254     {
00255         fprintf(fd, " %d ", m_nColIndex);
00256     }
00257     else
00258     {
00259         m_ColStr.PrintMe(fd, nTabs);
00260     }
00261 }
00262 
00263 void MHColour::SetFromString(const char *str, int nLen)
00264 {
00265     m_nColIndex = -1;
00266     m_ColStr.Copy(MHOctetString(str, nLen));
00267 }
00268 
00269 void MHColour::Copy(const MHColour &col)
00270 {
00271     m_nColIndex = col.m_nColIndex;
00272     m_ColStr.Copy(col.m_ColStr);
00273 }
00274 
00275 // An object reference is used to identify and refer to an object.
00276 // Internal objects have the m_GroupId field empty.
00277 
00278 MHObjectRef MHObjectRef::Null; // This has zero for the object number and an empty group id.
00279 
00280 // An object reference is either an integer or a pair of a group id and an integer.
00281 void MHObjectRef::Initialise(MHParseNode *p, MHEngine *engine)
00282 {
00283     if (p->m_nNodeType == MHParseNode::PNInt)
00284     {
00285         m_nObjectNo = p->GetIntValue();
00286         // Set the group id to the id of this group.
00287         m_GroupId.Copy(engine->GetGroupId());
00288     }
00289     else if (p->m_nNodeType == MHParseNode::PNSeq)
00290     {
00291         MHParseNode *pFirst = p->GetSeqN(0);
00292         MHOctetString groupId;
00293         pFirst->GetStringValue(m_GroupId);
00294         m_nObjectNo = p->GetSeqN(1)->GetIntValue();
00295     }
00296     else
00297     {
00298         p->Failure("ObjectRef: Argument is not int or sequence");
00299     }
00300 }
00301 
00302 void MHObjectRef::PrintMe(FILE *fd, int nTabs) const
00303 {
00304     if (m_GroupId.Size() == 0)
00305     {
00306         fprintf(fd, " %d ", m_nObjectNo);
00307     }
00308     else
00309     {
00310         fprintf(fd, " ( ");
00311         m_GroupId.PrintMe(fd, nTabs);
00312         fprintf(fd, " %d ) ", m_nObjectNo);
00313     }
00314 }
00315 
00316 QString MHObjectRef::Printable() const
00317 {
00318     if (m_GroupId.Size() == 0)
00319     {
00320         return QString(" %1 ").arg(m_nObjectNo);
00321     }
00322     else
00323     {
00324         return QString(" ( ") + m_GroupId.Printable() + QString(" %1 ").arg(m_nObjectNo);
00325     }
00326 }
00327 
00328 // Make a copy of an object reference.
00329 void MHObjectRef::Copy(const MHObjectRef &objr)
00330 {
00331     m_nObjectNo = objr.m_nObjectNo;
00332     m_GroupId.Copy(objr.m_GroupId);
00333 }
00334 
00335 // The object references may not be identical but may nevertheless refer to the same
00336 // object.  The only safe way to do this is to compare the canonical paths.
00337 bool MHObjectRef::Equal(const MHObjectRef &objr, MHEngine *engine) const
00338 {
00339     return m_nObjectNo == objr.m_nObjectNo && engine->GetPathName(m_GroupId) == engine->GetPathName(objr.m_GroupId);
00340 }
00341 
00342 bool MHContentRef::Equal(const MHContentRef &cr, MHEngine *engine) const
00343 {
00344     return engine->GetPathName(m_ContentRef) == engine->GetPathName(cr.m_ContentRef);
00345 }
00346 
00347 // "Generic" versions of int, bool etc can be either the value or the an indirect reference.
00348 
00349 void MHGenericBoolean::Initialise(MHParseNode *pArg, MHEngine *engine)
00350 {
00351     if (pArg->m_nNodeType == MHParseNode::PNTagged && pArg->GetTagNo() == C_INDIRECTREFERENCE)
00352     {
00353         // Indirect reference.
00354         m_fIsDirect = false;
00355         m_Indirect.Initialise(pArg->GetArgN(0), engine);
00356     }
00357     else   // Simple integer value.
00358     {
00359         m_fIsDirect = true;
00360         m_fDirect = pArg->GetBoolValue();
00361     }
00362 }
00363 
00364 void MHGenericBoolean::PrintMe(FILE *fd, int nTabs) const
00365 {
00366     if (m_fIsDirect)
00367     {
00368         fprintf(fd, "%s ", m_fDirect ? "true" : "false");
00369     }
00370     else
00371     {
00372         fprintf(fd, ":IndirectRef ");
00373         m_Indirect.PrintMe(fd, nTabs + 1);
00374     }
00375 }
00376 
00377 // Return the value, looking up any indirect ref.
00378 bool MHGenericBoolean::GetValue(MHEngine *engine) const
00379 {
00380     if (m_fIsDirect)
00381     {
00382         return m_fDirect;
00383     }
00384     else
00385     {
00386         MHUnion result;
00387         MHRoot *pBase = engine->FindObject(m_Indirect);
00388         pBase->GetVariableValue(result, engine);
00389         result.CheckType(MHUnion::U_Bool);
00390         return result.m_fBoolVal;
00391     }
00392 }
00393 
00394 // Return the indirect reference or fail if it's direct
00395 MHObjectRef *MHGenericBase::GetReference()
00396 {
00397     if (m_fIsDirect)
00398     {
00399         MHERROR("Expected indirect reference");
00400     }
00401 
00402     return &m_Indirect;
00403 }
00404 
00405 void MHGenericInteger::Initialise(MHParseNode *pArg, MHEngine *engine)
00406 {
00407     if (pArg->m_nNodeType == MHParseNode::PNTagged && pArg->GetTagNo() == C_INDIRECTREFERENCE)
00408     {
00409         // Indirect reference.
00410         m_fIsDirect = false;
00411         m_Indirect.Initialise(pArg->GetArgN(0), engine);
00412     }
00413     else   // Simple integer value.
00414     {
00415         m_fIsDirect = true;
00416         m_nDirect = pArg->GetIntValue();
00417     }
00418 }
00419 
00420 void MHGenericInteger::PrintMe(FILE *fd, int nTabs) const
00421 {
00422     if (m_fIsDirect)
00423     {
00424         fprintf(fd, "%d ", m_nDirect);
00425     }
00426     else
00427     {
00428         fprintf(fd, ":IndirectRef ");
00429         m_Indirect.PrintMe(fd, nTabs + 1);
00430     }
00431 }
00432 
00433 // Return the value, looking up any indirect ref.
00434 int MHGenericInteger::GetValue(MHEngine *engine) const
00435 {
00436     if (m_fIsDirect)
00437     {
00438         return m_nDirect;
00439     }
00440     else
00441     {
00442         MHUnion result;
00443         MHRoot *pBase = engine->FindObject(m_Indirect);
00444         pBase->GetVariableValue(result, engine);
00445 
00446         // From my reading of the MHEG documents implicit conversion is only
00447         // performed when assigning variables.  Nevertheless the Channel 4
00448         // Teletext assumes that implicit conversion takes place here as well.
00449         if (result.m_Type == MHUnion::U_String)
00450         {
00451             // Implicit conversion of string to integer.
00452             int v = 0;
00453             int p = 0;
00454             bool fNegative = false;
00455 
00456             if (result.m_StrVal.Size() > 0 && result.m_StrVal.GetAt(0) == '-')
00457             {
00458                 p++;
00459                 fNegative = true;
00460             }
00461 
00462             for (; p < result.m_StrVal.Size(); p++)
00463             {
00464                 unsigned char ch =  result.m_StrVal.GetAt(p);
00465 
00466                 if (ch < '0' || ch > '9')
00467                 {
00468                     break;
00469                 }
00470 
00471                 v = v * 10 + ch - '0';
00472             }
00473 
00474             if (fNegative)
00475             {
00476                 return -v;
00477             }
00478             else
00479             {
00480                 return v;
00481             }
00482         }
00483         else
00484         {
00485             result.CheckType(MHUnion::U_Int);
00486             return result.m_nIntVal;
00487         }
00488     }
00489 }
00490 
00491 void MHGenericOctetString::Initialise(MHParseNode *pArg, MHEngine *engine)
00492 {
00493     if (pArg->m_nNodeType == MHParseNode::PNTagged && pArg->GetTagNo() == C_INDIRECTREFERENCE)
00494     {
00495         // Indirect reference.
00496         m_fIsDirect = false;
00497         m_Indirect.Initialise(pArg->GetArgN(0), engine);
00498     }
00499     else   // Simple string value.
00500     {
00501         m_fIsDirect = true;
00502         pArg->GetStringValue(m_Direct);
00503     }
00504 }
00505 
00506 void MHGenericOctetString::PrintMe(FILE *fd, int /*nTabs*/) const
00507 {
00508     if (m_fIsDirect)
00509     {
00510         m_Direct.PrintMe(fd, 0);
00511     }
00512     else
00513     {
00514         fprintf(fd, ":IndirectRef ");
00515         m_Indirect.PrintMe(fd, 0);
00516     }
00517 }
00518 
00519 // Return the value, looking up any indirect ref.
00520 void MHGenericOctetString::GetValue(MHOctetString &str, MHEngine *engine) const
00521 {
00522     if (m_fIsDirect)
00523     {
00524         str.Copy(m_Direct);
00525     }
00526     else
00527     {
00528         MHUnion result;
00529         MHRoot *pBase = engine->FindObject(m_Indirect);
00530         pBase->GetVariableValue(result, engine);
00531 
00532         // From my reading of the MHEG documents implicit conversion is only
00533         // performed when assigning variables.  Nevertheless the Channel 4
00534         // Teletext assumes that implicit conversion takes place here as well.
00535         if (result.m_Type == MHUnion::U_Int)
00536         {
00537             // Implicit conversion of int to string.
00538             char buff[30]; // 30 chars is more than enough.
00539 #ifdef _WIN32
00540             _snprintf(buff, sizeof(buff), "%0d", result.m_nIntVal);
00541 #else
00542             snprintf(buff, sizeof(buff), "%0d", result.m_nIntVal);
00543 #endif
00544             str.Copy(buff);
00545         }
00546         else
00547         {
00548             result.CheckType(MHUnion::U_String);
00549             str.Copy(result.m_StrVal);
00550         }
00551     }
00552 }
00553 
00554 void MHGenericObjectRef::Initialise(MHParseNode *pArg, MHEngine *engine)
00555 {
00556     if (pArg->m_nNodeType == MHParseNode::PNTagged && pArg->GetTagNo() == C_INDIRECTREFERENCE)
00557     {
00558         // Indirect reference.
00559         m_fIsDirect = false;
00560         m_Indirect.Initialise(pArg->GetArgN(0), engine);
00561     }
00562     else   // Direct reference.
00563     {
00564         m_fIsDirect = true;
00565         m_ObjRef.Initialise(pArg, engine);
00566     }
00567 }
00568 
00569 void MHGenericObjectRef::PrintMe(FILE *fd, int nTabs) const
00570 {
00571     if (m_fIsDirect)
00572     {
00573         m_ObjRef.PrintMe(fd, nTabs + 1);
00574     }
00575     else
00576     {
00577         fprintf(fd, ":IndirectRef ");
00578         m_Indirect.PrintMe(fd, nTabs + 1);
00579     }
00580 }
00581 
00582 // Return the value, looking up any indirect ref.
00583 void MHGenericObjectRef::GetValue(MHObjectRef &ref, MHEngine *engine) const
00584 {
00585     if (m_fIsDirect)
00586     {
00587         ref.Copy(m_ObjRef);
00588     }
00589     else
00590     {
00591         MHUnion result;
00592         MHRoot *pBase = engine->FindObject(m_Indirect);
00593         pBase->GetVariableValue(result, engine);
00594         result.CheckType(MHUnion::U_ObjRef);
00595         ref.Copy(result.m_ObjRefVal);
00596     }
00597 }
00598 
00599 void MHGenericContentRef::Initialise(MHParseNode *pArg, MHEngine *engine)
00600 {
00601     if (pArg->GetTagNo() == C_INDIRECTREFERENCE)
00602     {
00603         // Indirect reference.
00604         m_fIsDirect = false;
00605         m_Indirect.Initialise(pArg->GetArgN(0), engine);
00606     }
00607     else if (pArg->GetTagNo() == C_CONTENT_REFERENCE)  // Direct reference.
00608     {
00609         m_fIsDirect = true;
00610         m_Direct.Initialise(pArg->GetArgN(0), engine);
00611     }
00612     else
00613     {
00614         MHERROR("Expected direct or indirect content reference");
00615     }
00616 }
00617 
00618 void MHGenericContentRef::PrintMe(FILE *fd, int /*nTabs*/) const
00619 {
00620     if (m_fIsDirect)
00621     {
00622         m_Direct.PrintMe(fd, 0);
00623     }
00624     else
00625     {
00626         fprintf(fd, ":IndirectRef ");
00627         m_Indirect.PrintMe(fd, 0);
00628     }
00629 }
00630 
00631 // Return the value, looking up any indirect ref.
00632 void MHGenericContentRef::GetValue(MHContentRef &ref, MHEngine *engine) const
00633 {
00634     if (m_fIsDirect)
00635     {
00636         ref.Copy(m_Direct);
00637     }
00638     else
00639     {
00640         MHUnion result;
00641         MHRoot *pBase = engine->FindObject(m_Indirect);
00642         pBase->GetVariableValue(result, engine);
00643         result.CheckType(MHUnion::U_ContentRef);
00644         ref.Copy(result.m_ContentRefVal);
00645     }
00646 }
00647 
00648 // Copies the argument, getting the value of an indirect args.
00649 void MHUnion::GetValueFrom(const MHParameter &value, MHEngine *engine)
00650 {
00651     switch (value.m_Type)
00652     {
00653         case MHParameter::P_Int:
00654             m_Type = U_Int;
00655             m_nIntVal = value.m_IntVal.GetValue(engine);
00656             break;
00657         case MHParameter::P_Bool:
00658             m_Type = U_Bool;
00659             m_fBoolVal = value.m_BoolVal.GetValue(engine);
00660             break;
00661         case MHParameter::P_String:
00662             m_Type = U_String;
00663             value.m_StrVal.GetValue(m_StrVal, engine);
00664             break;
00665         case MHParameter::P_ObjRef:
00666             m_Type = U_ObjRef;
00667             value.m_ObjRefVal.GetValue(m_ObjRefVal, engine);
00668             break;
00669         case MHParameter::P_ContentRef:
00670             m_Type = U_ContentRef;
00671             value.m_ContentRefVal.GetValue(m_ContentRefVal, engine);
00672             break;
00673         case MHParameter::P_Null:
00674             m_Type = U_None;
00675             break;
00676     }
00677 }
00678 
00679 const char *MHUnion::GetAsString(enum UnionTypes t)
00680 {
00681     switch (t)
00682     {
00683         case U_Int:
00684             return "int";
00685         case U_Bool:
00686             return "bool";
00687         case U_String:
00688             return "string";
00689         case U_ObjRef:
00690             return "objref";
00691         case U_ContentRef:
00692             return "contentref";
00693         case U_None:
00694             return "none";
00695     }
00696 
00697     return ""; // Not reached.
00698 }
00699 
00700 void MHUnion::CheckType(enum UnionTypes t) const
00701 {
00702     if (m_Type != t)
00703     {
00704         MHERROR(QString("Type mismatch - expected %1 found %2").arg(GetAsString(m_Type)).arg(GetAsString(t)));
00705     }
00706 }
00707 
00708 
00709 // A parameter is a generic whose argument is either the value itself or an indirect reference.
00710 void MHParameter::Initialise(MHParseNode *p, MHEngine *engine)
00711 {
00712     switch (p->GetTagNo())
00713     {
00714         case C_NEW_GENERIC_BOOLEAN:
00715             m_Type = P_Bool;
00716             m_BoolVal.Initialise(p->GetArgN(0), engine);
00717             break;
00718         case C_NEW_GENERIC_INTEGER:
00719             m_Type = P_Int;
00720             m_IntVal.Initialise(p->GetArgN(0), engine);
00721             break;
00722         case C_NEW_GENERIC_OCTETSTRING:
00723             m_Type = P_String;
00724             m_StrVal.Initialise(p->GetArgN(0), engine);
00725             break;
00726         case C_NEW_GENERIC_OBJECT_REF:
00727             m_Type = P_ObjRef;
00728             m_ObjRefVal.Initialise(p->GetArgN(0), engine);
00729             break;
00730         case C_NEW_GENERIC_CONTENT_REF:
00731             m_Type = P_ContentRef;
00732             m_ContentRefVal.Initialise(p->GetArgN(0), engine);
00733             break;
00734         default:
00735             p->Failure("Expected generic");
00736     }
00737 }
00738 
00739 void MHParameter::PrintMe(FILE *fd, int nTabs) const
00740 {
00741     PrintTabs(fd, nTabs);
00742 
00743     switch (m_Type)
00744     {
00745             // Direct values.
00746         case P_Int:
00747             fprintf(fd, ":GInteger ");
00748             m_IntVal.PrintMe(fd, 0);
00749             break;
00750         case P_Bool:
00751             fprintf(fd, ":GBoolean ");
00752             m_BoolVal.PrintMe(fd, 0);
00753             break;
00754         case P_String:
00755             fprintf(fd, ":GOctetString ");
00756             m_StrVal.PrintMe(fd, 0);
00757             break;
00758         case P_ObjRef:
00759             fprintf(fd, ":GObjectRef ");
00760             m_ObjRefVal.PrintMe(fd, 0);
00761             break;
00762         case P_ContentRef:
00763             fprintf(fd, ":GObjectRef ");
00764             m_ContentRefVal.PrintMe(fd, 0);
00765             break;
00766         case P_Null:
00767             break;
00768     }
00769 }
00770 
00771 // Return the indirect reference so that it can be updated.  We don't need to check
00772 // the type at this stage.  If we assign the wrong value that will be picked up in
00773 // the assignment.
00774 MHObjectRef *MHParameter::GetReference()
00775 {
00776     switch (m_Type)
00777     {
00778         case P_Int:
00779             return m_IntVal.GetReference();
00780         case P_Bool:
00781             return m_BoolVal.GetReference();
00782         case P_String:
00783             return m_StrVal.GetReference();
00784         case P_ObjRef:
00785             return m_ObjRefVal.GetReference();
00786         case P_ContentRef:
00787             return m_ContentRefVal.GetReference();
00788         case P_Null:
00789             return NULL;
00790     }
00791 
00792     return NULL; // To keep VC++ happy
00793 }
00794 
00795 // A content reference is simply a string.
00796 MHContentRef MHContentRef::Null; // This is the empty string.
00797 
00798 void MHContentRef::Initialise(MHParseNode *p, MHEngine *)
00799 {
00800     p->GetStringValue(m_ContentRef);
00801 }
00802 
00803 void MHFontBody::Initialise(MHParseNode *p, MHEngine *engine)
00804 {
00805     if (p->m_nNodeType == MHParseNode::PNString)
00806     {
00807         p->GetStringValue(m_DirFont);
00808     }
00809     else
00810     {
00811         m_IndirFont.Initialise(p, engine);
00812     }
00813 }
00814 
00815 void MHFontBody::PrintMe(FILE *fd, int nTabs) const
00816 {
00817     if (m_DirFont.Size() > 0)
00818     {
00819         m_DirFont.PrintMe(fd, nTabs);
00820     }
00821     else
00822     {
00823         m_IndirFont.PrintMe(fd, nTabs);
00824     }
00825 }
00826 
00827 void MHFontBody::Copy(const MHFontBody &fb)
00828 {
00829     m_DirFont.Copy(fb.m_DirFont);
00830     m_IndirFont.Copy(fb.m_IndirFont);
00831 }
00832 
00833 void MHPointArg::Initialise(MHParseNode *p, MHEngine *engine)
00834 {
00835     x.Initialise(p->GetSeqN(0), engine);
00836     y.Initialise(p->GetSeqN(1), engine);
00837 }
00838 
00839 void MHPointArg::PrintMe(FILE *fd, int nTabs) const
00840 {
00841     fprintf(fd, "( ");
00842     x.PrintMe(fd, nTabs);
00843     y.PrintMe(fd, nTabs);
00844     fprintf(fd, ") ");
00845 }
00846 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends