Esempio n. 1
0
void CMUSHclientDoc::CheckArgumentsUsed (const CString strTag, 
                                         CArgumentList & ArgumentList)
  {

  for (POSITION pos = ArgumentList.GetHeadPosition (); pos; )
    {
    CArgument *  pArgument = ArgumentList.GetNext (pos);

    if (!pArgument->bUsed)
      {
      if (pArgument->strName.IsEmpty ())
        MXP_error (DBG_WARNING, wrnMXP_UnusedArgument,
                   TFormat ("Unused argument (%i) for <%s>: %s", 
                   pArgument->iPosition,
                  (LPCTSTR) strTag,
                  (LPCTSTR) pArgument->strValue
                  ));     
      else
        MXP_error (DBG_WARNING, wrnMXP_UnusedArgument,
                   TFormat ("Unused argument for <%s>: %s=\"%s\"", 
                  (LPCTSTR) strTag,
                  (LPCTSTR) pArgument->strName,
                  (LPCTSTR) pArgument->strValue
                  ));
      } // end of unused argument
    } // end of checking each argument used

  } // end of CMUSHclientDoc::CheckArgumentsUsed 
Esempio n. 2
0
// get an argument by name or position
CString GetArgument (const CArgumentList & ArgumentList, 
                     CString strName, 
                     const int iPosition, 
                     const bool bLowerCase)
  {
  CArgument * pArgument;
  CArgument * pFoundArgument = NULL;
  CString strValue;

  strName.MakeLower ();   // name is not case-sensitive

  for (POSITION pos = ArgumentList.GetHeadPosition (); pos; )
    {
    pArgument = ArgumentList.GetNext (pos);

    // keywords are not, strictly speaking, arguments
    if (pArgument->bKeyword)
      continue;

    // found name?
    if (!strName.IsEmpty () && pArgument->strName == strName)
      {
      pFoundArgument = pArgument;
      break;
      }
    
    // remember position match in case no name match
    if (iPosition && pArgument->iPosition == iPosition)
      pFoundArgument = pArgument;

    }

  // if we found it, note used
  if (pFoundArgument)
    {
    // found name, take value
    strValue = pFoundArgument->strValue;
    pFoundArgument->bUsed = true;
    if (bLowerCase)
      strValue.MakeLower ();
    }

  // return value - will be empty if not found
  return strValue;
  } // end of GetArgument
Esempio n. 3
0
// get an keyword in argument list (eg. is OPEN there?)
bool GetKeyword (CArgumentList & ArgumentList, 
                     CString strName)
  {
  CArgument * pArgument;
  CString strValue;

  for (POSITION pos = ArgumentList.GetHeadPosition (); pos; )
    {
    pArgument = ArgumentList.GetNext (pos);
    // found keyword (something with no name)?
    if (pArgument->strValue.CompareNoCase (strName) == 0 && 
        pArgument->strName.IsEmpty ())
      {

      pArgument->bUsed = true;   // note it was used

      // any positional arguments after this one effectively are one lower
      // (because although we allocated it a number it doesn't deserve one)

      if (!pArgument->bKeyword)     // don't do it twice
        {
        pArgument->bKeyword = true; // note it for future reference
        while (pos)
          {
          pArgument = ArgumentList.GetNext (pos);
          if (pArgument->iPosition)
             pArgument->iPosition--;
          } // end of renumbering
        } // end of not renumbered yet

      return true;
      }
    }

  return false;
  } // end of GetKeyword
