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
void CMUSHclientDoc::MXP_collected_entity (void) { m_strMXPstring.TrimLeft (); m_strMXPstring.TrimRight (); // case insensitive // m_strMXPstring.MakeLower (); // count them m_iMXPentities++; // TRACE1 ("MXP collected entity %s\n", (LPCTSTR) m_strMXPstring); MXP_error (DBG_ALL, msgMXP_CollectedEntity, TFormat ("MXP entity: &%s;", (LPCTSTR) m_strMXPstring)); if (!IsValidName (m_strMXPstring) && m_strMXPstring.Left (1) != "#") { MXP_error (DBG_ERROR, errMXP_InvalidEntityName, TFormat ("Invalid MXP entity name \"%s\" supplied.", m_strMXPstring)); return; } // see if we know of this entity CString strEntityContents = MXP_GetEntity (m_strMXPstring); if (!strEntityContents.IsEmpty ()) AddToLine (strEntityContents, 0); } // end of CMUSHclientDoc::MXP_collected_entity
// 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
bool CheckRegularExpression (const CString strRegexp, const int iOptions) { const char *error; int erroroffset; pcre * program; program = pcre_compile(strRegexp, iOptions, &error, &erroroffset, NULL); if (program) { pcre_free (program); return true; // good } CRegexpProblemDlg dlg; dlg.m_strErrorMessage = Translate (error); dlg.m_strErrorMessage += "."; // end the sentence // make first character upper-case, so it looks like a sentence. :) dlg.m_strErrorMessage.SetAt (0, toupper (dlg.m_strErrorMessage [0])); dlg.m_strColumn = TFormat ("Error occurred at column %i.", erroroffset + 1); dlg.m_strText = strRegexp; dlg.m_strText += ENDLINE; if (erroroffset > 0) dlg.m_strText += CString ('-', erroroffset - 1); dlg.m_strText += '^'; dlg.m_iColumn = erroroffset + 1; dlg.DoModal (); return false; // bad }
BOOL CChatListDlg::OnInitDialog() { CDialog::OnInitDialog(); // update window title SetWindowText (TFormat ("Chat sessions for %s", m_pDoc->m_mush_name)); int iColOrder [eColumnChatCount] = {0, 1, 2, 3, 4, 5}, iColWidth [eColumnChatCount] = {90, 66, 81, 81, 55, 50}; // set list control to display whole row when selected and to allow column drag/drop App.RestoreColumnConfiguration ("Chat List", eColumnChatCount, m_ctlChatList, iColOrder, iColWidth, m_last_col, m_reverse); m_ctlChatList.InsertColumn(eColumnChatName, TranslateHeading ("Name"), LVCFMT_LEFT, iColWidth [eColumnChatName]); m_ctlChatList.InsertColumn(eColumnGroup, TranslateHeading ("Group"), LVCFMT_LEFT, iColWidth [eColumnGroup]); m_ctlChatList.InsertColumn(eColumnFromIP, TranslateHeading ("From IP"), LVCFMT_LEFT, iColWidth [eColumnFromIP]); m_ctlChatList.InsertColumn(eColumnCallIP, TranslateHeading ("Call IP"), LVCFMT_LEFT, iColWidth [eColumnCallIP]); m_ctlChatList.InsertColumn(eColumnCallPort, TranslateHeading ("Call Port"), LVCFMT_LEFT, iColWidth [eColumnCallPort]); m_ctlChatList.InsertColumn(eColumnFlags, TranslateHeading ("Flags"), LVCFMT_LEFT, iColWidth [eColumnFlags]); // recover column sequence m_ctlChatList.SendMessage (LVM_SETCOLUMNORDERARRAY, eColumnChatCount, (DWORD) iColOrder); // the update handler will auto-refresh the list ;) return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
void CMultiLineTriggerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMultiLineTriggerDlg) DDX_Control(pDX, IDC_TRIGGER_TEXT, m_ctlTriggerText); DDX_Text(pDX, IDC_TRIGGER_TEXT, m_strTriggerText); DDX_Check(pDX, IDC_MATCH_CASE, m_bMatchCase); //}}AFX_DATA_MAP if(pDX->m_bSaveAndValidate) { // can't make an empty trigger if (m_strTriggerText.IsEmpty ()) { ::TMessageBox("The trigger match text cannot be empty.", MB_ICONSTOP); DDX_Text(pDX, IDC_TRIGGER_TEXT, m_strTriggerText); pDX->Fail(); } // end of text being blank int iCount = 1; const char * p; for (p = m_strTriggerText; *p; p++) if (*p == '\n') iCount++; if (iCount < 1) { ::TMessageBox("Multi-line triggers must match at least 2 lines.", MB_ICONSTOP); DDX_Text(pDX, IDC_TRIGGER_TEXT, m_strTriggerText); pDX->Fail(); } // end of text being blank if (iCount > MAX_RECENT_LINES) { ::UMessageBox( TFormat ("Multi-line triggers can match a maximum of %i lines.", MAX_RECENT_LINES), MB_ICONSTOP); DDX_Text(pDX, IDC_TRIGGER_TEXT, m_strTriggerText); pDX->Fail(); } // end of text being blank CString strText = ::Replace (m_strTriggerText, ENDLINE, "\\n"); // check they haven't put crap into the regular expression if (!CheckRegularExpression (strText, PCRE_MULTILINE)) { // failed check DDX_Text(pDX, IDC_TRIGGER_TEXT, m_strTriggerText); pDX->Fail(); } } // end of save and validate else FixFont (m_font, m_ctlTriggerText, "Courier New", 9, FW_NORMAL, DEFAULT_CHARSET); }
void CMUSHclientDoc::MXP_collected_entity (void) { m_strMXPstring.TrimLeft (); m_strMXPstring.TrimRight (); // case insensitive // m_strMXPstring.MakeLower (); // count them m_iMXPentities++; // TRACE1 ("MXP collected entity %s\n", (LPCTSTR) m_strMXPstring); MXP_error (DBG_ALL, msgMXP_CollectedEntity, TFormat ("MXP entity: &%s;", (LPCTSTR) m_strMXPstring)); if (!IsValidName (m_strMXPstring) && m_strMXPstring.Left (1) != "#") { MXP_error (DBG_ERROR, errMXP_InvalidEntityName, TFormat ("Invalid MXP entity name \"%s\" supplied.", m_strMXPstring)); return; } // see if we know of this entity CString strEntityContents = MXP_GetEntity (m_strMXPstring); if (!strEntityContents.IsEmpty ()) { // if the entity happens to be < & > etc. don't reprocess it m_bMXP = false; DisplayMsg (strEntityContents, strEntityContents.GetLength (), 0); m_bMXP = true; } } // end of CMUSHclientDoc::MXP_collected_entity
bool NotFound (CFindInfo & FindInfo) { WrapUpFind (FindInfo); CString strMsg; CString strFindType = "text"; if (FindInfo.m_bRegexp) strFindType = "regular expression"; strMsg = TFormat ("The %s \"%s\" was not found%s", (LPCTSTR) strFindType, (LPCTSTR) FindInfo.m_strFindStringList.GetHead (), FindInfo.m_bAgain ? " again." : " ."); ::UMessageBox (strMsg, MB_ICONINFORMATION); FindInfo.m_iStartColumn = -1; return false; } // end of NotFound
// here at an unexpected termination of element collection, eg. <blah \n void CMUSHclientDoc::MXP_unterminated_element (const char * pReason) { char * p = "thing"; int i = errMXP_Unknown; switch (m_phase) { case HAVE_MXP_ELEMENT: p = "element"; i = errMXP_UnterminatedElement; break; case HAVE_MXP_COMMENT: p = "comment"; i = errMXP_UnterminatedComment; break; case HAVE_MXP_ENTITY: p = "entity"; i = errMXP_UnterminatedEntity; break; case HAVE_MXP_QUOTE: p = "quote"; i = errMXP_UnterminatedQuote; break; } // end of switch MXP_error (DBG_ERROR, i, // error level TFormat ("Unterminated MXP %s: %s (%s)", (LPCTSTR) p, (LPCTSTR) m_strMXPstring, pReason)); } // end of CMUSHclientDoc::MXP_unterminated_element
void CGoToLineDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CGoToLineDlg) DDX_Text(pDX, IDC_LINE_NUMBER, m_iLineNumber); //}}AFX_DATA_MAP if(pDX->m_bSaveAndValidate) { if (m_iLineNumber < 1 || m_iLineNumber > m_iMaxLine) { CString strMessage; strMessage = TFormat ("Line number must be in range 1 to %i", m_iMaxLine); ::UMessageBox(strMessage); DDX_Text(pDX, IDC_LINE_NUMBER, m_iLineNumber); pDX->Fail(); } } // end of saving and validating }
// returns true if error bool CScriptEngine::Execute (DISPID & dispid, // dispatch ID, will be set to DISPID_UNKNOWN on an error LPCTSTR szProcedure, // eg. ON_TRIGGER_XYZ const unsigned short iReason, // value for m_iCurrentActionSource LPCTSTR szType, // eg. trigger, alias LPCTSTR szReason, // eg. trigger subroutine XXX DISPPARAMS & params, // parameters long & nInvocationCount, // count of invocations COleVariant * result // result of call ) { // If Lua, we may have been called with no arguments, so just do that if (L) { list<double> nparams; list<string> sparams; bool r; bool status = ExecuteLua (dispid, szProcedure, iReason, szType, szReason, nparams, sparams, nInvocationCount, NULL, NULL, NULL, &r); if (result) { result->vt = VT_BOOL; result->boolVal = r; } return status; } // have Lua // don't do it if no routine address if (dispid == DISPID_UNKNOWN) return false; strProcedure = szProcedure; strType = szType; strReason = szReason; bImmediate = false; unsigned short iOldStyle = m_pDoc->m_iNoteStyle; m_pDoc->m_iNoteStyle = NORMAL; // back to default style HRESULT hr; EXCEPINFO ExcepInfo; unsigned int ArgErr; LARGE_INTEGER start, finish; SCRIPTSTATE ss; m_pDoc->Trace (TFormat ("Executing %s script \"%s\"", szType, szProcedure)); // Frame.SetStatusMessageNow (TFormat ("Executing %s subroutine \"%s\"", szType, szProcedure)); if (m_IActiveScript) { // new for Python - an error may have caused the script state to change hr = m_IActiveScript->GetScriptState (&ss); if (hr == S_OK) { // try to put it back to connected if (ss != SCRIPTSTATE_CONNECTED) hr = m_IActiveScript->SetScriptState (SCRIPTSTATE_CONNECTED); } if (hr != S_OK) { ::UMessageBox (TFormat ("Script engine problem invoking subroutine \"%s\" when %s", (LPCTSTR) szProcedure, (LPCTSTR) szReason)); strProcedure.Empty (); strType.Empty (); strReason.Empty (); bImmediate = true; m_pDoc->m_iNoteStyle = iOldStyle; return true; } } // end of having script engine if (App.m_iCounterFrequency) QueryPerformanceCounter (&start); else { start.QuadPart = 0; finish.QuadPart = 0; } if (iReason != eDontChangeAction) m_pDoc->m_iCurrentActionSource = iReason; hr = m_pDispatch->Invoke (dispid, IID_NULL, 0, DISPATCH_METHOD, ¶ms, result, &ExcepInfo, &ArgErr); if (iReason != eDontChangeAction) m_pDoc->m_iCurrentActionSource = eUnknownActionSource; if (hr == S_OK && App.m_iCounterFrequency) { QueryPerformanceCounter (&finish); m_pDoc->m_iScriptTimeTaken += finish.QuadPart - start.QuadPart; if (m_pDoc->m_CurrentPlugin) m_pDoc->m_CurrentPlugin->m_iScriptTimeTaken += finish.QuadPart - start.QuadPart; } // put status line back // ShowStatusLine (); if (hr == S_OK) nInvocationCount++; // count number of times used else { dispid = DISPID_UNKNOWN; // stop further invocations if (hr == 0x800a01c2) // wrong number of arguments ::UMessageBox (TFormat ("Wrong number of arguments for script subroutine \"%s\" when %s" "\n\nWe expected your subroutine to have %i argument%s", (LPCTSTR) szProcedure, (LPCTSTR) szReason, PLURAL (params.cArgs))); else ::UMessageBox (TFormat ("Unable to invoke script subroutine \"%s\" when %s", (LPCTSTR) szProcedure, (LPCTSTR) szReason)); } // end of bad invoke strProcedure.Empty (); strType.Empty (); strReason.Empty (); bImmediate = true; m_pDoc->m_iNoteStyle = iOldStyle; return hr != S_OK; // true on error } // end of CScriptEngine::ExecuteScript
// 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
void CGenPropertyPage::OnAddItem(CDialog & dlg) { // load dialog with default values InitDialog (&dlg); // display dialog, exit if cancelled if (dlg.DoModal () != IDOK) return; // create the object's lookup name (label converted to lower case, or generated) CObject * pItem; CString strObjectName; strObjectName = GetObjectName (&dlg); if (strObjectName.IsEmpty ()) strObjectName.Format ("*%s%s", // e.g. *trigger100 (LPCTSTR) m_strObjectType, (LPCTSTR) App.GetUniqueString ()); else strObjectName.MakeLower(); // if already there (presumably not possible with un-named objects), // then abort the add if (m_ObjectMap->Lookup (strObjectName, pItem)) { CString strMsg; strMsg = TFormat ("The %s named \"%s\" is already in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) GetObjectName (&dlg), (LPCTSTR) m_strObjectType); ::UMessageBox (strMsg); return; } // add new object to map m_ObjectMap->SetAt (strObjectName, pItem = MakeNewObject ()); // unload from dialog into object's properties UnloadDialog (&dlg, pItem); // They can no longer cancel the property sheet, the document has changed CancelToClose (); if (!CheckIfTemporary (pItem)) m_doc->SetModifiedFlag (TRUE); // create a CString for lookup purposes CString * pstrObjectName = new CString (strObjectName); // add this item to the list view add_item (pItem, pstrObjectName, 0, TRUE); SetInternalName (pItem, strObjectName); // set name so we can delete one-shot items // resort the list t_gen_sort_param sort_param (m_ObjectMap, m_last_col, m_reverse, m_CompareObjects); m_ctlList->SortItems (CompareFunc, (LPARAM) &sort_param); // redraw the list if (GetFilterFlag ()) LoadList (); // full reload because it may have changed filter requirements // get dispatch id from the script and put it into the item if (m_doc->m_ScriptEngine) { CString strMessage; SetDispatchID (pItem, m_doc->GetProcedureDispid (GetScriptName (pItem), m_strObjectType, GetLabel (pItem), strMessage)); if (!strMessage.IsEmpty ()) ::UMessageBox (strMessage, MB_ICONINFORMATION); } } // end of CGenPropertyPage::OnAddItem
void CAliasDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); if(!pDX->m_bSaveAndValidate) { if (m_current_alias && m_current_alias->bIncluded) m_strIncluded = "(included)"; else m_strIncluded.Empty (); } //{{AFX_DATA_MAP(CAliasDlg) DDX_Control(pDX, IDC_SEND_TO, m_ctlSendTo); DDX_Control(pDX, IDC_VARIABLE, m_ctlVariable); DDX_Control(pDX, IDC_REGEXP, m_ctlRegexp); DDX_Control(pDX, IDC_ALIAS_CONTENTS, m_ctlAliasContents); DDX_Control(pDX, IDC_ALIAS_NAME, m_ctlAliasName); DDX_Text(pDX, IDC_ALIAS_CONTENTS, m_contents); DDX_Text(pDX, IDC_ALIAS_NAME, m_name); DDX_Text(pDX, IDC_ALIAS_LABEL, m_strLabel); DDX_Check(pDX, IDC_ENABLED, m_bEnabled); DDX_Text(pDX, IDC_SCRIPT_NAME, m_strProcedure); DDX_Check(pDX, IDC_IGNORE_CASE, m_bIgnoreCase); DDX_Check(pDX, IDC_EXPAND_VARIABLES, m_bExpandVariables); DDX_Check(pDX, IDC_OMIT_FROM_LOG, m_bOmitFromLogFile); DDX_Check(pDX, IDC_REGEXP, m_bRegexp); DDX_Check(pDX, IDC_OMIT_FROM_OUTPUT, m_bOmitFromOutput); DDX_Check(pDX, IDC_ALIAS_MENU, m_bMenu); DDX_Check(pDX, IDC_TEMPORARY_ALIAS, m_bTemporary); DDX_Text(pDX, IDC_GROUP, m_strGroup); DDX_Text(pDX, IDC_VARIABLE, m_strVariable); DDX_CBIndex(pDX, IDC_SEND_TO, m_iSendTo); DDX_Check(pDX, IDC_KEEP_EVALUATING, m_bKeepEvaluating); DDX_Text(pDX, IDC_SEQUENCE, m_iSequence); DDV_MinMaxInt(pDX, m_iSequence, 0, 10000); DDX_Check(pDX, IDC_ECHO_ALIAS, m_bEchoAlias); DDX_Check(pDX, IDC_OMIT_FROM_COMMAND_HISTORY, m_bOmitFromCommandHistory); DDX_Text(pDX, IDC_INCLUDED, m_strIncluded); DDX_Text(pDX, IDC_REGEXP_ERROR, m_strRegexpError); DDX_Check(pDX, IDC_ONE_SHOT, m_bOneShot); //}}AFX_DATA_MAP if(pDX->m_bSaveAndValidate) { POSITION pos; CAlias * alias_item; m_strLabel.TrimLeft (); m_strLabel.TrimRight (); m_strProcedure.TrimLeft (); m_strProcedure.TrimRight (); m_strGroup.TrimLeft (); m_strGroup.TrimRight (); m_strVariable.TrimLeft (); m_strVariable.TrimRight (); if (m_name.IsEmpty ()) { ::TMessageBox("The alias cannot be blank."); DDX_Text(pDX, IDC_ALIAS_NAME, m_name); pDX->Fail(); } // end of alias being blank // check for foolishly using ** in a non-regular expression if (m_name.Find ("**") != -1 && !m_bRegexp) { CCreditsDlg dlg; dlg.m_iResourceID = IDR_MULTIPLE_ASTERISKS; dlg.m_strTitle = "Warning"; dlg.DoModal (); DDX_Text(pDX, IDC_ALIAS_NAME, m_name); pDX->Fail(); } int iInvalidPos = m_name.FindOneOf ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"); if (iInvalidPos != -1) { char c = m_name [iInvalidPos]; ::UMessageBox(TFormat ( "The alias 'match' text contains an invalid non-printable character (hex %02X) at position %i.", c, iInvalidPos + 1), MB_ICONSTOP); DDX_Text(pDX, IDC_ALIAS_NAME, m_name); pDX->Fail(); } // end of alias match having weird characters in it // we allow carriage-return, linefeed, tab here iInvalidPos = m_contents.FindOneOf ("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F"); if (iInvalidPos != -1) { char c = m_contents [iInvalidPos]; ::UMessageBox(TFormat ( "The alias 'send' text contains an invalid non-printable character (hex %02X) at position %i.", c, iInvalidPos + 1), MB_ICONSTOP); DDX_Text(pDX, IDC_ALIAS_CONTENTS, m_contents); pDX->Fail(); } // end of alias send having weird characters in it // compile regular expression to check it if (m_bRegexp) { if (!CheckRegularExpression (m_name, (m_bIgnoreCase ? 0 : PCRE_CASELESS) | (m_pDoc->m_bUTF_8 ? PCRE_UTF8 : 0) #if ALIASES_USE_UTF8 | (m_pDoc->m_bUTF_8 ? PCRE_UTF8 : 0) #endif // ALIASES_USE_UTF8 )) { // failed check DDX_Text(pDX, IDC_ALIAS_NAME, m_name); pDX->Fail(); } } // end of checking regular expression CString strAliasName; for (pos = m_pAliasMap->GetStartPosition (); pos; ) { m_pAliasMap->GetNextAssoc (pos, strAliasName, alias_item); // don't compare against itself if (alias_item == m_current_alias) continue; /* bool bDuplicate = false; // if either one is case-insensitive, compare insensitive if ((alias_item->bIgnoreCase || m_bIgnoreCase) && alias_item->name.CompareNoCase (m_name) == 0) bDuplicate = true; // if both are case-sensitive, compare exactly else if (alias_item->name == m_name) bDuplicate = true; // we won't consider it a match if they send to different places if (alias_item->iSendTo != m_iSendTo) bDuplicate = false; if (bDuplicate) { ::TMessageBox("This alias is already in the list of aliases."); DDX_Text(pDX, IDC_ALIAS_NAME, m_name); pDX->Fail(); } */ // now check the label for duplicates if (!m_strLabel.IsEmpty ()) // we can have duplicate blank names if (m_strLabel.CompareNoCase (alias_item->strLabel) == 0) { CString strMsg; strMsg = TFormat ("The alias label \"%s\" is already in the list of aliases.", (LPCTSTR) m_strLabel); ::UMessageBox(strMsg); DDX_Text(pDX, IDC_ALIAS_LABEL, m_strLabel); pDX->Fail(); } } // end of checking each alias if (!m_strLabel.IsEmpty ()) // we can have blank labels { // check label is valid if (CheckLabel (m_strLabel)) { ::TMessageBox("The label must start with a letter and consist of letters" ", numbers or the underscore character."); DDX_Text(pDX, IDC_ALIAS_LABEL, m_strLabel); pDX->Fail(); } } // end of having non-blank label if (m_strVariable.IsEmpty ()) // we can have blank variables { if (m_iSendTo == eSendToVariable) { ::TMessageBox("When sending to a variable you must specify a variable name. ", MB_ICONSTOP); DDX_Text(pDX, IDC_VARIABLE, m_strVariable); pDX->Fail(); } } else { // check variable name is valid if (CheckLabel (m_strVariable)) { ::TMessageBox("The variable name must start with a letter and consist of letters" ", numbers or the underscore character."); DDX_Text(pDX, IDC_VARIABLE, m_strVariable); pDX->Fail(); } } // end of having non-blank variable // check for speed walking OK, unless they are substituting if (!m_bExpandVariables || m_contents.Find ('@') == -1) if (m_iSendTo == eSendToSpeedwalk && m_contents.Find ('%') == -1) { CString strResult = m_pDoc->DoEvaluateSpeedwalk (m_contents); if (!strResult.IsEmpty ()) { if (strResult [0] == '*') // error in speedwalk string? { ::UMessageBox (strResult.Mid (1)); DDX_Text(pDX, IDC_ALIAS_CONTENTS, m_contents); pDX->Fail(); } // end of error message } // end of non-empty speedwalk } // end of speed walking wanted if(m_contents.IsEmpty () && m_strProcedure.IsEmpty ()) { ::TMessageBox("The alias contents cannot be blank unless you specify a script subroutine."); DDX_Text(pDX, IDC_ALIAS_CONTENTS, m_contents); pDX->Fail(); } // end of contents being blank if (!m_strProcedure.IsEmpty ()) // blank procedure is OK { // check procedure is valid if (CheckLabel (m_strProcedure, true)) { ::TMessageBox("The script subroutine name must start with a letter and consist of letters" ", numbers or the underscore character."); DDX_Text(pDX, IDC_SCRIPT_NAME, m_strProcedure); pDX->Fail(); } } // end of having non-blank procedure } // end of saving and validating else if (App.m_bFixedFontForEditing) { FixFont (m_font, m_ctlAliasName, App.m_strFixedPitchFont, App.m_iFixedPitchFontSize, FW_NORMAL, DEFAULT_CHARSET); FixFont (m_font2, m_ctlAliasContents, App.m_strFixedPitchFont, App.m_iFixedPitchFontSize, FW_NORMAL, DEFAULT_CHARSET); } }
void CTimerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); if(!pDX->m_bSaveAndValidate) { if (m_current_timer && m_current_timer->bIncluded) m_strIncluded = "(included)"; else m_strIncluded.Empty (); } //{{AFX_DATA_MAP(CTimerDlg) DDX_Control(pDX, IDC_SEND_TO, m_ctlSendTo); DDX_Control(pDX, IDC_SCRIPT_NAME, m_ctlProcedure); DDX_Control(pDX, IDC_TIMER_CONTENTS, m_ctlContents); DDX_Control(pDX, IDC_BUTTON_AT, m_ctlButtonAt); DDX_Check(pDX, IDC_ENABLED, m_bEnabled); DDX_Text(pDX, IDC_TIMER_LABEL, m_strLabel); DDX_Text(pDX, IDC_AT_HOUR, m_iAtHour); DDV_MinMaxInt(pDX, m_iAtHour, 0, 23); DDX_Text(pDX, IDC_AT_MINUTE, m_iAtMinute); DDV_MinMaxInt(pDX, m_iAtMinute, 0, 59); DDX_Text(pDX, IDC_INTERVAL_HOUR, m_iEveryHour); DDV_MinMaxInt(pDX, m_iEveryHour, 0, 23); DDX_Text(pDX, IDC_INTERVAL_MINUTE, m_iEveryMinute); DDV_MinMaxInt(pDX, m_iEveryMinute, 0, 59); DDX_Text(pDX, IDC_OFFSET_HOUR, m_iOffsetHour); DDV_MinMaxInt(pDX, m_iOffsetHour, 0, 23); DDX_Text(pDX, IDC_OFFSET_MINUTE, m_iOffsetMinute); DDV_MinMaxInt(pDX, m_iOffsetMinute, 0, 59); DDX_MinMaxString(pDX, IDC_TIMER_CONTENTS, m_strContents); DDV_MinMaxString(pDX, m_strContents, 0, 32000); DDX_Radio(pDX, IDC_BUTTON_EVERY, m_iType); DDX_Text(pDX, IDC_SCRIPT_NAME, m_strProcedure); DDX_Check(pDX, IDC_ONE_SHOT_TIMER, m_bOneShot); DDX_Check(pDX, IDC_TEMPORARY, m_bTemporary); DDX_Check(pDX, IDC_ACTIVE_WHEN_CLOSED, m_bActiveWhenClosed); DDX_Text(pDX, IDC_GROUP, m_strGroup); DDX_CBIndex(pDX, IDC_SEND_TO, m_iSendTo); DDX_Text(pDX, IDC_VARIABLE, m_strVariable); DDX_Text(pDX, IDC_INCLUDED, m_strIncluded); DDX_Check(pDX, IDC_OMIT_FROM_OUTPUT, m_bOmitFromOutput); DDX_Check(pDX, IDC_OMIT_FROM_LOG, m_bOmitFromLog); DDX_Text(pDX, IDC_AT_SECOND, m_fAtSecond); DDV_MinMaxDouble(pDX, m_fAtSecond, 0., 59.99999); DDX_Text(pDX, IDC_INTERVAL_SECOND, m_fEverySecond); DDV_MinMaxDouble(pDX, m_fEverySecond, 0., 59.99999); DDX_Text(pDX, IDC_OFFSET_SECOND, m_fOffsetSecond); DDV_MinMaxDouble(pDX, m_fOffsetSecond, 0., 59.99999); //}}AFX_DATA_MAP if(pDX->m_bSaveAndValidate) { m_strLabel.TrimLeft (); m_strLabel.TrimRight (); m_strProcedure.TrimLeft (); m_strProcedure.TrimRight (); m_strGroup.TrimLeft (); m_strGroup.TrimRight (); if (m_iType == CTimer::eInterval) { CmcDateTimeSpan ts1 (0, m_iEveryHour, m_iEveryMinute, m_fEverySecond); CmcDateTimeSpan ts2 (0, m_iOffsetHour, m_iOffsetMinute, m_fOffsetSecond); if (ts1 <= CmcDateTimeSpan (0, 0, 0, 0)) { ::TMessageBox("The timer interval must be greater than zero."); DDX_Text(pDX, IDC_INTERVAL_HOUR, m_iEveryHour); pDX->Fail(); } // end of interval <= 0 if(ts2 >= ts1) { ::TMessageBox("The timer offset must be less than the timer period."); DDX_Text(pDX, IDC_OFFSET_HOUR, m_iOffsetHour); pDX->Fail(); } // end of offset >= period } // end of doing a periodical timer CString strTimerName; CTimer * timer_item; POSITION pos; for (pos = m_pTimerMap->GetStartPosition (); pos; ) { m_pTimerMap->GetNextAssoc (pos, strTimerName, timer_item); // don't compare against itself if (timer_item == m_current_timer) continue; // now check the label for duplicates if (!m_strLabel.IsEmpty ()) // we can have duplicate blank names if (m_strLabel.CompareNoCase (timer_item->strLabel) == 0) { CString strMsg; strMsg = TFormat ("The timer label \"%s\" is already in the list of timers.", (LPCTSTR) m_strLabel); ::UMessageBox(strMsg); DDX_Text(pDX, IDC_TIMER_LABEL, m_strLabel); pDX->Fail(); } } // end of checking each Timer if (!m_strLabel.IsEmpty ()) // we can have blank labels { // check label is valid if (CheckLabel (m_strLabel)) { ::TMessageBox ("The label must start with a letter and consist of letters" ", numbers or the underscore character."); DDX_Text(pDX, IDC_TIMER_LABEL, m_strLabel); pDX->Fail(); } } // end of having non-blank label if (m_strVariable.IsEmpty ()) // we can have blank variables { if (m_iSendTo == eSendToVariable) { ::TMessageBox("When sending to a variable you must specify a variable name. ", MB_ICONSTOP); DDX_Text(pDX, IDC_VARIABLE, m_strVariable); pDX->Fail(); } } else { // check variable name is valid if (CheckLabel (m_strVariable)) { ::TMessageBox("The variable name must start with a letter and consist of letters" ", numbers or the underscore character."); DDX_Text(pDX, IDC_VARIABLE, m_strVariable); pDX->Fail(); } } // end of having non-blank variable // check for speed walking OK, unless they are substituting if (m_iSendTo == eSendToSpeedwalk) { CString strResult = m_pDoc->DoEvaluateSpeedwalk (m_strContents); if (!strResult.IsEmpty ()) { if (strResult [0] == '*') // error in speedwalk string? { ::UMessageBox (strResult.Mid (1)); // already translated, I think DDX_Text(pDX, IDC_TIMER_CONTENTS, m_strContents); pDX->Fail(); } // end of error message } // end of non-empty speedwalk } // end of speed walking wanted if(m_strContents.IsEmpty () && m_strProcedure.IsEmpty ()) { ::TMessageBox("The timer contents cannot be blank unless you specify a script subroutine."); DDX_Text(pDX, IDC_TIMER_CONTENTS, m_strContents); pDX->Fail(); } // end of contents being blank if (!m_strProcedure.IsEmpty ()) // blank procedure is OK { // check procedure is valid if (CheckLabel (m_strProcedure, true)) { ::TMessageBox("The script subroutine name must start with a letter and consist of letters" ", numbers or the underscore character."); DDX_Text(pDX, IDC_SCRIPT_NAME, m_strProcedure); pDX->Fail(); } } // end of having non-blank procedure } // end of saving and validating }
// 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
void CGenPropertyPage::OnChangeItem(CDialog & dlg) { CString strMsg; // iterate through list in case we implement multiple selection one day for (int nItem = -1; (nItem = m_ctlList->GetNextItem(nItem, LVNI_SELECTED)) != -1;) { // get the lower-case name of this item's object CString * pstrObjectName = (CString *) m_ctlList->GetItemData (nItem); ASSERT (pstrObjectName != NULL); CObject * pItem; // check object is still there (it might have gone while we looked at the list box) if (!m_ObjectMap->Lookup (*pstrObjectName, pItem)) { m_ctlList->DeleteItem (nItem); // it's gone, so delete it from the list view m_ctlList->RedrawItems (0, m_ctlList->GetItemCount () - 1); // redraw the list // in the case of one-shot timers, unnamed items might be removed from the list if (pstrObjectName->Left (1) == "*") strMsg = TFormat ("The %s you selected is no longer in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) m_strObjectType); else strMsg = TFormat ("The %s named \"%s\" is no longer in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) *pstrObjectName, (LPCTSTR) m_strObjectType); ::UMessageBox (strMsg); delete pstrObjectName; // and get rid of its name string continue; } ASSERT_VALID (pItem); ASSERT( pItem->IsKindOf( RUNTIME_CLASS( CObject ) ) ); // load dialog with values from the found item LoadDialog (&dlg, pItem); // put up the dialog, give up if they cancel if (dlg.DoModal () != IDOK) continue; // lookup this object, to make sure it still exists if (!m_ObjectMap->Lookup (*pstrObjectName, pItem)) { m_ctlList->DeleteItem (nItem); // it's gone, so delete it from the list view m_ctlList->RedrawItems (0, m_ctlList->GetItemCount () - 1); // redraw the list // in the case of one-shot timers, unnamed items might be removed from the list if (pstrObjectName->Left (1) == "*") strMsg = TFormat ("The %s you selected is no longer in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) m_strObjectType); else strMsg = TFormat ("The %s named \"%s\" is no longer in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) *pstrObjectName, (LPCTSTR) m_strObjectType); delete pstrObjectName; // and get rid of its name string ::UMessageBox (strMsg); continue; } ASSERT_VALID (pItem); ASSERT( pItem->IsKindOf( RUNTIME_CLASS( CObject ) ) ); if (CheckIfIncluded (pItem)) { strMsg = TFormat ("The %s named \"%s\" has been included from an include file. You cannot modify it here.", (LPCTSTR) m_strObjectType, (LPCTSTR) *pstrObjectName); ::UMessageBox (strMsg); return; // can't modify included items } // check object still has the same modification number // (it might have been modified while we looked at the list box) if (GetModificationNumber (pItem) != m_nUpdateNumber) { strMsg = TFormat ("The %s named \"%s\" has already been modified by a script subroutine", (LPCTSTR) m_strObjectType, (LPCTSTR) *pstrObjectName); ::UMessageBox (strMsg); continue; } // check for name change CString strObjectName = GetObjectName (&dlg); if (strObjectName.IsEmpty ()) strObjectName.Format ("*%s%s", (LPCTSTR) m_strObjectType, (LPCTSTR) App.GetUniqueString ()); else strObjectName.MakeLower (); if (strObjectName != *pstrObjectName) // has name changed? { // here if label has changed CObject * new_pItem; if (m_ObjectMap->Lookup (strObjectName, new_pItem)) { strMsg = TFormat ("The %s named \"%s\" already exists in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) strObjectName, (LPCTSTR) m_strObjectType); ::UMessageBox (strMsg); continue; } // remove old entry and re-add under new name m_ObjectMap->RemoveKey (*pstrObjectName); // remove old entry m_ObjectMap->SetAt (strObjectName, pItem); // insert under new name // delete old name in the list delete pstrObjectName; // create a new CString for lookup purposes pstrObjectName = new CString (strObjectName); // record item's new name as the list object data m_ctlList->SetItemData(nItem, (DWORD) pstrObjectName); } // end of label changing // see if the user changed anything, anyway if (CheckIfChanged (&dlg, pItem)) { // unload from dialog into object's properties UnloadDialog (&dlg, pItem); // They can no longer cancel the property sheet, the document has changed CancelToClose (); if (!CheckIfTemporary (pItem)) m_doc->SetModifiedFlag (TRUE); // re-setup list with amended details int nNewItem = add_item (pItem, pstrObjectName, nItem, FALSE); m_ctlList->RedrawItems (nNewItem, nNewItem); } // end of item changing // Get dispatch id from the script and put it into the item. // We do this even if nothing has changed, so that we can force re-evaluation // of the dispatch ID, by just getting the item and pressing OK. if (m_doc->m_ScriptEngine) { CString strMessage; SetDispatchID (pItem, m_doc->GetProcedureDispid (GetScriptName (pItem), m_strObjectType, GetLabel (pItem), strMessage)); if (!strMessage.IsEmpty ()) ::UMessageBox (strMessage, MB_ICONINFORMATION); } } // end of dealing with each selected item // redraw the list if (GetFilterFlag ()) LoadList (); // full reload because it may have changed filter requirements // resort the list t_gen_sort_param sort_param (m_ObjectMap, m_last_col, m_reverse, m_CompareObjects); m_ctlList->SortItems (CompareFunc, (LPARAM) &sort_param); } // end of CGenPropertyPage::OnChangeItem
void CMUSHclientDoc::MXP_Definition (CString strTag) { bool bSecure = MXP_Secure (); MXP_Restore_Mode (); // cancel secure-once mode // check in secure mode if (DEFINITIONS_MUST_BE_SECURE && !bSecure) { MXP_error (DBG_ERROR, errMXP_DefinitionWhenNotSecure, TFormat ("MXP definition ignored when not in secure mode: <!%s>" , (LPCTSTR) strTag)); return; } CString strDefinition; // get first word (eg. ELEMENT or ENTITY) GetWord (strDefinition, strTag); if (!IsValidName (strDefinition)) { MXP_error (DBG_ERROR, errMXP_InvalidDefinition, TFormat ("Invalid MXP definition name: <!%s>", (LPCTSTR) m_strMXPstring)); return; } strDefinition.MakeLower (); // case-insensitive? // get name of what we are defining CString strName; GetWord (strName, strTag); if (!IsValidName (strName)) { MXP_error (DBG_ERROR, errMXP_InvalidElementName, TFormat ("Invalid MXP element/entity name: \"%s\"", (LPCTSTR) strName)); return; } /* if (m_bPuebloActive) { MXP_error (DBG_ERROR, errMXP_DefinitionAttemptInPueblo, TFormat ("Defining elements/entities not valid in Pueblo: <%s>", (LPCTSTR) strName)); return; } */ // debugging MXP_error (DBG_INFO, msgMXP_GotDefinition, TFormat ("Got Definition: !%s %s %s", (LPCTSTR) strDefinition, (LPCTSTR) strName, (LPCTSTR) strTag)); if (strDefinition == "element" || strDefinition == "el") MXP_Element (strName, strTag); else if (strDefinition == "entity" || strDefinition == "en") MXP_Entity (strName, strTag); else if (strDefinition == "attlist" || strDefinition == "at") MXP_Attlist (strName, strTag); else MXP_error (DBG_ERROR, errMXP_InvalidDefinition, TFormat ("Unknown definition type: <!%s>", (LPCTSTR) strDefinition)); } // end of CMUSHclientDoc::MXP_Definition
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
// 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 < 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
void CMUSHclientDoc::CheckTimerList (CTimerMap & TimerMap) { CTimer * timer_item; CString strTimerName; CmcDateTime tNow = CmcDateTime::GetTimeNow(); CmcDateTimeSpan tsOneDay (1, 0, 0, 0); // check for deleted chat sessions for (POSITION chatpos = m_ChatList.GetHeadPosition (); chatpos; ) { POSITION oldpos = chatpos; CChatSocket * pSocket = m_ChatList.GetNext (chatpos); if (pSocket->m_bDeleteMe) { m_ChatList.RemoveAt (oldpos); delete pSocket; break; // list is no longer valid } } set <string> firedTimersList; POSITION pos; // iterate through all timers for this document - first build list of them for (pos = TimerMap.GetStartPosition(); pos; ) { TimerMap.GetNextAssoc (pos, strTimerName, timer_item); if (!timer_item->bEnabled) // ignore un-enabled timers continue; // no timer activity whilst closed or in the middle of connecting, or if not enabled if (!timer_item->bActiveWhenClosed) if (m_iConnectPhase != eConnectConnectedToMud) continue; // if not ready to fire yet, ignore it if (timer_item->tFireTime > tNow) continue; firedTimersList.insert ((LPCTSTR) strTimerName); // add to list of fired timers } // now process list, checking timer still exists in case a script deleted one // see: http://www.gammon.com.au/forum/?id=10358 for (set <string>::iterator it = firedTimersList.begin (); it != firedTimersList.end (); it++) { // get next fired timer from list strTimerName = it->c_str (); // check still exists, get pointer if so if (!TimerMap.Lookup (strTimerName, timer_item)) continue; timer_item->nMatched++; // count timer matches timer_item->tWhenFired = tNow; // when it fired m_iTimersFiredCount++; m_iTimersFiredThisSessionCount++; // TRACE1 ("Fired at = %10.8f\n", timer_item->tWhenFired.m_dt); if (timer_item->strLabel.IsEmpty ()) Trace ("Fired unlabelled timer "); else Trace ("Fired timer %s", (LPCTSTR) timer_item->strLabel); // TRACE1 ("Fire time = %10.8f\n", timer_item->tFireTime.m_dt); // update fire time - before calling the script, in case it takes a long time if (timer_item->iType == CTimer::eAtTime) timer_item->tFireTime += tsOneDay; else timer_item->tFireTime += CmcDateTimeSpan (0, // add the interval timer_item->iEveryHour, timer_item->iEveryMinute, timer_item->fEverySecond); // in case clock changes or some such thing, make sure timer will be due to // fire in the future, not the past, or it might go mad and keep firing if (timer_item->tFireTime <= tNow) ResetOneTimer (timer_item); // if one-shot, disable it, so if the timer routine finds it again while // it is still executing (eg. due to a syntax error dialog box) then // it won't fire again. if (timer_item->bOneShot) timer_item->bEnabled = false; // send timer message, if this timer list is "active" CString strExtraOutput; timer_item->bExecutingScript = true; // cannot be deleted now m_iCurrentActionSource = eTimerFired; SendTo (timer_item->iSendTo, timer_item->strContents, timer_item->bOmitFromOutput, // omit from output timer_item->bOmitFromLog, // omit from log TFormat ("Timer: %s", (LPCTSTR) timer_item->strLabel), timer_item->strVariable, strExtraOutput ); m_iCurrentActionSource = eUnknownActionSource; timer_item->bExecutingScript = false; // can be deleted now // display any stuff sent to output window if (!strExtraOutput.IsEmpty ()) DisplayMsg (strExtraOutput, strExtraOutput.GetLength (), COMMENT); // invoke script subroutine, if any if (!timer_item->strProcedure.IsEmpty ()) if (CheckScriptingAvailable ("Timer", timer_item->dispid, timer_item->strProcedure)) continue; if (timer_item->dispid != DISPID_UNKNOWN) // if we have a dispatch id { CString strType = "timer"; CString strReason = TFormat ("processing timer \"%s\"", (LPCTSTR) timer_item->strLabel); // get unlabelled timer's internal name const char * pLabel = timer_item->strLabel; if (pLabel [0] == 0) pLabel = GetTimerRevMap () [timer_item].c_str (); if (GetScriptEngine () && GetScriptEngine ()->IsLua ()) { list<double> nparams; list<string> sparams; sparams.push_back (pLabel); timer_item->bExecutingScript = true; // cannot be deleted now GetScriptEngine ()->ExecuteLua (timer_item->dispid, timer_item->strProcedure, eTimerFired, strType, strReason, nparams, sparams, timer_item->nInvocationCount); timer_item->bExecutingScript = false; // can be deleted now } // end of Lua else { // prepare for the arguments (so far, 1 which is the timer name) // WARNING - arguments should appear in REVERSE order to what the sub expects them! enum { eTimerName, eArgCount, // this MUST be last }; COleVariant args [eArgCount]; DISPPARAMS params = { args, NULL, eArgCount, 0 }; // args [eTimerName] = strTimerName; args [eTimerName] = pLabel; timer_item->bExecutingScript = true; // cannot be deleted now ExecuteScript (timer_item->dispid, timer_item->strProcedure, eTimerFired, strType, strReason, params, timer_item->nInvocationCount); timer_item->bExecutingScript = false; // can be deleted now } // not Lua } // end of having a dispatch ID // If they passed the wrong arguments to the timer routine, the dialog box // might appear, and the timer be deleted, before we get a chance to // do this code, in which case the timer has gone. // Just get it again to be sure ... [#430] if (!TimerMap.Lookup (strTimerName, timer_item)) return; // if one-shot timer, delete from list if (timer_item->bOneShot) { TimerMap.RemoveKey (strTimerName); delete timer_item; SortTimers (); } } // end of processing each timer } // end of CMUSHclientDoc::CheckTimerMap
CString CMUSHclientDoc::MXP_GetEntity (CString & strName) { CString strLowerCaseName = strName; strLowerCaseName.MakeLower (); CString strEntityContents; // look for &#nnn; if (strName [0] == '#') { int iResult = 0; // validate and work out number if (strName [1] == 'x') { for (int i = 2; i < strName.GetLength (); i++) { if (!isxdigit (strName [i])) { MXP_error (DBG_ERROR, errMXP_InvalidEntityNumber, TFormat ("Invalid hex number in MXP entity: &%s;" , (LPCTSTR) strName)); return ""; } int iNewDigit = toupper (strName [i]); if (iNewDigit >= 'A') iNewDigit -= 7; if (iResult & 0xF0) { MXP_error (DBG_ERROR, errMXP_InvalidEntityNumber, TFormat ("Invalid hex number in MXP entity: &%s;" "- maximum of 2 hex digits", (LPCTSTR) strName)); return ""; } iResult = (iResult << 4) + iNewDigit - '0'; } } // end of hex entity else for (int i = 1; i < strName.GetLength (); i++) { if (!isdigit (strName [i])) { MXP_error (DBG_ERROR, errMXP_InvalidEntityNumber, TFormat ("Invalid number in MXP entity: &%s;" , (LPCTSTR) strName)); return ""; } iResult *= 10; iResult += strName [i] - '0'; } if (iResult != 9 && iResult != 10 ) // we will accept tabs and newlines ;) if (iResult < 32 || // don't allow nonprintable characters iResult > 255) // don't allow characters more than 1 byte { MXP_error (DBG_ERROR, errMXP_DisallowedEntityNumber, TFormat ("Disallowed number in MXP entity: &%s;" , (LPCTSTR) strName)); return ""; } unsigned char cOneCharacterLine [2] = { (unsigned char) iResult, 0}; return (char *) cOneCharacterLine; } // end of entity starting with # // look up global entities first if (App.m_EntityMap.Lookup (strName, strEntityContents)) return strEntityContents; // then try ones for this document else if (m_CustomEntityMap.Lookup (strLowerCaseName, strEntityContents)) return strEntityContents; MXP_error (DBG_ERROR, errMXP_UnknownEntity, TFormat ("Unknown MXP entity: &%s;" , (LPCTSTR) strName)); return ""; } // end of CMUSHclientDoc::MXP_GetEntity
// here for <!ENTITY blah> void CMUSHclientDoc::MXP_Entity (CString strName, CString strTag) { // case insensitive strName.MakeLower (); CString strEntityContents; if (App.m_EntityMap.Lookup (strName, strEntityContents)) { MXP_error (DBG_ERROR, errMXP_CannotRedefineEntity, TFormat ("Cannot redefine entity: &%s;", (LPCTSTR) strName)); return; } GetWord (strEntityContents, strTag); // blank contents deletes the entity if (strEntityContents.IsEmpty ()) m_CustomEntityMap.RemoveKey (strName); else { // look for entities imbedded in the definition, eg. <!EN blah '<Nick>'> const char * p = strEntityContents; const char * pStart; CString strFixedValue; CString strEntity; strFixedValue.Empty (); for ( ; *p; p++) { if (*p == '&') { 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_NoClosingSemicolon, TFormat ("No closing \";\" in MXP entity argument \"%s\"", (LPCTSTR) strEntityContents)); return; } CString s (pStart, p - pStart); strFixedValue += MXP_GetEntity (s); // add to list } // end of having an ampersand else strFixedValue += *p; // just add ordinary characters to list } // end of processing the value // add entity to map m_CustomEntityMap.SetAt (strName, strFixedValue); // tell each plugin what we have received if (m_bPluginProcessesSetEntity) SendToAllPluginCallbacks (ON_PLUGIN_MXP_SETENTITY, CFormat ("%s=%s", (LPCTSTR) strName, (LPCTSTR) strFixedValue)); m_CurrentPlugin = NULL; } // check they didn't supply any other arguments strTag.TrimLeft (); while (!strTag.IsEmpty ()) { CString strKeyword; GetWord (strKeyword, strTag); strKeyword.MakeLower (); if (strKeyword == "desc") { GetWord (strKeyword, strTag); if (strKeyword != "=") GetWord (strKeyword, strTag); // get description } else if (strKeyword == "private") { // do nothing } else if (strKeyword == "publish") { // do nothing } else if (strKeyword == "delete") { m_CustomEntityMap.RemoveKey (strName); } else if (strKeyword == "add") { // do nothing } else if (strKeyword == "remove") { m_CustomEntityMap.RemoveKey (strName); } else { MXP_error (DBG_WARNING, errMXP_UnexpectedEntityArguments, TFormat ("Unexpected word \"%s\" in entity definition for &%s; ignored", (LPCTSTR) strKeyword, (LPCTSTR) strName)); return; } } // of processing optional words } // end of CMUSHclientDoc::MXP_Entity
STDMETHODIMP CActiveScriptSite::OnScriptError(IActiveScriptError *pscripterror) { DWORD dwCookie; LONG nChar; ULONG nLine; BSTR bstr = 0; EXCEPINFO ei; ZeroMemory(&ei, sizeof(ei)); TRACE ("CActiveScriptSite: OnScriptError\n"); pscripterror->GetSourcePosition(&dwCookie, &nLine, &nChar); pscripterror->GetSourceLineText(&bstr); pscripterror->GetExceptionInfo(&ei); CScriptErrorDlg dlg; if (ei.wCode) dlg.m_iError = ei.wCode; else dlg.m_iError = ei.scode; nLine = nLine + 1; // make 1-relative to be consistent with lua dlg.m_strEvent = TFormat ("Execution of line %i column %i", nLine, nChar + 1); dlg.m_strDescription = ei.bstrDescription; if (!strProcedure.IsEmpty ()) { dlg.m_strCalledBy = "Function/Sub: "; dlg.m_strCalledBy += strProcedure; dlg.m_strCalledBy += " called by "; dlg.m_strCalledBy += strType; dlg.m_strCalledBy += ENDLINE; dlg.m_strCalledBy += "Reason: "; dlg.m_strCalledBy += strReason; } else { dlg.m_strCalledBy = Translate ("Immediate execution"); dlg.m_strDescription += ENDLINE; if (bstr) { dlg.m_strDescription += Translate ("Line in error: "); dlg.m_strDescription += ENDLINE; dlg.m_strDescription += bstr; } } dlg.m_strRaisedBy = Translate ("No active world"); if (m_pDoc) { if (m_pDoc->m_CurrentPlugin) { dlg.m_strRaisedBy = TFormat ("Plugin: %s (called from world: %s)", (LPCTSTR) m_pDoc->m_CurrentPlugin->m_strName, (LPCTSTR) m_pDoc->m_mush_name); } else dlg.m_strRaisedBy = TFormat ("World: %s", (LPCTSTR) m_pDoc->m_mush_name); } if (!m_pDoc || !m_pDoc->m_bScriptErrorsToOutputWindow) { if (m_pDoc) dlg.m_bHaveDoc = true; dlg.DoModal (); if (m_pDoc && dlg.m_bUseOutputWindow) { m_pDoc->m_bScriptErrorsToOutputWindow = true; m_pDoc->SetModifiedFlag (TRUE); } } else { m_pDoc->ColourNote (SCRIPTERRORFORECOLOUR, SCRIPTERRORBACKCOLOUR, Translate ("Script error")); m_pDoc->ColourNote (SCRIPTERRORFORECOLOUR, SCRIPTERRORBACKCOLOUR, dlg.m_strRaisedBy); m_pDoc->ColourNote (SCRIPTERRORFORECOLOUR, SCRIPTERRORBACKCOLOUR, dlg.m_strEvent); m_pDoc->ColourNote (SCRIPTERRORFORECOLOUR, SCRIPTERRORBACKCOLOUR, dlg.m_strCalledBy); m_pDoc->ColourNote (SCRIPTERRORFORECOLOUR, SCRIPTERRORBACKCOLOUR, dlg.m_strDescription); // show bad lines? if (!bImmediate) m_pDoc->ShowErrorLines (nLine); } // end of showing in output window SysFreeString(bstr); SysFreeString(ei.bstrSource); SysFreeString(ei.bstrDescription); SysFreeString(ei.bstrHelpFile); return S_OK; } // end of CActiveScriptSite::OnScriptError
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
void CGenPropertyPage::OnDeleteItem() { CUIntArray arySelected; int iCount = m_ctlList->GetSelectedCount (); int nItem, i, iIncluded = 0, iExecuting = 0; arySelected.SetSize (iCount); // first, remember selected items for (nItem = -1, i = 0; (nItem = m_ctlList->GetNextItem(nItem, LVNI_SELECTED)) != -1;) arySelected [i++] = nItem; if (iCount == 0) return; if (App.m_bTriggerRemoveCheck) { // mucking around to make it plural properly CString sName = m_strObjectType; if (iCount > 1) if (sName == "alias") sName += "es"; else sName += "s"; if (::UMessageBox (TFormat ("Delete %i %s - are you sure?", iCount, sName), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) != IDYES ) return; } // end of wanting to confirm // we do it this way because deleting items buggers up the position in the array for (i = iCount - 1; i >= 0; i--) { nItem = arySelected [i]; // get the lower-case name of this item's object CString * pstrObjectName = (CString *) m_ctlList->GetItemData (nItem); ASSERT (pstrObjectName != NULL); CObject * pItem; // see if in the map if (!m_ObjectMap->Lookup (*pstrObjectName, pItem)) continue; // already deleted! ASSERT_VALID (pItem); ASSERT( pItem->IsKindOf( RUNTIME_CLASS( CObject ) ) ); if (CheckIfIncluded (pItem)) { iIncluded++; // don't do message here in case hundreds of them continue; } if (CheckIfExecuting (pItem)) { iExecuting++; // don't do message here in case hundreds of them continue; } // They can no longer cancel the property sheet, the document has changed CancelToClose (); if (!CheckIfTemporary (pItem)) m_doc->SetModifiedFlag (TRUE); // delete from the map m_ObjectMap->RemoveKey (*pstrObjectName); // delete the item itself delete pItem; // and remove from the dialog list control m_ctlList->DeleteItem (nItem); // delete its item string delete pstrObjectName; } // end of dealing with each selected item if (iIncluded) { CString strMsg; strMsg = TFormat ("%i item%s %s included from an include file. You cannot delete %s here.", PLURAL (iIncluded), iIncluded == 1 ? "was" : "were", iIncluded == 1 ? "it" : "them"); ::UMessageBox (strMsg); } if (iExecuting) { CString strMsg; strMsg = TFormat ("%i item%s %s currently executing a script. You cannot delete %s now.", PLURAL (iExecuting), iExecuting == 1 ? "is" : "are", iExecuting == 1 ? "it" : "them"); ::UMessageBox (strMsg); } } // end of CGenPropertyPage::OnDeleteItem
void CGenPropertyPage::LoadList (void) { long iCount = 0; long iNotShown = 0; // for filtering CScriptEngine * m_ScriptEngine = NULL; // for the filtering checks bool bFiltering = GetFilterFlag (); if (bFiltering) { m_ScriptEngine = new CScriptEngine (m_doc, "Lua"); if (m_ScriptEngine->CreateScriptEngine ()) bFiltering = false; else { // compile filter script try { if (m_ScriptEngine->Parse (GetFilterScript (), "Script file")) bFiltering = false; } // end of try catch (CException * e) { e->ReportError (); e->Delete (); bFiltering = false; } } // not error creating engine } // end of filtering wanted lua_State * L = NULL; // if filtering, get the "filter" function on the stack if (bFiltering) { L = m_ScriptEngine->L; // make copy for convenience lua_settop(L, 0); // clear stack, just in case if (!GetNestedFunction (L, "filter", true)) bFiltering = false; } // remove all old items (we used the item data to key to the item) for (int nItem = 0; nItem < m_ctlList->GetItemCount (); nItem++) delete (CString *) m_ctlList->GetItemData (nItem); m_ctlList->DeleteAllItems (); CString strObjectName; CObject * pItem; // Item data for (POSITION pos = m_ObjectMap->GetStartPosition (); pos; ) { m_ObjectMap->GetNextAssoc (pos, strObjectName, pItem); bool bUse = true; // defaults to true if no filtering if (bFiltering) { lua_pushvalue(L, 1); // filter function lua_pushstring (L, (const char *) strObjectName); // key of the item GetFilterInfo (pItem, L); // table of related info if (lua_pcall (L, 2, 1, 0)) // call with 1 arg1 and 1 result { LuaError (L); bFiltering = false; } else { // use result if we get the exact type: boolean (true/false) if (lua_isboolean (L, -1)) { bUse = lua_toboolean (L, -1); if (!bUse) iNotShown++; // this one not shown } lua_pop (L, 1); // pop result } } // end of filtering wanted if (bUse) // add to list if passed filter { CString * pstrObjectName = new CString (strObjectName); add_item (pItem, pstrObjectName, 0, TRUE); iCount++; } } t_gen_sort_param sort_param (m_ObjectMap, m_last_col, m_reverse, m_CompareObjects); m_ctlList->SortItems (CompareFunc, (LPARAM) &sort_param); // set the 1st item to be selected - we do this here because sorting the // list means our first item is not necessarily the 1st item in the list if (!m_ObjectMap->IsEmpty ()) // provided we have any m_ctlList->SetItemState (0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); CString strSummary = TFormat ("%i item%s.", PLURAL (iCount)); if (iNotShown) strSummary += TFormat (" (%i item%s hidden by filter)", PLURAL (iNotShown)); m_ctlSummary->SetWindowText (strSummary); delete m_ScriptEngine; } // end of CGenPropertyPage::LoadList
void CGenPropertyPage::OnCopyItem() { char * p = NULL; try { CMemFile f; // open memory file for writing CArchive ar(&f, CArchive::store); // in case we do more than one (one day) the header comes before the batch if (m_strObjectType == "alias") m_doc->Save_Header_XML (ar, "aliases", false); else m_doc->Save_Header_XML (ar, m_strObjectType + "s", false); // timers, triggers etc. for (int nItem = -1; (nItem = m_ctlList->GetNextItem(nItem, LVNI_SELECTED)) != -1;) { // get the lower-case name of this item's object CString * pstrObjectName = (CString *) m_ctlList->GetItemData (nItem); ASSERT (pstrObjectName != NULL); CObject * pItem; // check object is still there (it might have gone while we looked at the list box) if (!m_ObjectMap->Lookup (*pstrObjectName, pItem)) { CString strMsg; m_ctlList->DeleteItem (nItem); // it's gone, so delete it from the list view m_ctlList->RedrawItems (0, m_ctlList->GetItemCount () - 1); // redraw the list // in the case of one-shot timers, unnamed items might be removed from the list if (pstrObjectName->Left (1) == "*") strMsg = TFormat ("The %s you selected is no longer in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) m_strObjectType); else strMsg = TFormat ("The %s named \"%s\" is no longer in the %s list", (LPCTSTR) m_strObjectType, (LPCTSTR) *pstrObjectName, (LPCTSTR) m_strObjectType); ::UMessageBox (strMsg); delete pstrObjectName; // and get rid of its name string continue; } ASSERT_VALID (pItem); ASSERT( pItem->IsKindOf( RUNTIME_CLASS( CObject ) ) ); // turn into XML if (m_strObjectType == "trigger") m_doc->Save_One_Trigger_XML (ar, (CTrigger *) pItem); else if (m_strObjectType == "alias") m_doc->Save_One_Alias_XML (ar, (CAlias *) pItem); else if (m_strObjectType == "timer") m_doc->Save_One_Timer_XML (ar, (CTimer *) pItem); else if (m_strObjectType == "variable") m_doc->Save_One_Variable_XML (ar, (CVariable *) pItem); } // end of dealing with each selected item if (m_strObjectType == "alias") m_doc->Save_Footer_XML (ar, "aliases"); else m_doc->Save_Footer_XML (ar, m_strObjectType + "s"); // timers, triggers etc. ar.Close(); int nLength = f.GetLength (); p = (char *) f.Detach (); CString strXML (p, nLength); free (p); // remove memory allocated in CMemFile p = NULL; putontoclipboard (strXML, m_doc->m_bUTF_8); } // end of try block catch (CException* e) { if (p) free (p); // remove memory allocated in CMemFile e->ReportError(); e->Delete(); } } // end of CGenPropertyPage::OnCopyItem
void CInsertUnicodeDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CInsertUnicodeDlg) DDX_Text(pDX, IDC_UNICODE_CHARACTER, m_strCharacter); DDX_Check(pDX, IDC_UNICODE_HEX, m_bHex); //}}AFX_DATA_MAP if (pDX->m_bSaveAndValidate) { m_strCharacter.TrimLeft (); m_strCharacter.TrimRight (); if(m_strCharacter.IsEmpty ()) { ::TMessageBox ("Unicode character code cannot be blank."); DDX_Text(pDX, IDC_UNICODE_CHARACTER, m_strCharacter); pDX->Fail(); } // end of code being blank if(m_strCharacter.GetLength () > 10) { ::TMessageBox ("Unicode character code too long."); DDX_Text(pDX, IDC_UNICODE_CHARACTER, m_strCharacter); pDX->Fail(); } // end of code being too long to convert const char * p = m_strCharacter; __int64 i = 0; // converted number if (m_bHex) { for ( ; *p; p++) { if (!isxdigit (*p)) { ::UMessageBox (TFormat ("Bad hex character: '%c'.", *p)); DDX_Text(pDX, IDC_UNICODE_CHARACTER, m_strCharacter); pDX->Fail(); } int iNewDigit = toupper (*p); if (iNewDigit >= 'A') iNewDigit -= 7; i = (i << 4) + iNewDigit - '0'; } // end of building up sequence } // in hex else { // decimal for ( ; *p; p++) if (!isdigit (*p)) { ::UMessageBox (TFormat ("Bad decimal character: '%c'.", *p)); DDX_Text(pDX, IDC_UNICODE_CHARACTER, m_strCharacter); pDX->Fail(); } i = _atoi64 (m_strCharacter); } if (i < 0 || i > LONG_MAX) { ::UMessageBox (TFormat ("Unicode character %I64i too large - must be in range 0 to 2147483647 " "(hex 0 to 7FFFFFFF).", i)); DDX_Text(pDX, IDC_UNICODE_CHARACTER, m_strCharacter); pDX->Fail(); } m_iCode = i; } // end of saving }
int regexec(register t_regexp *prog, register const char *string, const int start_offset) { int options = App.m_bRegexpMatchEmpty ? 0 : PCRE_NOTEMPTY; // don't match on an empty string int count; // exit if no regexp program to process (possibly because of previous error) if (prog->m_program == NULL) return false; // inspired by a suggestion by Twisol (to remove a hard-coded limit on the number of wildcards) int capturecount = 0; // how many captures did we get? pcre_fullinfo(prog->m_program, NULL, PCRE_INFO_CAPTURECOUNT, &capturecount); // allocate enough memory vector<int> offsets ((capturecount + 1) * 3); // we always get offset 0 - the whole match LARGE_INTEGER start, finish; if (App.m_iCounterFrequency) QueryPerformanceCounter (&start); else { start.QuadPart = 0; finish.QuadPart = 0; } pcre_callout = NULL; count = pcre_exec(prog->m_program, prog->m_extra, string, strlen (string), start_offset, options, &offsets [0], offsets.size ()); if (App.m_iCounterFrequency) { QueryPerformanceCounter (&finish); prog->iTimeTaken += finish.QuadPart - start.QuadPart; } prog->m_iMatchAttempts++; // how many times did we try to match? if (count == PCRE_ERROR_NOMATCH) return false; // no match - don't save matching string etc. // otherwise free program as an indicator that we can't keep trying to do this one if (count <= 0) { pcre_free (prog->m_program); prog->m_program = NULL; pcre_free (prog->m_extra); prog->m_extra = NULL; prog->m_iExecutionError = count; // remember reason ThrowErrorException (TFormat ("Error executing regular expression: %s", (LPCTSTR) Convert_PCRE_Runtime_Error (count))); } // if, and only if, we match, we will save the matching string, the count // and offsets, so we can extract the wildcards later on prog->m_sTarget = string; // for extracting wildcards prog->m_iCount = count; // ditto prog->m_vOffsets.clear (); copy (offsets.begin (), offsets.end (), back_inserter (prog->m_vOffsets)); return true; // match }