Beispiel #1
0
  // here for <!ATTLIST blah>
void CMUSHclientDoc::MXP_Attlist (CString strName, CString strTag)
  {
// append attributes strTag to element strName

CElement * pElement;

  strName.MakeLower (); // case-insensitive?

// check element already defined
  if (!m_CustomElementMap.Lookup (strName, pElement))
    {
    MXP_error (DBG_ERROR, errMXP_UnknownElementInAttlist,
              TFormat ("Cannot add attributes to undefined MXP element: <%s>", 
                (LPCTSTR) strName)); 
    return;
    } // end of no element matching

CArgumentList ArgumentList;

  // build into an argument list
  if (BuildArgumentList (ArgumentList, strTag))
    {
    DELETE_LIST (ArgumentList);
    return;
    }

  // add to any existing arguments - is this wise? :)
  pElement->AttributeList.AddTail (&ArgumentList);

  // nb - arguments get moved to argument list - no need to delete them
  } // end of CMUSHclientDoc::MXP_Attlist
	void WordcodeEmitter::computeExceptionFixups() 
	{
		if (info == NULL || info->exceptions == NULL)
			return;
		
		DELETE_LIST(catch_info, exception_fixes);
		
		ExceptionHandlerTable* old_table = info->exceptions;
		int exception_count = old_table->exception_count;
		size_t extra = sizeof(ExceptionHandler)*(exception_count - 1);
		ExceptionHandlerTable* new_table = new (core->GetGC(), extra) ExceptionHandlerTable(exception_count);
		
		// Insert items in the exn list for from, to, and target, with the pc pointing
		// to the correct triggering instruction in the ABC and the update loc
		// pointing to the location to be patched; and a flag is_int_offset (if false
		// it's a intptr_t).
		
		for ( int i=0 ; i < exception_count ; i++ ) {
			
			new_table->exceptions[i].traits = old_table->exceptions[i].traits;
			new_table->exceptions[i].scopeTraits = old_table->exceptions[i].scopeTraits;
			
			catch_info* p[3];
			
			p[0] = new catch_info;
			p[0]->pc = code_start + info->exceptions->exceptions[i].from;
			p[0]->is_target = false;
			p[0]->fixup_loc = (void*)&(new_table->exceptions[i].from);
			
			p[1] = new catch_info;
			p[1]->pc = code_start + info->exceptions->exceptions[i].to;
			p[1]->is_target = false;
			p[1]->fixup_loc = (void*)&(new_table->exceptions[i].to);
			
			p[2] = new catch_info;
			p[2]->pc = code_start + info->exceptions->exceptions[i].target;
			p[2]->is_target = true;
			p[2]->fixup_loc = (void*)&(new_table->exceptions[i].target);
			
			if (p[0]->pc > p[1]->pc) {
				catch_info* tmp = p[0];
				p[0] = p[1];
				p[1] = tmp;
			}
			if (p[1]->pc > p[2]->pc) {
				catch_info* tmp = p[1];
				p[1] = p[2];
				p[2] = tmp;
			}
			if (p[0]->pc > p[1]->pc) {
				catch_info* tmp = p[0];
				p[0] = p[1];
				p[1] = tmp;
			}
			
			int j=0;
			catch_info* e = exception_fixes;
			catch_info* ee = NULL;
			while (j < 3 && e != NULL) {
				if (e->pc > p[j]->pc) {
					if (ee == NULL) 
						exception_fixes = p[j];
					else 
						ee->next = p[j];
					p[j]->next = e;
					e = p[j];
					j++;
				}
				else {
					ee = e;
					e = e->next;
				}
			}
			while (j < 3) {
				if (ee == NULL) 
					exception_fixes = p[j];
				else 
					ee->next = p[j];
				p[j]->next = e;
				ee = p[j];
				j++;
			}
		}
		
		WB(core->GetGC(), info, &info->word_code.exceptions, new_table);
		
#ifdef _DEBUG
		if (exception_fixes != NULL) {
			catch_info* ee = exception_fixes;
			catch_info* e = ee->next;
			AvmAssert(ee->pc <= e->pc);
			ee = e;
			e = e->next;
		}
#endif
	}