void Fitter::init(FitCalculator * c, const CArgumentList& alst,
		const FResidualList& rlst, const FParameterList& fplst,
		const CParameterList& cplst)
{
	//init calculator
	calculator = c;

	//init arguments and residuals
	CArgument arg;
	residualsList.reset(new double[rlst.size()]);
	if(!argumentsList.empty())
	{
		argumentsList.clear();
	}
	for (size_t i = 0; i < rlst.size(); i++)
	{
		//for log-fit
		/*if(rlst.at(i) > 0)
		{
			residualsList[i] = log(rlst.at(i));
		}
		else
		{
			residualsList[i] = 0.0;
		}*/
		//for lin-fit
		residualsList[i] = rlst.at(i);

		arg = alst.at(i);
		argumentsList.push_back(arg);
	}
	//init calc and fit parameters
	fitParameterList = fplst;
	calcParameterList = cplst;

	printState();
}
Esempio n. 5
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 
Esempio n. 6
0
// do the action required to open a single atomic tag (iAction)
void CMUSHclientDoc::MXP_OpenAtomicTag (const CString strTag,
                                        int iAction, 
                                        CStyle * pStyle,
                                        CString & strAction,    // new action
                                        CString & strHint,      // new hint
                                        CString & strVariable,   // new variable
                                        CArgumentList & ArgumentList)
  {
CString strArgument;
CString strArgumentName;
bool bIgnoreUnusedArgs = false; // cut down on some spam by setting this
COLORREF colour1,
         colour2;

unsigned short iFlags      = pStyle->iFlags;      
COLORREF       iForeColour = pStyle->iForeColour; 
COLORREF       iBackColour = pStyle->iBackColour; 

  // call script if required
  if (m_dispidOnMXP_OpenTag != DISPID_UNKNOWN || m_bPluginProcessesOpenTag)
    {
    // dummy-up an argument list
    CString strArgument;
    CArgument * pArgument;
    POSITION pos;

    // put the arguments into the array

    for (pos = ArgumentList.GetHeadPosition (); pos; )
      {
      pArgument = ArgumentList.GetNext (pos);
      
      // empty ones we will put there by position
      if (pArgument->strName.IsEmpty ())
        strArgument += CFormat ("'%s'",
                      (LPCTSTR) pArgument->strValue);
      else
        strArgument += CFormat ("%s='%s'",
                      (LPCTSTR) pArgument->strName,
                      (LPCTSTR) pArgument->strValue);

      if (pos)
        strArgument += " ";

      }      // end of looping through each argument

    bool bNotWanted = MXP_StartTagScript (strTag, strArgument, 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

    }


// find current foreground and background RGB values
  GetStyleRGB (pStyle, colour1, colour2);

// special processing for Pueblo
// a tag like this: <A XCH_CMD="examine #1"> 
// will convert to a SEND tag

  if (iAction == MXP_ACTION_HYPERLINK &&
      PUEBLO_ACTIVE)
    {
    strArgument = GetArgument (ArgumentList, "xch_cmd", 0, true);
    if (!strArgument.IsEmpty ())
      {
      m_bPuebloActive = true;  // for correct newline processing
      iAction = MXP_ACTION_SEND;
      }
    }    

  // now take the action 
  switch (iAction)
    {

    // temporarily make headlines the same as bold
    case MXP_ACTION_H1: 
    case MXP_ACTION_H2: 
    case MXP_ACTION_H3: 
    case MXP_ACTION_H4: 
    case MXP_ACTION_H5: 
    case MXP_ACTION_H6: 

    case MXP_ACTION_BOLD: pStyle->iFlags |= HILITE; break;
    case MXP_ACTION_UNDERLINE: pStyle->iFlags |= UNDERLINE; break;
    case MXP_ACTION_ITALIC: pStyle->iFlags |= BLINK; break;

    case MXP_ACTION_COLOR:
         {

         pStyle->iForeColour = colour1;
         pStyle->iBackColour = colour2;
         // convert to RGB colour to start with in case only FORE or BACK supplied
         pStyle->iFlags &= ~COLOURTYPE;  // clear bits, eg. custom
         pStyle->iFlags |= COLOUR_RGB;

         // foreground colour
         strArgument = GetArgument (ArgumentList, "fore", 1, true);  // get foreground colour
         if (!m_bIgnoreMXPcolourChanges)
           if (SetColour (strArgument, pStyle->iForeColour)) 
             MXP_error (DBG_ERROR, errMXP_UnknownColour,
                        TFormat ("Unknown colour: \"%s\"" ,
                                 (LPCTSTR) strArgument));

         // background colour
         strArgument = GetArgument (ArgumentList, "back", 2, true);  // get background colour
         if (!m_bIgnoreMXPcolourChanges)
           if (SetColour (strArgument, pStyle->iBackColour)) 
             MXP_error (DBG_ERROR, errMXP_UnknownColour,
                        TFormat ("Unknown colour: \"%s\"" ,
                                 (LPCTSTR) strArgument));
         }
         break;   // end of COLOR

    case MXP_ACTION_HIGH:
         {
         CColor clr;

         pStyle->iForeColour = colour1;
         pStyle->iBackColour = colour2;
         // convert to RGB colour to start with 
         pStyle->iFlags &= ~COLOURTYPE;  // clear bits, eg. custom
         pStyle->iFlags |= COLOUR_RGB;

         clr.SetColor (colour1);
         float lum = clr.GetLuminance ();
         lum += 0.15f;
         if (lum > 1.0f)
           lum = 1.0f;
         clr.SetLuminance (lum);
         pStyle->iForeColour = clr; 
         
         }
         break;   // end of COLOR

    case MXP_ACTION_SEND: 
          // send to mud hyperlink

          pStyle->iFlags &= ~ACTIONTYPE;   // cancel old actions
          if (GetKeyword (ArgumentList, "prompt"))
            pStyle->iFlags |= ACTION_PROMPT;   // prompt action
          else
            pStyle->iFlags |= ACTION_SEND;   // send-to action

          if (m_bUnderlineHyperlinks)
            pStyle->iFlags |= UNDERLINE;   // underline it

          if (m_bUseCustomLinkColour)
            {
            // find current background RGB value
            pStyle->iForeColour = m_iHyperlinkColour;    // use hyperlink colour
            pStyle->iBackColour = colour2;
            pStyle->iFlags &= ~COLOURTYPE;  // clear bits, eg. custom
            pStyle->iFlags |= COLOUR_RGB;
            }

          strArgument = GetArgument (ArgumentList,"href", 1, false);  // get link
          if (strArgument.IsEmpty ())
            strArgument = GetArgument (ArgumentList,"xch_cmd", 1, false);  // get link
            
          strAction = strArgument;   // hyperlink
         
          strArgument = GetArgument (ArgumentList, "hint", 2, false);  // get hints
          if (strArgument.IsEmpty ())
            strArgument = GetArgument (ArgumentList,"xch_hint", 2, false);  // get hint
          
          strHint = strArgument;     // hints

          break;  // end of MXP_ACTION_SEND

    case MXP_ACTION_HYPERLINK: 
          // hyperlink

          strArgument = GetArgument (ArgumentList,"href", 1, false);  // get link
          strAction = strArgument;   // hyperlink

          pStyle->iFlags &= ~ACTIONTYPE;   // cancel old actions
          pStyle->iFlags |= ACTION_HYPERLINK | UNDERLINE;   // send-to action

          if (m_bUseCustomLinkColour)
            {
            pStyle->iForeColour = m_iHyperlinkColour;    // use hyperlink colour
            pStyle->iBackColour = colour2;
            pStyle->iFlags &= ~COLOURTYPE;  // clear bits, eg. custom
            pStyle->iFlags |= COLOUR_RGB;
            }

          break;  // end of MXP_ACTION_HYPERLINK

    case MXP_ACTION_FONT:
          {
          pStyle->iForeColour = colour1;
          pStyle->iBackColour = colour2;
          // convert to RGB colour to start with in case only FORE or BACK supplied
          pStyle->iFlags &= ~COLOURTYPE;  // clear bits, eg. custom
          pStyle->iFlags |= COLOUR_RGB;

          // eg. <FONT COLOR=Red,Blink>
          CStringList list;

          strArgument = GetArgument (ArgumentList,"color", 1, true);  // get color etc.
          if (strArgument.IsEmpty () && PUEBLO_ACTIVE)
            strArgument = GetArgument (ArgumentList,"fgcolor", 1, true);  // get color
          StringToList (strArgument, ",", list);   // break into components

          for (POSITION pos = list.GetHeadPosition (); pos; )
            {
            CString strItem = list.GetNext (pos); // get action item

            if (strItem == "blink")
               pStyle->iFlags |= BLINK;
            else
            if (strItem == "italic")
               pStyle->iFlags |= BLINK;
            else
            if (strItem == "underline")
               pStyle->iFlags |= UNDERLINE;
            else
            if (strItem == "bold")
               pStyle->iFlags |= HILITE;
            else
            if (strItem == "inverse")
               pStyle->iFlags |= INVERSE;
            else
              {  // must be colour name, yes?

              // foreground colour
              if (!m_bIgnoreMXPcolourChanges)
                if (SetColour (strItem, pStyle->iForeColour)) 
                  MXP_error (DBG_ERROR, errMXP_UnknownColour,
                              TFormat ("Unknown colour: \"%s\"" ,
                                      (LPCTSTR) strItem));
              } // end of colour

            } // end of handling each item in the list
          strArgument = GetArgument (ArgumentList,"back", 2, true);  // get back color
          if (strArgument.IsEmpty () && PUEBLO_ACTIVE)
            strArgument = GetArgument (ArgumentList,"bgcolor", 2, true);  // get back color
          // background colour

          if (!m_bIgnoreMXPcolourChanges)
            if (SetColour (strArgument, pStyle->iBackColour)) 
              MXP_error (DBG_ERROR, errMXP_UnknownColour,
                        TFormat ("Unknown colour: \"%s\"" ,
                                  (LPCTSTR) strArgument));

          // get font size argument to avoid warnings about unused arguments
          strArgument = GetArgument (ArgumentList,"size", 0, true);  // get font size
          }
          break; // end of FONT

    case MXP_ACTION_VERSION:
            {

            CString strVersion = CFormat ("\x1B[1z<VERSION MXP=\"%s\" CLIENT=MUSHclient "
                      "VERSION=\"%s\" REGISTERED=YES>%s",
                     MXP_VERSION,
                     MUSHCLIENT_VERSION,
                     ENDLINE
                     );

            SendPacket (strVersion, strVersion.GetLength ());  // send version info back
            MXP_error (DBG_INFO, infoMXP_VersionSent,
                      TFormat ("Sent version response: %s" ,
                                (LPCTSTR) strVersion.Mid (4)));

            }
          break;  // end of VERSION

    case MXP_ACTION_AFK:
          if (m_bSendMXP_AFK_Response)    // if player wants us to
            {
            strArgument = GetArgument (ArgumentList,"challenge", 1, false);  // get challenge

            // find time since last player input
            CTimeSpan ts = CTime::GetCurrentTime() - m_tLastPlayerInput;
            CString strAFK = CFormat ("\x1B[1z<AFK %ld %s>%s",
                      ts.GetTotalSeconds  (),
                      (LPCTSTR) strArgument,
                      ENDLINE
                     );

            SendPacket (strAFK, strAFK.GetLength ());  // send AFK info back
            MXP_error (DBG_INFO, infoMXP_AFKSent,
                      TFormat ("Sent AFK response: %s" ,
                                (LPCTSTR) strAFK.Mid (4)));
            } // end of AFK
          break;

    case MXP_ACTION_SUPPORT:
            {
            CString strSupports;
            CAtomicElement * pElement;
            CStringList list;
            CString strName;       

            if (ArgumentList.IsEmpty ())
              {
              for (POSITION pos = App.m_ElementMap.GetStartPosition(); pos; ) 
                {                                                
                App.m_ElementMap.GetNextAssoc (pos, strName, pElement);

                if ((pElement->iFlags & TAG_NOT_IMP) == 0)
                  {
                  strSupports += "+";
                  strSupports += pElement->strName;
                  strSupports += " ";

                  // now list the sub-items it supports
                  StringToList (pElement->strArgs, ",", list);   // break into components
                  for (POSITION argpos = list.GetHeadPosition (); argpos; )
                    {
                    CString strItem = list.GetNext (argpos); // get argument item
                    strSupports += "+";
                    strSupports += pElement->strName;
                    strSupports += ".";
                    strSupports += strItem;
                    strSupports += " ";
                    } // end of doing each sub-item
                  } // end of being implemented
                }  // end of looping through all atomic elements
              } // end of wanting complete list
            else
              {
              for (POSITION pos = ArgumentList.GetHeadPosition (); pos; )
                {
                CArgument * pArgument = ArgumentList.GetNext (pos); 
                CStringList questionlist;
                StringToList (pArgument->strValue, ".", questionlist);   // break into components

                // should be one or two words, eg. send.prompt or color
                if (questionlist.GetCount () > 2)
                  {
                  MXP_error (DBG_ERROR, errMXP_InvalidSupportArgument,
                            TFormat ("Invalid <support> argument: %s" ,
                                      (LPCTSTR) pArgument->strValue));
                  return;
                  }
                
                CString strTag =  questionlist.RemoveHead ();
                strTag.MakeLower ();

                // check valid name requested
                if (!IsValidName (strTag))
                  {
                  MXP_error (DBG_ERROR, errMXP_InvalidSupportArgument,
                            TFormat ("Invalid <support> argument: %s" ,
                                      (LPCTSTR) strTag));
                  return;
                  }

                // look up main element name

                if (!App.m_ElementMap.Lookup (strTag, pElement) ||
                   (pElement->iFlags & TAG_NOT_IMP) != 0)
                  {     // not supported
                  strSupports += "-";
                  strSupports += strTag;
                  strSupports += " ";
                  continue;   // all done for this argument
                  }

                // only one word - they aren't looking for a suboption
                if (questionlist.IsEmpty ())
                  {     // supported
                  strSupports += "+";
                  strSupports += strTag;
                  strSupports += " ";
                  continue;   // all done for this argument
                  }
                  
                CString strSubtag =  questionlist.RemoveHead ();
                strSubtag.MakeLower ();

                if (strSubtag == "*")
                  {   // they want list of options for this tag
                  // now list the sub-items it supports
                  StringToList (pElement->strArgs, ",", list);   // break into components
                  for (POSITION argpos = list.GetHeadPosition (); argpos; )
                    {
                    CString strItem = list.GetNext (argpos); // get argument item
                    strSupports += "+";
                    strSupports += pElement->strName;
                    strSupports += ".";
                    strSupports += strItem;
                    strSupports += " ";
                    } // end of doing each sub-item
                  } // end of wildcard
                else
                  {  // not wildcard - must be name
                  // check valid name requested
                  if (!IsValidName (strSubtag))
                    {
                    MXP_error (DBG_ERROR, errMXP_InvalidSupportArgument,
                              TFormat ("Invalid <support> argument: %s" ,
                                        (LPCTSTR) strSubtag));
                    return;
                    }

                  // so, see if that word is in our arguments list
                  StringToList (pElement->strArgs, ",", list);   // break into components
                  if (list.Find (strSubtag))
                    {
                    strSupports += "+";
                    strSupports += pArgument->strValue;
                    strSupports += " ";
                    }
                  else
                    {
                    strSupports += "-";
                    strSupports += pArgument->strValue;
                    strSupports += " ";
                    }
                  }    // end of not looking for wildcard
                } // end of doing each argument

              } // find individual items

            CString strMessage = CFormat ("\x1B[1z<SUPPORTS %s>%s",
                                          (LPCTSTR) strSupports,
                                          ENDLINE);

            SendPacket (strMessage, strMessage.GetLength ());  // send version info back
            MXP_error (DBG_INFO, infoMXP_SupportsSent,
                      TFormat ("Sent supports response: %s" ,
                                (LPCTSTR) strMessage.Mid (4)));

            }
          bIgnoreUnusedArgs = true;

          break;  // end of MXP_ACTION_SUPPORT

    case MXP_ACTION_OPTION:
            {
            CString strOptions;
            CStringList list;
            CString strName;       

            if (ArgumentList.IsEmpty ())
              {

              for (long i = 0; OptionsTable [i].pName; i++)
                {
                char * pName = OptionsTable [i].pName;
                strOptions += CFormat ("%s=%ld ",
                               pName, 
                               (LPCTSTR) GetOptionItem (i));
                }

              } // end of wanting complete list
            else
              {
              for (POSITION pos = ArgumentList.GetHeadPosition (); pos; )
                {
                CArgument * pArgument = ArgumentList.GetNext (pos); 

                strOptions += CFormat ("%s=%ld",
                               (LPCTSTR) pArgument->strValue, 
                               (LPCTSTR) GetOption (pArgument->strValue));

                } // end of doing each argument

              } // find individual items

            CString strMessage = CFormat ("\x1B[1z<OPTIONS %s>%s",
                                          (LPCTSTR) strOptions,
                                          ENDLINE);

            SendPacket (strMessage, strMessage.GetLength ());  // send version info back
            MXP_error (DBG_INFO, infoMXP_OptionsSent,
                      TFormat ("Sent options response: %s" ,
                                (LPCTSTR) strMessage.Mid (4)));

            }
          bIgnoreUnusedArgs = true;

          break;  // end of MXP_ACTION_OPTION

    case MXP_ACTION_RECOMMEND_OPTION:
          if (m_bMudCanChangeOptions)
            {
            CString strOptions;
            CStringList list;
            CString strName;       

            for (POSITION pos = ArgumentList.GetHeadPosition (); pos; )
              {
              CArgument * pArgument = ArgumentList.GetNext (pos); 

              int iItem;
              int iResult = FindBaseOption (pArgument->strName, OptionsTable, iItem);

              if (iResult != eOK)
                MXP_error (DBG_ERROR, errMXP_InvalidOptionArgument,
                          TFormat ("Option named '%s' not known.",
                          (LPCTSTR) pArgument->strName));      
              else if (!(OptionsTable [iItem].iFlags & OPT_SERVER_CAN_WRITE))
                MXP_error (DBG_ERROR, errMXP_CannotChangeOption,
                          TFormat ("Option named '%s' cannot be changed.",
                          (LPCTSTR) pArgument->strName));      
              else
                {
                iResult = SetOptionItem (iItem, atol (pArgument->strValue), true, false);
                if (iResult == eOK)
                  MXP_error (DBG_INFO, infoMXP_OptionChanged,
                            TFormat ("Option named '%s' changed to '%s'.",
                            (LPCTSTR) pArgument->strName,
                            (LPCTSTR) pArgument->strValue)); 
                else
                  MXP_error (DBG_ERROR, errMXP_OptionOutOfRange,
                            TFormat ("Option named '%s' could not be changed to '%s' (out of range).",
                            (LPCTSTR) pArgument->strName,
                            (LPCTSTR) pArgument->strValue));      
                }

              } // end of doing each argument

            }
          bIgnoreUnusedArgs = true;

          break;  // end of MXP_ACTION_RECOMMEND_OPTION


    case MXP_ACTION_USER:
            if (!m_name.IsEmpty () && 
                m_connect_now == eConnectMXP)
              {
              CString strPacket = m_name + ENDLINE;
              SendPacket (strPacket, strPacket.GetLength ());  // send name to MUD
              MXP_error (DBG_INFO, infoMXP_CharacterNameSent,
                          TFormat ("Sent character name: %s" ,
                                  (LPCTSTR) m_name));      
              }
            else if (m_connect_now != eConnectMXP)
              MXP_error (DBG_WARNING, wrnMXP_CharacterNameRequestedButNotDefined,
                        Translate ("Character name requested but auto-connect not set to MXP."));      
            else
              MXP_error (DBG_WARNING, wrnMXP_CharacterNameRequestedButNotDefined,
                        Translate ("Character name requested but none defined."));      
            break;  // end of USER

    case MXP_ACTION_PASSWORD:
            if (m_nTotalLinesSent > 10)     // security check
              MXP_error (DBG_WARNING, wrnMXP_PasswordNotSent,
                        "Too many lines sent to MUD - password not sent.");      
            else
            if (!m_password.IsEmpty () && 
                m_connect_now == eConnectMXP)
              {
              CString strPacket = m_password + ENDLINE;
              SendPacket (strPacket, strPacket.GetLength ());  // send password to MUD
              MXP_error (DBG_INFO, infoMXP_PasswordSent,
                        "Sent password to world.");      
              }
            else if (m_connect_now != eConnectMXP)
              MXP_error (DBG_WARNING, wrnMXP_PasswordRequestedButNotDefined,
                        "Password requested but auto-connect not set to MXP.");      
            else
              MXP_error (DBG_WARNING, wrnMXP_PasswordRequestedButNotDefined,
                        "Password requested but none defined.");      
            break;  // end of PASSWORD

         // new para
    case MXP_ACTION_P:
          // experimental
          m_cLastChar = 0;
          m_bInParagraph = true;      
          break;  // end of MXP_ACTION_P
    
          // new line
    case MXP_ACTION_BR:
          bIgnoreUnusedArgs = true; // don't worry about args for now :)

          StartNewLine (true, 0);
          SetNewLineColour (0);
          break;  // end of MXP_ACTION_BR

          // reset
    case MXP_ACTION_RESET:
          MXP_Off ();
          break;  // end of MXP_ACTION_RESET

          // MXP options  (MXP OFF, MXP DEFAULT_OPEN, MXP DEFAULT_SECURE etc.
    case MXP_ACTION_MXP:
          
          if (GetKeyword (ArgumentList, "off"))
            MXP_Off (true);

          /*
          if (GetKeyword (ArgumentList, "default_open"))
            {
            MXP_error (DBG_INFO, "MXP default mode now OPEN.");
            m_iMXP_defaultMode = eMXP_open;
            }  // end of DEFAULT_OPEN

          if (GetKeyword (ArgumentList, "default_secure"))
            {
            MXP_error (DBG_INFO, "MXP default mode now SECURE.");
            m_iMXP_defaultMode = eMXP_secure;
            }  // end of DEFAULT_SECURE

          if (GetKeyword (ArgumentList, "default_locked"))
            {
            MXP_error (DBG_INFO, "MXP default mode now LOCKED.");
            m_iMXP_defaultMode = eMXP_locked;
            }  // end of DEFAULT_LOCKED


          if (GetKeyword (ArgumentList, "use_newlines"))
            {
            MXP_error (DBG_INFO, "Now interpreting newlines as normal.");
            m_bInParagraph = false;      
            }   // end of USE_NEWLINES

          if (GetKeyword (ArgumentList, "ignore_newlines"))
            {
            MXP_error (DBG_INFO, "Now ignoring newlines.");
            m_bInParagraph = true;      
            }   // end of IGNORE_NEWLINES

          */

          break;  // end of MXP_ACTION_MXP

    case MXP_ACTION_SCRIPT:
          MXP_error (DBG_INFO, infoMXP_ScriptCollectionStarted,
                      "Script collection mode entered (discarding script).");
          m_bMXP_script = true;
          break;  // end of MXP_ACTION_SCRIPT

    case MXP_ACTION_HR: 

          {
          // wrap up previous line if necessary
          if (m_pCurrentLine->len > 0)
             StartNewLine (true, 0);

          /*
          CString strLine;
          char * p = strLine.GetBuffer (m_nWrapColumn);
          memset (p, 175, m_nWrapColumn);
          strLine.ReleaseBuffer (m_nWrapColumn);
          AddToLine (strLine, 0);
          */
          // mark line as HR line
          m_pCurrentLine->flags = HORIZ_RULE;
          
          StartNewLine (true, 0); // now finish this line
          }
          break;  // end of MXP_ACTION_HR

    case MXP_ACTION_PRE: 
          m_bPreMode = true;
          break;  // end of MXP_ACTION_PRE

     case MXP_ACTION_UL:   
          m_iListMode = eUnorderedList;
          m_iListCount = 0;
          break;  // end of MXP_ACTION_UL
     case MXP_ACTION_OL:   
          m_iListMode = eOrderedList;
          m_iListCount = 0;
          break;  // end of MXP_ACTION_OL
     case MXP_ACTION_LI:   
         {
          // wrap up previous line if necessary
          if (m_pCurrentLine->len > 0)
             StartNewLine (true, 0);
          CString strListItem = " * ";
          if (m_iListMode == eOrderedList)
            strListItem.Format (" %i. ", ++m_iListCount);
          AddToLine (strListItem, 0);
          }
          break;  // end of MXP_ACTION_LI

    // pueblo tags we put here so we don't get warnings

      case MXP_ACTION_BODY : bIgnoreUnusedArgs = true; break; // just ignore it
      case MXP_ACTION_HEAD : bIgnoreUnusedArgs = true; break; // just ignore it
      case MXP_ACTION_HTML : bIgnoreUnusedArgs = true; break; // just ignore it
      case MXP_ACTION_TITLE: bIgnoreUnusedArgs = true; break; // just ignore it
      case MXP_ACTION_SAMP : bIgnoreUnusedArgs = true; break; // just ignore it
      case MXP_ACTION_CENTER : bIgnoreUnusedArgs = true; break; // just ignore it
      case MXP_ACTION_XCH_PANE : bIgnoreUnusedArgs = true; break; // just ignore it

      case MXP_ACTION_IMG  : 
      case MXP_ACTION_IMAGE:

        {
          GetKeyword (ArgumentList, "ismap"); // make sure we realise it is a keyword

          // detect newline treatment
          strArgument = GetArgument (ArgumentList,"xch_mode", 0, false);  // get mode
          if (!strArgument.IsEmpty ())
            {
            m_bPuebloActive = true;  // for correct newline processing
            if (strArgument.CompareNoCase ("purehtml") == 0)
               m_bSuppressNewline = true;
            else
            if (strArgument.CompareNoCase ("html") == 0)
               m_bSuppressNewline = false;
            } // end of some sort of Pueblo

          strArgument = GetArgument (ArgumentList,"url", 0, false);  // get link
          if (strArgument.IsEmpty () && PUEBLO_ACTIVE)   
            strArgument = GetArgument (ArgumentList,"src", 0, false);  // get link

          CString strFilename = GetArgument (ArgumentList,"fname", 0, false); // and file name

          if (!strArgument.IsEmpty ())
            {

            CString strOldAction = strAction;
            int iFlags = pStyle->iFlags;
            COLORREF iForeColour = pStyle->iForeColour;
            COLORREF iBackColour = pStyle->iBackColour;

            // ensure on new line
            if (m_pCurrentLine->len > 0)
               StartNewLine (true, 0);

            // starting a new line may have deleted pStyle

            pStyle = m_pCurrentLine->styleList.GetTail ();

            if (m_bUseCustomLinkColour)
              {
              pStyle->iForeColour = m_iHyperlinkColour;    // use hyperlink colour
              pStyle->iBackColour = colour2;
              pStyle->iFlags &= ~COLOURTYPE;  // clear bits, eg. custom
              pStyle->iFlags |= COLOUR_RGB;
              }

            strArgument += strFilename;   // append filename to URL
            strAction = strArgument;   // hyperlink
            pStyle->iFlags &= ~ACTIONTYPE;   // cancel old actions
            pStyle->iFlags |= ACTION_HYPERLINK;   // send-to action

            if (m_bUnderlineHyperlinks)
              pStyle->iFlags |= UNDERLINE;   // send-to action

            AddToLine ("[", 0);          
            AddToLine (strArgument, 0);
            AddToLine ("]", 0);

            // have to add the action now, before we start a new line
            pStyle->pAction = GetAction (strAction, strHint, strVariable);
            strAction.Empty ();

            StartNewLine (true, 0);   // new line after image tag
            // go back to old style (ie. lose the underlining)
            AddStyle (iFlags, 
                     iForeColour, 
                     iBackColour, 
                     0, 
                     strOldAction);

            }
        }
        break; // end of MXP_ACTION_IMG

    case MXP_ACTION_XCH_PAGE:
         bIgnoreUnusedArgs = true;
         m_bPuebloActive = true;  // for correct newline processing
         MXP_Off ();    // same as <reset>?
      break;  // end of MXP_ACTION_XCH_PAGE

    case MXP_ACTION_VAR: 
          // set variable

          strVariable = GetArgument (ArgumentList,"", 1, false);  // get name

          // case insensitive
          strVariable.MakeLower ();

          if (!IsValidName (strVariable))
            {
            MXP_error (DBG_ERROR, errMXP_InvalidDefinition,
                      TFormat ("Invalid MXP entity name: <!%s>", 
                      (LPCTSTR) strVariable)); 
            strVariable.Empty ();
            return;
            }

            { // protect local variable
            CString strEntityContents;

            if (App.m_EntityMap.Lookup (strVariable, strEntityContents))
              {
              MXP_error (DBG_ERROR, errMXP_CannotRedefineEntity,
                        TFormat ("Cannot redefine entity: &%s;", 
                        (LPCTSTR) strVariable)); 
              strVariable.Empty ();
              return;
              }
              }

          break;  // end of MXP_ACTION_VAR


    default:
          {
          // warn them it is not implemented
          MXP_error (DBG_WARNING, wrnMXP_TagNotImplemented,
                     TFormat ("MXP tag <%s> is not implemented" ,
                             (LPCTSTR) strTag));
          }   // end of default

    } // end of switch on iAction

  if (!bIgnoreUnusedArgs)
    CheckArgumentsUsed (strTag, ArgumentList);

  } // end of CMUSHclientDoc::MXP_OpenAtomicTag
Esempio n. 7
0
bool CMUSHclientDoc::MXP_StartTagScript  (const CString & strName, 
                     const CString & strArguments,
                     CArgumentList & ArgumentList)
  {

  // don't make it too easy to dummy up AFK replies
  if (strName == "afk")
    return false;

  if (!SendToAllPluginCallbacks (ON_PLUGIN_MXP_OPENTAG, 
                                CFormat ("%s,%s",
                                (LPCTSTR) strName,
                                (LPCTSTR) strArguments)
                                ), true)
      return true;    


  // see if main script wants to do anything
  if (m_dispidOnMXP_OpenTag == DISPID_UNKNOWN)
    return false;

  long nInvocationCount = 0;
  long iCount = ArgumentList.GetCount ();

  CString strType = "MXP open tag";
  CString strReason =  TFormat ("opening MXP tag %s", (LPCTSTR) strName);

  if (GetScriptEngine () && GetScriptEngine ()->IsLua ())
    {
    list<double> nparams;
    list<string> sparams;
    sparams.push_back ((LPCTSTR) strName);    // name of tag
    sparams.push_back ((LPCTSTR) strArguments);  // all arguments

    map <string, string> table;

    CArgument * pArgument;
    POSITION pos;

    // put the arguments into the table

    for (iCount = 0, pos = ArgumentList.GetHeadPosition (); pos; iCount++)
      {
      pArgument = ArgumentList.GetNext (pos);
      CString strName = pArgument->strName;

      // empty ones we will put there by position
      if (strName.IsEmpty ())
        strName = CFormat ("%i",
                      pArgument->iPosition);
      
      table [(LPCTSTR) strName] = pArgument->strValue;
      }      // end of looping through each argument

    bool result;
    GetScriptEngine ()->ExecuteLua (m_dispidOnMXP_OpenTag, 
                                   m_strOnMXP_OpenTag, 
                                   eWorldAction,
                                   strType, 
                                   strReason, 
                                   nparams,
                                   sparams, 
                                   nInvocationCount,
                                   NULL,
                                   &table,
                                   NULL,
                                   &result);
    return result;
    }   // end of Lua

  COleSafeArray sa;   // for wildcard list

  if (iCount) // cannot create empty array dimension
    {
    sa.CreateOneDim (VT_VARIANT, iCount);

    CArgument * pArgument;
    POSITION pos;

    // put the arguments into the array

    for (iCount = 0, pos = ArgumentList.GetHeadPosition (); pos; iCount++)
      {
      pArgument = ArgumentList.GetNext (pos);

      // the array must be a bloody array of variants, or VBscript kicks up
      COleVariant v;
      
      // empty ones we will put there by position
      if (pArgument->strName.IsEmpty ())
        v = CFormat ("%i=%s",
                      pArgument->iPosition,
                      (LPCTSTR) pArgument->strValue);
      else
        v = CFormat ("%s=%s",
                      (LPCTSTR) pArgument->strName,
                      (LPCTSTR) pArgument->strValue);
      sa.PutElement (&iCount, &v);
      }      // end of looping through each argument
    } // end of having at least one

  // WARNING - arguments should appear in REVERSE order to what the sub expects them!

  enum
    {
    eArgumentArray,
    eArguments,
    eTagName,
    eArgCount,     // this MUST be last
    };    

  COleVariant args [eArgCount];
  DISPPARAMS params = { args, NULL, eArgCount, 0 };

  args [eTagName] = strName;
  args [eArguments] = strArguments;
  args [eArgumentArray] = sa;

  COleVariant result;

  ExecuteScript (m_dispidOnMXP_OpenTag,  
                 m_strOnMXP_OpenTag,
                 eWorldAction,
                 strType, 
                 strReason,
                 params, 
                 nInvocationCount,
                 &result); 

  // if the function returns a non-zero result, don't go ahead
  if (result.vt != VT_EMPTY)
    {
    result.ChangeType (VT_I4);  // make a long
    if (result.vt == VT_I4)   // conversion successful
      if (result.lVal)        // return if non-zero
        return true;
    }

  return false;
  } // end of CMUSHclientDoc::MXP_StartTagScript 
Esempio n. 8
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