00001 /* 00002 File: SLContext.cc 00003 00004 Function: See header file 00005 00006 Author(s): Andrew Willmott 00007 00008 Copyright: (c) 1995-2000, Andrew Willmott 00009 00010 Notes: 00011 00012 */ 00013 00014 00015 #include "gcl/SLContext.h" 00016 00029 const UInt16 slc_EOL = 0x8000; 00030 const UInt16 slc_DaemonFlag = 0x4000; 00031 const UInt16 slc_LevelMask = 0x0FFF; 00032 00033 00034 SLContext::SLContext(Int numAttrs) : 00035 attributeList(numAttrs), 00036 attributeStack() 00037 { 00038 Clear(); 00039 } 00040 00041 AttrPtr SLContext::Get(AttrType attrType) 00042 { 00043 if (attributeList[attrType].level & slc_DaemonFlag) 00044 return(attributeList[attrType].daemon->Get()); 00045 else 00046 return(attributeList[attrType].data); 00047 } 00048 00049 Void SLContext::Set(AttrType attrType, AttrPtr attrPtr) 00050 { 00051 Assert(attrType < attributeList.NumItems(), 00052 "(SLContext::Set) Unknown attribute type"); 00053 AttrRec *pRec = &attributeList[attrType]; 00054 AttrStackRec sRec; 00055 Bool isDaemon = (pRec->level & slc_DaemonFlag); 00056 00057 // if the attribute exists and wasn't set this level, push it... 00058 00059 if (pRec->data && (pRec->level & slc_LevelMask) < level) 00060 { 00061 sRec.attrRec = *pRec; 00062 sRec.attrType = attrType; 00063 00064 if (isDaemon) 00065 pRec->daemon->Save(); 00066 00067 attributeStack.Push(sRec); 00068 } 00069 00070 if (isDaemon) 00071 pRec->daemon->Set(attrPtr); 00072 else 00073 pRec->data = attrPtr; 00074 00075 pRec->level = level; 00076 } 00077 00078 Void SLContext::SetDaemon(AttrType attrType, AttrDaemon *daemon) 00079 { 00080 Assert((attributeList[attrType].level & slc_DaemonFlag) == 0, "Daemon already set for this slot."); 00081 00082 Set(attrType, daemon); 00083 00084 if (daemon) 00085 attributeList[attrType].level |= slc_DaemonFlag; 00086 } 00087 00088 Void SLContext::Push() 00089 { 00090 AttrStackRec sRec; 00091 00092 level++; 00093 sRec.attrRec.level = slc_EOL; // mark pRec as a sentinel 00094 attributeStack.Push(sRec); // Add to the stack 00095 } 00096 00097 Void SLContext::Pop() 00098 { 00099 Int i; 00100 00101 // pop off all the attributes changed since the last push... 00102 00103 Assert(level > 0, "(SLContext::Pop) Too many pops"); 00104 00105 while (!(attributeStack.Top().attrRec.level & slc_EOL)) 00106 { 00107 if (attributeStack.Top().attrRec.level & slc_DaemonFlag) 00108 attributeStack.Top().attrRec.daemon->Restore(); 00109 00110 attributeList[attributeStack.Top().attrType] = 00111 attributeStack.Top().attrRec; 00112 attributeStack.Pop(); 00113 } 00114 00115 // pop off the sentinel... 00116 00117 attributeStack.Pop(); 00118 level--; 00119 00120 // zero anything that wasn't previously set at this level. 00121 00122 for (i = 0; i < attributeList.NumItems(); i++) 00123 if ((attributeList[i].level & slc_LevelMask) > level) 00124 { 00125 attributeList[i].data = 0; 00126 attributeList[i].level = 0; 00127 } 00128 } 00129 00130 Bool SLContext::IsCurrent(AttrType attrType) 00131 { 00132 return(attributeList[attrType].level == level); 00133 } 00134 00135 Void SLContext::Clear() 00136 { 00137 Int i; 00138 00139 attributeStack.SetSize(0); 00140 level = 0; 00141 00142 for (i = 0; i < attributeList.NumItems(); i++) 00143 { 00144 attributeList[i].level = 0; 00145 attributeList[i].data = 0; 00146 } 00147 } 00148 00149 ostream &operator << (ostream &s, const AttrRec &ar) 00150 { 00151 s << ar.data << "@" << ar.level; 00152 00153 return(s); 00154 } 00155 00156 ostream &operator << (ostream &s, const AttrStackRec &asr) 00157 { 00158 s << asr.attrRec << ":" << asr.attrType; 00159 00160 return(s); 00161 } 00162 00163 ostream &operator << (ostream &s, const SLContext &ctx) 00164 { 00165 s << "SLContext at level " << ctx.level << ". Current attributes: " << endl; 00166 s << (AttrList &) ctx.attributeList << endl; 00167 s << "Attribute stack: " << endl << (AttrStackList &) ctx.attributeStack << endl; 00168 00169 return(s); 00170 } 00171 00172