Beispiel #3
0
bool CMUSHclientDoc::BuildArgumentList (CArgumentList & ArgumentList, 
                                        CString strTag) 
  {
CArgument * pArgument;
int iArgumentNumber = 0;
bool bEnd;
CString strArgumentName;
CString strEquals;
CString strArgumentValue;


// first get rid of old arguments

  DELETE_LIST (ArgumentList);

// collect all arguments

  // get first word
  bEnd = GetWord (strArgumentName, strTag);

  while (!bEnd)
    {

    if (strArgumentName == "/")
      {
      strTag.TrimLeft ();
      if (!strTag.IsEmpty ())
          {
          MXP_error (DBG_ERROR, errMXP_InvalidArgumentName,
                    TFormat ("Invalid parameter name: \"%s\"", 
                    (LPCTSTR) strArgumentName)); 
          return true;
          }
    
      // NB - not implemented yet - we have detected an empty tag.
      //      eg.  <sound blah blah />

      return false;   // OK return

      } // end of / at end of list

// #error fix it here ...

    // is it folllowed by equals?
    bEnd = GetWord (strEquals, strTag);
    if (strEquals == "=") // yes
      {
      if (!IsValidName (strArgumentName))   // check name valid
        {
        MXP_error (DBG_ERROR, errMXP_InvalidArgumentName,
                  TFormat ("Invalid parameter name: \"%s\"", 
                  (LPCTSTR) strArgumentName)); 
        return true;
        }

      bEnd = GetWord (strArgumentValue, strTag);  // so get value
      if (bEnd)
        {
        MXP_error (DBG_ERROR, errMXP_NoArgument,
                    TFormat ("No argument value supplied for: \"%s\"", 
                  (LPCTSTR) strArgumentName)); 
        return true;
        }

      strArgumentName.MakeLower ();
      // named arguments don't have a numbered position
      pArgument = new CArgument (strArgumentName, strArgumentValue, 0);
      ArgumentList.AddTail (pArgument);
      bEnd = GetWord (strArgumentName, strTag); // get next argument
      }   // end of name=value
    else
      { // positional argument, no name=value
      // thus, name is value
      pArgument = new CArgument ("", strArgumentName, ++iArgumentNumber);
      ArgumentList.AddTail (pArgument);
      strArgumentName = strEquals;    // and strEquals is next argument, if any      
      }   // end of value alone
    }  // end of processing each argument                             

  return false; // all OK
  } // end of CMUSHclientDoc::BuildArgumentList 
