|
MythTV
0.26-pre
|
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
1.7.6.1