Beispiel #4
0
// here for start tag, eg. <bold> <underline> <usertag>
void CMUSHclientDoc::MXP_StartTag (CString strTag)
  {
// are we in secure mode right now?
bool bSecure = MXP_Secure ();
bool bNoReset = false;

  MXP_Restore_Mode ();  // cancel secure-once mode

static CArgumentList ArgumentList;

CString strName;

  GetWord (strName, strTag);

  // count them
  m_iMXPtags++;

  if (!IsValidName (strName))
    {
    MXP_error (DBG_ERROR, errMXP_InvalidElementName,
                TFormat ("Invalid MXP element name \"%s\" supplied.",
                strName)); 
    return;
    }

  // case insensitive?
  strName.MakeLower ();

// see if we know of this element

CAtomicElement * pAtomicElement = NULL;
CElement * pElement = NULL;
bool bOpen;
bool bCommand;
POSITION atompos;

// find existing styles

CStyle * pStyle = m_pCurrentLine->styleList.GetTail ();

unsigned short iFlags = pStyle->iFlags;      
COLORREF       iForeColour = pStyle->iForeColour; 
COLORREF       iBackColour = pStyle->iBackColour; 
CAction *      pAction = pStyle->pAction;

CString strAction;    
CString strHint;      
CString strVariable;  

  // get old action, hint etc. so that something like:
  // <send href="nick"> <b> blah </b> </send> will work
  // in this case we want the href (action) to persist through the <b>

  if (pAction)
    {
    strAction = pAction->m_strAction;
    strHint = pAction->m_strHint;
    strVariable = pAction->m_strVariable;
    } // end of having an action etc.


  if (App.m_ElementMap.Lookup (strName, pAtomicElement))
    {
    bOpen    = (pAtomicElement->iFlags & TAG_OPEN) != 0;
    bCommand = (pAtomicElement->iFlags & TAG_COMMAND) != 0;
    bNoReset = (pAtomicElement->iFlags & TAG_NO_RESET) != 0;

    // check for mixing Pueblo and MXP tags

/*

  // ALLOW BOTH for now

    if ((pAtomicElement->iFlags & TAG_PUEBLO) &&
        !m_bPuebloActive)
      {
      MXP_error (DBG_ERROR, errMXP_PuebloOnly,
                TFormat ("Using Pueblo-only element in MXP mode: <%s>" ,
                          (LPCTSTR) strName));
      return;
      }
    
    if ((pAtomicElement->iFlags & TAG_MXP) &&
        m_bPuebloActive)
      {
      MXP_error (DBG_ERROR, errMXP_MXPOnly,
                TFormat ("Using MXP-only element in Pueblo mode: <%s>" ,
                          (LPCTSTR) strName));
      return;
      }

*/

    } // end of atomic element found
  else
    {
    if (!m_CustomElementMap.Lookup (strName, pElement))
      {
      MXP_error (DBG_ERROR, errMXP_UnknownElement,
                 TFormat ("Unknown MXP element: <%s>" ,
                          (LPCTSTR) strName));
      return;
      }
    pAtomicElement = NULL;
    bOpen    = pElement->bOpen;
    bCommand = pElement->bCommand;
    if (!pElement->strFlag.IsEmpty ())
      strVariable = pElement->strFlag;  // might have a variable to set
    } // end of not atomic


  // check for secure tags
  if (!bOpen && 
      !bSecure &&
      SECURE_ELEMENT_CHECK)
    {
    MXP_error (DBG_ERROR, errMXP_ElementWhenNotSecure,
                TFormat ("Secure MXP tag ignored when not in secure mode: <%s>" ,
                        (LPCTSTR) strName));
    return;
    }


  if (BuildArgumentList (ArgumentList, strTag))
    {
    DELETE_LIST (ArgumentList);
    return;
    }

  // call script if required for user-defined elements
  // atomic elements have their script called in MXP_OpenAtomicTag

  if ((m_dispidOnMXP_OpenTag != DISPID_UNKNOWN || m_bPluginProcessesOpenTag)
        && pAtomicElement == NULL)
    {
    bool bNotWanted = MXP_StartTagScript (strName, strTag, ArgumentList);

    // re-get current style in case the script did a world.note
    pStyle = m_pCurrentLine->styleList.GetTail ();

    // put things backt to how they were
    pStyle->iFlags      = iFlags;      
    pStyle->iForeColour = iForeColour; 
    pStyle->iBackColour = iBackColour; 

    if (bNotWanted)
      return;   // they didn't want to go ahead with this tag

    }

// If existing run is zero length, get rid of it, unless it
// is a tag marker

  if (pStyle->iLength == 0 && (pStyle->iFlags & START_TAG) == 0)
    {
    DELETESTYLE (pStyle);
    m_pCurrentLine->styleList.RemoveTail ();
    }

  // command tags are not popped from the stack, and thus don't need a record

  if (!bCommand)
    {
  // add a marker to the current line for the tag itself
  // this is a record of what the text style was at this point

    AddStyle (iFlags | START_TAG, 
              iForeColour, 
              iBackColour, 
              0, 
              strName,
              "",
              strVariable);

    // remember what is outstanding

    CActiveTag * pTag = new CActiveTag;

    pTag->strName = strName;
    pTag->bSecure = bSecure;
    pTag->bNoReset = bNoReset;
    m_ActiveTagList.AddTail (pTag);  // add to outstanding tag list

    // warn if they are overdoing the outstanding tags
    if (m_ActiveTagList.GetCount () % OUTSTANDING_TAG_WARNING == 0 &&
        m_ActiveTagList.GetCount () != m_iLastOutstandingTagCount)
      {
      MXP_error (DBG_WARNING, wrnMXP_ManyOutstandingTags,
                  TFormat (
                          "Now have %i outstanding MXP tags" ,
                          m_ActiveTagList.GetCount ()));
      m_iLastOutstandingTagCount = m_ActiveTagList.GetCount ();
      }


    } // end of not command tag

//if (strName == "ex")
  /*
  {

  iFlags &= ~COLOURTYPE;  // clear bits, eg. custom
  iFlags |= COLOUR_RGB;

  iForeColour = 255;
  iBackColour = 255 * 256;
  }
  */

// now add another style entry to the line - this will have the
// style adjusted for the new attributes (eg. bold)

CStyle * pNewStyle = AddStyle (iFlags & STYLE_BITS, 
                               iForeColour, 
                               iBackColour, 
                               0, 
                               NULL);  // we will add the action later

  
  // atomic element?  (looked-up earlier)
  if (pAtomicElement)
    {
    CArgument * pArgument;

    for (atompos = ArgumentList.GetHeadPosition (); atompos; )
      {
      pArgument = ArgumentList.GetNext (atompos);

      // Walk the value for &xxx; entries

      if (pArgument->strValue.Find ('&') != -1)
        {

        const char * p = pArgument->strValue;
        const char * pStart = pArgument->strValue;
        CString strEntity;
        CString strFixedValue;
        strFixedValue.Empty ();
        long length;

        for ( ; *p; p++)
          {
          if (*p == '&')
            {

            // copy up to ampersand
            length = p - pStart;
      
            if (length > 0)
              strFixedValue += CString (pStart, length);

            p++;    // skip ampersand
            pStart = p; // where entity starts
            for ( ; *p && *p != ';'; p++) // look for closing semicolon
              ; // just keep looking
            if (*p != ';')
              {
              MXP_error (DBG_ERROR, errMXP_NoClosingSemicolonInArgument,
                        TFormat ("No closing \";\" in MXP element argument \"%s\"", 
                        (LPCTSTR) pArgument->strValue)); 
              return;
              }

            strEntity = CString (pStart, p - pStart);   // build entity, excluding & and ;

            // b. i. Look up entity in attribute list by name (eg. "col")

            CString strReplacement = "&text;";

            if (strEntity != "text")
              strReplacement = MXP_GetEntity (strEntity);
            strFixedValue += strReplacement;    // add to list

            pStart = p + 1;   // move on past the entity
            
            } // end of having an ampersand 

          } // end of processing the value

        strFixedValue += pStart;

        pArgument->strValue = strFixedValue;
        } // end of subsitution needed
      } // end of processing each argument in the atomic list

    MXP_OpenAtomicTag (strName,
                       pAtomicElement->iAction, 
                       pNewStyle,
                       strAction,
                       strHint,
                       strVariable,
                       ArgumentList);

    // new style might have changed if they started a new line
    // (eg. BR)
    if (!m_pCurrentLine->styleList.IsEmpty ())
      {
      pNewStyle = m_pCurrentLine->styleList.GetTail ();
      RememberStyle (pNewStyle);
      if (pNewStyle->pAction)
        {
        strAction = pNewStyle->pAction->m_strAction;
        strHint =  pNewStyle->pAction->m_strHint;
        strVariable = pNewStyle->pAction->m_strVariable;
        }
      }

    pNewStyle->pAction = GetAction (strAction, strHint, strVariable);

    DELETE_LIST (ArgumentList);  // clean up memory
    return;
    }

// --------- end of processing for ATOMIC element ------------

// must be a user-defined element

CElementItem * pElementItem;

  for (POSITION pos = pElement->ElementItemList.GetHeadPosition (); pos; )
    {
    pElementItem = pElement->ElementItemList.GetNext (pos);

    CArgumentList BuiltArgumentList;
    BuiltArgumentList.RemoveAll ();

    /* we need to build up the arguments to the atomic element from 3 places:

    1. The atom itself needs an argument list (eg. <COLOR &col;> )
    2. The user-defined element has an attribute list that lists possible arguments
       possibly with defaults, eg. col=red
    3. The tag itself may supply values, eg. col=blue

    These are:
       1.  pElementItem->ArgumentList     - what the atomic element wants
       2.  pElement->AttributeList        - what it can get, including defaults
       3.  ArgumentList                   - what is specified on *this* tag

    So, I think we need to:
     
       a. Walk the atomic item's argument list
       b. For any entries in the form &xxx; ...
           0. The special case &text; is left alone (for processing later)
           i. Look up the entity in the attribute list (2) above. 
          ii. If found, go to (c).
         iii. Look up entity in entities map (could be &lt; for instance)
          iv. If found, just replace it and continue
           v. If not found still, error
       c. If entity is found in attribute list (2) above, then:
       d. Look up value in supplied arguments (3) by name and position.
       e. If found, take supplied value.
       f. If not found, take default from (2) including <nothing> if applicable.

     Each entry gets built into BuiltArgumentList and passed down to the atomic element
     processing routine.

    */

    // a. Walk the atom's list
    CArgument * pArgument;
    int iArgumentNumber = 0;

    for (atompos = pElementItem->ArgumentList.GetHeadPosition (); atompos; )
      {
      pArgument = pElementItem->ArgumentList.GetNext (atompos);

      // b. Walk the value for &xxx; entries

      const char * p = pArgument->strValue;
      const char * pStart = pArgument->strValue;
      CString strEntity;
      CString strFixedValue;
      long length;

      strFixedValue.Empty ();

      for ( ; *p; p++)
        {
        if (*p == '&')
          {

          // copy up to ampersand
          length = p - pStart;
    
          if (length > 0)
            strFixedValue += CString (pStart, length);

          p++;    // skip ampersand
          pStart = p; // where entity starts
          for ( ; *p && *p != ';'; p++) // look for closing semicolon
            ; // just keep looking
          if (*p != ';')
            {
            MXP_error (DBG_ERROR, errMXP_NoClosingSemicolonInArgument,
                      TFormat ("No closing \";\" in MXP element argument \"%s\"", 
                      (LPCTSTR) pArgument->strValue)); 
            return;
            }

          strEntity = CString (pStart, p - pStart);   // build entity, excluding & and ;

          // b. i. Look up entity in attribute list by name (eg. "col")

          CString strReplacement = "&text;";

          if (strEntity != "text")
            {

            CString strDefault;

            CArgument * pAttribute = NULL;
            int iSequence = 1;

            for (POSITION attpos = pElement->AttributeList.GetHeadPosition (); 
                 attpos; 
                 iSequence++)
              {
              pAttribute = pElement->AttributeList.GetNext (attpos);
              if (pAttribute->strName.IsEmpty ())  // no name, value is name (ie. no default)
                {
                if (pAttribute->strValue.CompareNoCase (strEntity) == 0)
                  break;
                }
              else
                if (pAttribute->strName.CompareNoCase (strEntity) == 0)
                  {
                  strDefault = pAttribute->strValue;
                  break;
                  }
              pAttribute = NULL;   // indicates it wasn't found
              }  // end of looking for the attribute

            if (pAttribute)
              {

              // we now have a default and a position - look it up in the supplied arguments

              strReplacement = GetArgument (ArgumentList, strEntity, iSequence, false); 
              if (strReplacement.IsEmpty ())   // empty? take default
                {
                strReplacement = strDefault; 

                // stil empty? Warn them.
                if (strReplacement.IsEmpty ())
                  MXP_error (DBG_WARNING, wrnMXP_ArgumentNotSupplied,
                             TFormat ("Non-default argument \"%s\" not supplied to <%s>", 
                            (LPCTSTR) strEntity,
                            (LPCTSTR) strName
                            ));     
                }

              } // end of attribute found
            else
              strReplacement = MXP_GetEntity (strEntity);
            } // end of not being the entity &text;
          strFixedValue += strReplacement;    // add to list

          pStart = p + 1;   // move on past the entity
          
          } // end of having an ampersand 

        } // end of processing the value

      strFixedValue += pStart;

      // add fixed argument to the built argument list
      CArgument * pNewArgument;

      if (pArgument->strName.IsEmpty ())  // just a positional argument
        {
        pNewArgument = new CArgument ("", strFixedValue, ++iArgumentNumber);
        BuiltArgumentList.AddTail (pNewArgument);
        }
      else
        {
        pNewArgument = new CArgument (pArgument->strName, strFixedValue, 0);
        BuiltArgumentList.AddTail (pNewArgument);
        }


      } // end of processing each argument in the atomic list

    MXP_OpenAtomicTag (pElementItem->pAtomicElement->strName,
                       pElementItem->pAtomicElement->iAction, 
                       pNewStyle,
                       strAction,
                       strHint,
                       strVariable,
                       BuiltArgumentList); 

    DELETE_LIST (BuiltArgumentList);  // just a temporary list
    } // end of doing each atomic element

  // new style might have changed if they started a new line
  // (eg. BR)
  if (!m_pCurrentLine->styleList.IsEmpty ())
    {
    pNewStyle = m_pCurrentLine->styleList.GetTail ();
    RememberStyle (pNewStyle);
    }

  // make an action for the built-up action/hint/variable
  pNewStyle->pAction = GetAction (strAction, strHint, strVariable);

// check all arguments used

  CheckArgumentsUsed (strName, ArgumentList);

  DELETE_LIST (ArgumentList);  // clean up memory

  } // end of CMUSHclientDoc::MXP_StartTag
CMUSHclientDoc::~CMUSHclientDoc()
{
int i;

  // stop sounds playing, release sound buffers
  for (i = 0; i < MAX_SOUND_BUFFERS; i++)
    if (m_pDirectSoundSecondaryBuffer [i])
      {
      DWORD iStatus;
      if (SUCCEEDED (m_pDirectSoundSecondaryBuffer [i]->GetStatus (&iStatus)) &&
          (iStatus & DSBSTATUS_PLAYING))
        m_pDirectSoundSecondaryBuffer [i]->Stop ();

      m_pDirectSoundSecondaryBuffer [i]->Release ();
      }

  if (m_pTimerWnd)
    {
	  m_pTimerWnd->DestroyWindow();
	  delete m_pTimerWnd;
    m_pTimerWnd = NULL;
    }

  for (i = 0; i < 8; i++)  
    delete m_font [i];
  delete m_input_font;

  if (m_hNameLookup)
    WSACancelAsyncRequest (m_hNameLookup);  // cancel host name lookup in progress

  delete [] m_pGetHostStruct;   // delete buffer used by host name lookup

  delete m_MapFailureRegexp;    // delete regexp structure for mapping failures

	if (m_pSocket)
	{

    ShutDownSocket (*m_pSocket);

    delete m_pSocket;
    m_pSocket = NULL;

    }

	if (m_pChatListenSocket)
	{

    ShutDownSocket (*m_pChatListenSocket);

    delete m_pChatListenSocket;
    m_pChatListenSocket = NULL;

    }

  // UDP listening sockets
  for (map<int, UDPsocket *>::iterator udpSocketIterator = m_UDPsocketMap.begin ();
       udpSocketIterator != m_UDPsocketMap.end ();
       udpSocketIterator++)
      delete udpSocketIterator->second;

  // delete chat sessions

  DELETE_LIST (m_ChatList);

  // delete plugins

  // we have to do it this way, because otherwise if a plugin attempts to access the
  // plugin list (eg. BroadcastPlugin, Trace) during the delete operation, then it
  // may call a plugin that was deleted a moment ago, but is still in the list.

   for (PluginListIterator pit = m_PluginList.begin (); 
        pit != m_PluginList.end ();
        pit =  m_PluginList.erase (pit))    // erase from list and get next one
    delete *pit;  // delete *this* one

  CloseLog ();    // this writes out the log file postamble as well

// delete triggers
       
  DELETE_MAP (m_TriggerMap, CTrigger); 

// delete aliass

  DELETE_MAP (m_AliasMap, CAlias); 

// delete lines list

  DELETE_LIST (m_LineList);

// delete timer map

  DELETE_MAP (m_TimerMap, CTimer); 
  
// delete variables map

  DELETE_MAP (m_VariableMap, CVariable); 

// delete Element map

  DELETE_MAP (m_CustomElementMap, CElement); 

// delete active tags list

  DELETE_LIST (m_ActiveTagList);

// delete actions list

  DELETE_LIST (m_ActionList);


// get rid of our positions array

  delete [] m_pLinePositions;

// one less document

  gdoccount--;

// update activity window

  App.m_bUpdateActivity = TRUE;

// ****************** release scripting stuff

  DisableScripting ();

  if (!bWine)
  	AfxOleUnlockApp();        // not needed?

  // free compression stuff

  if (m_CompressOutput)
    free (m_CompressOutput);
  if (m_CompressInput)
    free (m_CompressInput);

  // don't wrap up if not initialised
  if (m_bCompressInitOK)
    inflateEnd (&m_zCompress);

  // don't need to know what the configuration was any more
  DeleteConfigurationArrays ();

  // delete our arrays
  for (tStringMapOfMaps::iterator it = m_Arrays.begin (); 
       it != m_Arrays.end ();
       it++)
         {
         tStringToStringMap * m = it->second;
         m->clear ();
         delete m;
         }

  // destroy accelerator table, if we had one
  if (m_accelerator)
    DestroyAcceleratorTable (m_accelerator);

  // if they loaded a special font, get rid of it
  RemoveSpecialFonts ();

#ifdef PANE

  // get rid of owned panes

  safe_for_each (m_PaneMap.begin (), m_PaneMap.end (), closepane);
#endif // PANE

  // delete MiniWindow map

  for (MiniWindowMapIterator mwit = m_MiniWindows.begin (); 
       mwit != m_MiniWindows.end ();
       mwit++)
         delete mwit->second;

  m_MiniWindowsOrder.clear ();

  // delete databases
  for (tDatabaseMapIterator dbit = m_Databases.begin (); 
       dbit != m_Databases.end ();
       dbit++)
         {
         if (dbit->second->pStmt)        // finalize any outstanding statement
           sqlite3_finalize(dbit->second->pStmt);
         if (dbit->second->db)           // and close the database
           sqlite3_close(dbit->second->db);
         delete dbit->second;      // now delete memory used by it
         }

}   // end of CMUSHclientDoc::~CMUSHclientDoc
Beispiel #6
0
// here for <!ELEMENT blah>
void CMUSHclientDoc::MXP_Element (CString strName, CString strTag)
  {
static CArgumentList ArgumentList;

  // get arguments to !ELEMENT definition
  if (BuildArgumentList (ArgumentList, strTag))
    {
    DELETE_LIST (ArgumentList);
    return;
    }

CElement * pElement;
bool bDelete = GetKeyword (ArgumentList, "delete");

  strName.MakeLower (); // case-insensitive?

  // see if we know of this atom

  CAtomicElement * element_item;

  if (App.m_ElementMap.Lookup (strName, element_item))
    {
    MXP_error (DBG_ERROR, errMXP_CannotRedefineElement,
               TFormat ("Cannot redefine built-in MXP element: <%s>" ,
                        (LPCTSTR) strName));
    return;
    }

// if element already defined, delete old one
  if (m_CustomElementMap.Lookup (strName, pElement))
    {
    if (!bDelete)
      MXP_error (DBG_WARNING, wrnMXP_ReplacingElement, 
                 TFormat ("Replacing previously-defined MXP element: <%s>", 
                (LPCTSTR) strName)); 
    DELETE_LIST (pElement->ElementItemList);
    DELETE_LIST (pElement->AttributeList);
    delete pElement;
    } // end of existing element

  if (bDelete)
    return; // all done!

// add new element to map
m_CustomElementMap.SetAt (strName, pElement = new CElement);

  pElement->strName = strName;

// get keywords first, so we won't mistake them for arguments 
// (eg. so OPEN doesn't become an argument)

  // look for keyword OPEN
  pElement->bOpen = GetKeyword (ArgumentList, "open");

  // look for keyword EMPTY
  pElement->bCommand = GetKeyword (ArgumentList, "empty");

CString strArgument;

  // get definition ( <COLOR &col;> )
  strArgument = GetArgument (ArgumentList, "", 1, false);  // get definition

// add atomic items here  --------------------------

  CString strAtom;

  const char * p = strArgument; 
  const char * pStart; 

  while (*p)
    {
    // check opening <
    if (*p != '<')
      {
      MXP_error (DBG_ERROR, errMXP_NoTagInDefinition,
                TFormat ("No opening \"<\" in MXP element definition \"%s\"", 
                (LPCTSTR) strArgument)); 
      return;
      }
    p++;  // skip <

    pStart = p;   // remember start of tag

    // skip <, look for >
    for (; *p && *p != '>'; p++) // look for closing tag
      {
      if (*p == '<')
        {
        MXP_error (DBG_ERROR, errMXP_UnexpectedDefinitionSymbol,
                  TFormat ("Unexpected \"<\" in MXP element definition \"%s\"", 
                  (LPCTSTR) strArgument)); 
        return;
        }
      if (*p == '\'' || *p == '\"') // quoted string?
        {
        char c = *p;    // remember opening quote
        for (p++; *p && *p != c; p++) // look for closing quote
          ; // just keep looking
        if (*p != c)
          {
          MXP_error (DBG_ERROR, errMXP_NoClosingDefinitionQuote,
                     TFormat ("No closing quote in MXP element definition \"%s\"", 
                    (LPCTSTR) strArgument)); 
          return;
          }
        } // end of quoted string

      } // end of search for closing tag  

    // check closing >
    if (*p != '>')
      {
      MXP_error (DBG_ERROR, errMXP_NoClosingDefinitionTag,
                TFormat ("No closing \">\" in MXP element definition \"%s\"", 
                (LPCTSTR) strArgument)); 
      return;
      }

    strAtom = CString (pStart, p - pStart);   // build tag, excluding < and >

    CString strAtomName;
    
    if (GetWord (strAtomName, strAtom))
      {
      MXP_error (DBG_ERROR, errMXP_NoDefinitionTag,
                TFormat ("No element name in MXP element definition \"<%s>\"", 
                (LPCTSTR) CString (pStart, p - pStart))); 
      return;
      }

    if (strAtomName == "/")
      {
      GetWord (strAtomName, strAtom);   // try to get next word
      strAtomName.MakeLower (); // case insensitive?
      MXP_error (DBG_ERROR, errMXP_DefinitionCannotCloseElement,
                TFormat ("Element definitions cannot close other elements: </%s>" ,
                          (LPCTSTR) strAtomName));
      return;
      }

    if (strAtomName == "!")
      {
      GetWord (strAtomName, strAtom);   // try to get next word
      strAtomName.MakeLower (); // case insensitive?
      MXP_error (DBG_ERROR, errMXP_DefinitionCannotDefineElement,
                TFormat ("Element definitions cannot define other elements: <!%s>" ,
                          (LPCTSTR) strAtomName));
      return;
      }

    strAtomName.MakeLower (); // case insensitive?

    // see if we know of this atom

    CAtomicElement * element_item;
  
    if (!App.m_ElementMap.Lookup (strAtomName, element_item))
      {
      MXP_error (DBG_ERROR, errMXP_NoInbuiltDefinitionTag,
                TFormat ("Unknown MXP element: <%s>" ,
                          (LPCTSTR) strAtomName));
      return;
      }

    // yes?  add to list

    CElementItem * pElementItem = new CElementItem;

    if (BuildArgumentList (pElementItem->ArgumentList, strAtom))  // add arguments
      {     // bad arguments
      DELETE_LIST (pElementItem->ArgumentList);
      delete pElementItem;
      return;
      }

    pElement->ElementItemList.AddTail (pElementItem );
    pElementItem->pAtomicElement = element_item;    // which atomic element

    p++; // skip >


    } // end of processing each atomic item

// end of add atomic items  --------------------------


  // get attributes  (COLOR=RED NAME=FRED)
  if (BuildArgumentList (pElement->AttributeList, GetArgument (ArgumentList, "att", 2, false)))
    {     // bad arguments
    DELETE_LIST (pElement->AttributeList);
    return;
    }


  // get tag (TAG=22)
  strArgument = GetArgument (ArgumentList, "tag", 3, true);  // get tag number

  if (IsNumeric (strArgument))
    {
    int i = atoi (strArgument);
    if (i >= 20 && i <= 99)
       pElement->iTag = i;
    }

  // get tag (FLAG=roomname)
  strArgument = GetArgument (ArgumentList, "flag", 4, true);  // get flag name

  if (!strArgument.IsEmpty ())
    {
/*
//   I won't check names right now ...

   if (strArgument == "roomname" ||
        strArgument == "roomdesc" ||
        strArgument == "roomexit" ||
        strArgument == "roomnum" ||
        strArgument == "prompt")
       pElement->strFlag = strArgument;
    else
*/
    if (strArgument.Left (4) == "set ")
      pElement->strFlag = strArgument.Mid (4);  // what variable to set
    else 
      pElement->strFlag = strArgument;
        
    pElement->strFlag.TrimLeft ();
    pElement->strFlag.TrimRight ();

    // make things a bit easier - let spaces through but change to underscores
    pElement->strFlag.Replace (" ", "_");

    // check variable name is OK
    if (CheckObjectName (pElement->strFlag) != eOK)
      {
      MXP_error (DBG_ERROR, errMXP_BadVariableName,
                 TFormat ("Bad variable name \"%s\" - for MXP FLAG definition", 
                (LPCTSTR) pElement->strFlag)); 
      pElement->strFlag.Empty ();
      }


    } // end of having a flag

  DELETE_LIST (ArgumentList);

  } // end of CMUSHclientDoc::MXP_Element