Esempio n. 1
0
void CMUSHclientDoc::ResetConfigurationArrays (void)
  {
int i; 

  for (i = 0; i < NUMITEMS (OptionsTable); i++)
     m_NumericConfiguration [i]->Reset ();


  for (i = 0; i < NUMITEMS (AlphaOptionsTable); i++)
     m_AlphaConfiguration [i]->Reset ();

  }
Esempio n. 2
0
void CMUSHclientDoc::DeleteConfigurationArrays (void)
  {
int i; 

  for (i = 0; i < NUMITEMS (OptionsTable); i++)
     delete m_NumericConfiguration  [i];

  m_NumericConfiguration.RemoveAll ();

  for (i = 0; i < NUMITEMS (AlphaOptionsTable); i++)
     delete m_AlphaConfiguration  [i];

  m_AlphaConfiguration.RemoveAll ();

  }
Esempio n. 3
0
void CMUSHclientDoc::AllocateConfigurationArrays (void)
  {
int i; 

  m_NumericConfiguration.SetSize (NUMITEMS (OptionsTable));

  for (i = 0; i < NUMITEMS (OptionsTable); i++)
     m_NumericConfiguration.SetAt (i, new CNumericConfiguration);


  m_AlphaConfiguration.SetSize (NUMITEMS (AlphaOptionsTable));

  for (i = 0; i < NUMITEMS (AlphaOptionsTable); i++)
     m_AlphaConfiguration.SetAt (i, new CAlphaConfiguration);

  }
Esempio n. 4
0
long CMUSHclientDoc::GetOptionItem (const int iItem)
  {
  return GetBaseOptionItem (iItem, 
                            OptionsTable, 
                            NUMITEMS (OptionsTable),
                            (char *) this);  
  }
Esempio n. 5
0
CString CMUSHclientDoc::GetAlphaOptionItem (const int iItem)
  {

  return GetBaseAlphaOptionItem (iItem, 
                                 AlphaOptionsTable,
                                 NUMITEMS (AlphaOptionsTable),
                                 (char *) this);

  }  // end of CMUSHclientDoc::GetAlphaOptionItem
BSTR CMUSHclientDoc::Hash(LPCTSTR Text) 
{
	CString strResult;

  SHS_INFO shsInfo;
  shsInit   (&shsInfo);
  shsUpdate (&shsInfo, (unsigned char *) (const char *) Text, 
              strlen (Text));
  shsFinal  (&shsInfo);

  for (int i = 0; i < NUMITEMS (shsInfo.digest); i++)
    strResult += CFormat ("%08x", shsInfo.digest [i]);

	return strResult.AllocSysString();
}   // end of CMUSHclientDoc::Hash
Esempio n. 7
0
// returns true if archive turns out to be XML
bool IsArchiveXML (CArchive& ar)
  {

  // auto-detect XML files

  char buf [500],     // should be even number of bytes in case Unicode
       buf2 [500];

  memset (buf, 0, sizeof (buf));
  ar.GetFile ()->Read (buf, sizeof (buf) - 2);   // allow for Unicode 00 00
  ar.GetFile ()->SeekToBegin ();  // back to start for further serialisation

  // look for Unicode (FF FE)
  if ((unsigned char) buf [0] == 0xFF &&
      (unsigned char) buf [1] == 0xFE)
    WideCharToMultiByte (CP_UTF8, 0, (LPCWSTR) &buf [2], -1, buf2, sizeof buf2, NULL, NULL);
  else
    // look for UTF-8 indicator bytes (EF BB BF)
    if ((unsigned char) buf [0] == 0xEF &&
        (unsigned char) buf [1] == 0xBB &&
        (unsigned char) buf [2] == 0xBF)
      strcpy (buf2, &buf [3]);   // skip them
  else 
    strcpy (buf2, buf);

  char * p = buf2;

  // skip leading whitespace
  while (isspace (*p))
    p++;

  // can't see them squeezing much into less than 15 chars
  //  (eg. minimum would be <macros></macros> )
  if (strlen (p) < 15)
    return false;

  for (int i = 0; i < NUMITEMS (sigs); i++)
    if (COMPARE_MEMORY (sigs [i]))
      return true;

  return false;

  } // end of IsArchiveXML
Esempio n. 8
0
// general MXP error message routine - appends a newline, and also writes to debug 
void CMUSHclientDoc::MXP_error (const int iLevel, 
                                const long iMessageNumber, 
                                CString strMessage)
  {

char * sLevel [] = 
  {
  " ",
  "E", // error
  "W", // warning
  "I", // info
  "A", // all
  };

char * p = "?";

  // turn error level into a character
  if (iLevel >= 0 && iLevel < NUMITEMS (sLevel))
    p = sLevel [iLevel];

  if (iLevel == DBG_ERROR)
    {
    m_iMXPerrors++;
    MXP_Restore_Mode (); // an error cancels secure-once mode
    } // end of error

  // call script if required
  if (m_dispidOnMXP_Error != DISPID_UNKNOWN)
    {
    long nInvocationCount = 0;

    CString strType = "MXP Error";
    CString strReason =  "processing MXP error";

    if (GetScriptEngine () && GetScriptEngine ()->IsLua ())
      {
      list<double> nparams;
      list<string> sparams;
      nparams.push_back (iMessageNumber);  // error number
      nparams.push_back (m_LineList.GetCount ());  // line
      sparams.push_back (p);    // level (a character)
      sparams.push_back ((LPCTSTR) strMessage);    // message
      bool result;
      GetScriptEngine ()->ExecuteLua (m_dispidOnMXP_Error, 
                                     m_strOnMXP_Error, 
                                     eWorldAction,
                                     strType, 
                                     strReason, 
                                     nparams,
                                     sparams, 
                                     nInvocationCount,
                                     NULL, NULL, NULL,
                                     &result);
      if (result)
         return;
      }   // end of Lua
   else
       {
      // WARNING - arguments should appear in REVERSE order to what the sub expects them!

      enum
        {
        eErrorMessage,
        eLineNumber,
        eMessageNumber,
        eErrorLevel,
        eArgCount,     // this MUST be last
        };    

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

      args [eErrorLevel] = p;
      args [eMessageNumber] = iMessageNumber;
      args [eLineNumber] = (long) m_LineList.GetCount ();
      args [eErrorMessage] = strMessage;

      COleVariant result;

      ExecuteScript (m_dispidOnMXP_Error,  
                     m_strOnMXP_Error,
                     eWorldAction,
                     strType, 
                     strReason,
                     params, 
                     nInvocationCount,
                     &result); 

      // if the function returns a non-zero result, don't display the message
      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;
        }
      }  // not Lua
    }  // end of script callback wanted


  // tell each plugin about the error tag
  if (m_bPluginProcessesError)
    SendToAllPluginCallbacks (ON_PLUGIN_MXP_ERROR, 
                              CFormat ("%s,%ld,%ld,%s",
                              (LPCTSTR) p,
                              iMessageNumber,
                              (long) m_LineList.GetCount (),
                              (LPCTSTR) strMessage));


  CString strTitle = MXP_ERROR_WINDOW;
  strTitle += " - ";
  strTitle += m_mush_name;

  if (iLevel > m_iMXPdebugLevel)   // only show required level
    return;

  CString str = CFormat ("%s %5i: (%5i) %s%s",
                      p,     // error level
                      iMessageNumber,   // actual error number
                      m_LineList.GetCount (),  // which line
                      (LPCTSTR) strMessage,     // what message
                      ENDLINE);

  AppendToTheNotepad (strTitle, 
                      str,                 // start new line
                      false,   // append
                      eNotepadMXPdebug);
  }
Esempio n. 9
0
long CMUSHclientDoc::SetAlphaOptionItem (const int iItem, 
                                        LPCTSTR sValue, 
                                        const bool bDoSpecial,
                                        const bool bInclude)
  {


  CString strValue = sValue;

  if (AlphaOptionsTable [iItem].iFlags & OPT_COMMAND_STACK)
    {

    if (strValue.GetLength () > 1)
      return eOptionOutOfRange;

      if (strValue.IsEmpty ())
        {
        m_enable_command_stack = false;
        return eOptionOutOfRange;
        }

      if (!isprint (strValue [0]) || isspace (strValue [0]))
        {
        m_enable_command_stack = false;
        return eOptionOutOfRange;
        }

    } // end of command stack character

  if (AlphaOptionsTable [iItem].iFlags & OPT_WORLD_ID)
    {

    if (!strValue.IsEmpty ())
      if (strValue.GetLength () != PLUGIN_UNIQUE_ID_LENGTH)
        return eOptionOutOfRange;

    // make sure hex characters
    const char * p = strValue;
    for ( ; *p ; p++)
      if (!isxdigit (*p))
      return eOptionOutOfRange;

    strValue.MakeLower ();

    } // end of world id
  
bool bChanged;
long iResult = SetBaseAlphaOptionItem (iItem,
                        AlphaOptionsTable,
                        NUMITEMS (AlphaOptionsTable),
                        (char *) this,
                        strValue,
                        bChanged);

  if (iResult != eOK)
    return iResult;

  if (bChanged)
    SetModifiedFlag ();

  if (bInclude)
    {
    m_AlphaConfiguration [iItem]->bInclude = true;
    m_AlphaConfiguration [iItem]->sValue = strValue;
    }

  // specials wanted?
  if (!bDoSpecial)
    return eOK;


// any special tests here ...

  if (AlphaOptionsTable [iItem].iFlags & OPT_UPDATE_INPUT_FONT)
    ChangeInputFont (m_input_font_height, 
                     m_input_font_name, 
                     m_input_font_weight, 
                     m_input_font_charset,
                     m_input_font_italic);

  if (AlphaOptionsTable [iItem].iFlags & OPT_UPDATE_OUTPUT_FONT)
    ChangeFont (m_font_height, 
                m_font_name, 
                m_font_weight, 
                m_font_charset,
                m_bShowBold,
                m_bShowItalic,
                m_bShowUnderline,
                m_iLineSpacing);

  if (AlphaOptionsTable [iItem].iFlags & OPT_UPDATE_VIEWS)
    UpdateAllViews (NULL);  

  return eOK;

  }  // end of CMUSHclientDoc:SetAlphaOptionItem 
Esempio n. 10
0
long CMUSHclientDoc::SetOptionItem (const int iItem, 
                                    long Value, 
                                    const bool bDoSpecial,
                                    const bool bInclude) 
  {
bool bChanged;

long iResult = SetBaseOptionItem (iItem, 
                                  OptionsTable, 
                                  NUMITEMS (OptionsTable),
                                  (char *) this,
                                  Value,
                                  bChanged);

  if (iResult != eOK)
    return iResult;

  if (bChanged)
    SetModifiedFlag ();

  if (bInclude)
    {
    m_NumericConfiguration [iItem]->bInclude = true;
    m_NumericConfiguration [iItem]->iValue = Value;
    }

  // specials wanted?
  if (!bDoSpecial)
    return eOK;
  
// some special handling

  if (OptionsTable [iItem].iFlags & OPT_FIX_OUTPUT_BUFFER)
    if (m_pCurrentLine)     // a new world might not have a line yet
      FixUpOutputBuffer (Value);

  if (OptionsTable [iItem].iFlags & OPT_FIX_INPUT_WRAP)
	  FixInputWrap();

  if (OptionsTable [iItem].iFlags & OPT_FIX_WRAP_COLUMN)
    {
    if (m_pCurrentLine)     // a new world might not have a line yet
      {
      // save current line text
      CString strLine = CString (m_pCurrentLine->text, m_pCurrentLine->len);

#ifdef USE_REALLOC
      m_pCurrentLine->text  = (char *) 
            realloc (m_pCurrentLine->text, 
                     MAX (m_pCurrentLine->len, Value) 
                     * sizeof (char));  
#else
      delete [] m_pCurrentLine->text;
      m_pCurrentLine->text = new char [MAX (m_pCurrentLine->len, Value)];
#endif

      // put text back
      memcpy (m_pCurrentLine->text, (LPCTSTR) strLine, m_pCurrentLine->len);
      ASSERT (m_pCurrentLine->text);
      }   // end of having a current line
    SendWindowSizes (Value);
    }

  if (OptionsTable [iItem].iFlags & OPT_FIX_SPEEDWALK_DELAY)
    SetSpeedWalkDelay ((short) Value);

  POSITION pos;

  if (OptionsTable [iItem].iFlags & OPT_FIX_TOOLTIP_VISIBLE)
    {
    for(pos = GetFirstViewPosition(); pos != NULL;)
    	{
    	CView* pView = GetNextView(pos);
    	if (pView->IsKindOf(RUNTIME_CLASS(CMUSHView)))
      	{
    		CMUSHView* pmyView = (CMUSHView*)pView;
        if (pmyView->m_ToolTip.m_hWnd)
    		  pmyView->m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_AUTOPOP, Value - 1);  // zero will be default  (-1)
    	  }	  // end if
      }  // end for
    } // end of OPT_FIX_TOOLTIP_VISIBLE

  if (OptionsTable [iItem].iFlags & OPT_FIX_TOOLTIP_START)
    {
    for(pos = GetFirstViewPosition (); pos != NULL;)
    	{
    	CView* pView = GetNextView(pos);
    	if (pView->IsKindOf(RUNTIME_CLASS(CMUSHView)))
      	{
    		CMUSHView* pmyView = (CMUSHView*)pView;
        if (pmyView->m_ToolTip.m_hWnd)
      		pmyView->m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, Value - 1);  // zero will be default  (-1)
    	  }	  // end if
      }  // end for
    } // end of OPT_FIX_TOOLTIP_START

  if (OptionsTable [iItem].iFlags & OPT_USE_MXP)
    {
    if (m_iUseMXP == eNoMXP && m_bMXP)
      MXP_Off (true);
    else if (m_iUseMXP == eUseMXP && !m_bMXP)
      MXP_On (false, true);   // not pueblo, manually on
    }

  if (OptionsTable [iItem].iFlags & OPT_UPDATE_INPUT_FONT)
    ChangeInputFont (m_input_font_height, 
                     m_input_font_name, 
                     m_input_font_weight, 
                     m_input_font_charset,
                     m_input_font_italic);

  if (OptionsTable [iItem].iFlags & OPT_UPDATE_OUTPUT_FONT)
    ChangeFont (m_font_height, 
                m_font_name, 
                m_font_weight, 
                m_font_charset,
                m_bShowBold,
                m_bShowItalic,
                m_bShowUnderline,
                m_iLineSpacing);

  if (OptionsTable [iItem].iFlags & OPT_UPDATE_VIEWS)
    UpdateAllViews (NULL);  


  return eOK;

  } // end of CMUSHclientDoc::SetOptionItem
Esempio n. 11
0
long CMUSHclientDoc::SetTriggerOption(LPCTSTR TriggerName, LPCTSTR OptionName, LPCTSTR Value) 
{
CString strTriggerName = TriggerName;
CString strValue = Value;
CTrigger * trigger_item;

  // trim spaces from name, make lower-case
  CheckObjectName (strTriggerName, false);

  if (!GetTriggerMap ().Lookup (strTriggerName, trigger_item))
    return eTriggerNotFound;

CString strOptionName = OptionName;

  strOptionName.MakeLower();
  strOptionName.TrimLeft ();
  strOptionName.TrimRight ();

int iItem;
int iResult = FindBaseOption (strOptionName, TriggerOptionsTable, iItem);

bool bChanged;

  if (iResult == eOK)
    {
    // this is a numeric option
    
    // for boolean options, accept "y" or "n"
    if (TriggerOptionsTable [iItem].iMinimum == 0 &&
      TriggerOptionsTable [iItem].iMaximum == 0)
      {
      if (strValue == "Y" || strValue == "y")
        Value = "1";
      else if (strValue == "N" || strValue == "n")
        Value = "0";
      }

    if (!IsNumber (Value, true))
       return eOptionOutOfRange;

    long iValue = atol (Value);

    if (m_CurrentPlugin &&
        (TriggerOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_WRITE))
    	return ePluginCannotSetOption;  // not available to plugin

    if (TriggerOptionsTable [iItem].iFlags & OPT_CANNOT_WRITE)
    	return ePluginCannotSetOption;  // not available for writing at all    

    iResult = SetBaseOptionItem (iItem,
                        TriggerOptionsTable,
                        NUMITEMS (TriggerOptionsTable),
                        (char *) trigger_item, 
                        iValue,
                        bChanged);

    if (bChanged)
      {
      if (!m_CurrentPlugin) // plugin mods don't really count
        SetModifiedFlag (TRUE);   // document has changed
      trigger_item->nUpdateNumber    = App.GetUniqueNumber ();   // for concurrency checks
      }

    if (strOptionName == "sequence")
      SortTriggers ();

    return iResult;

    }  // end of found
  else
    { // not numeric option, try alpha
    int iResult = FindBaseAlphaOption (strOptionName, TriggerAlphaOptionsTable, iItem);
    if (iResult == eOK)
      {

      // alpha option

      if (m_CurrentPlugin &&
          (TriggerAlphaOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_WRITE))
    	  return ePluginCannotSetOption;  // not available to plugin

      if (TriggerAlphaOptionsTable [iItem].iFlags & OPT_CANNOT_WRITE)
    	  return ePluginCannotSetOption;  // not available for writing at all    

      // ------ preliminary validation before setting the option

      // cannot have null match text
      if (strOptionName == "match" || 
          strOptionName == "ignore_case" ||
          strOptionName == "multi_line")
        {
        if (strValue.IsEmpty ())
          return eTriggerCannotBeEmpty;

        t_regexp * regexp = NULL;

        CString strRegexp; 

        if (trigger_item->bRegexp)
          strRegexp = strValue;
        else
          strRegexp = ConvertToRegularExpression (strValue);

        // compile regular expression
        try 
          {
          regexp = regcomp (strRegexp, (trigger_item->ignore_case ? PCRE_CASELESS : 0) |
                                       (trigger_item->bMultiLine  ? PCRE_MULTILINE : 0) |
                                       (m_bUTF_8 ? PCRE_UTF8 : 0)
                                       );
          }   // end of try
        catch(CException* e)
          {
          e->Delete ();
          return eBadRegularExpression;
          } // end of catch
      
        delete trigger_item->regexp;    // get rid of old one
        trigger_item->regexp = regexp;

        } // end of option "match"  
      else if (strOptionName == "script")
        {
  
        // get trigger dispatch ID

        if (GetScriptEngine () && !strValue.IsEmpty ())
          {
          DISPID dispid = DISPID_UNKNOWN;
          CString strMessage;
          dispid = GetProcedureDispid (strValue, "trigger", TriggerName, strMessage);
          if (dispid == DISPID_UNKNOWN)
            return eScriptNameNotLocated;
          trigger_item->dispid  = dispid;   // update dispatch ID
          }
        } // end of option "script"


      // set the option now

      iResult = SetBaseAlphaOptionItem (iItem,
                        TriggerAlphaOptionsTable,
                        NUMITEMS (TriggerAlphaOptionsTable),
                        (char *) trigger_item,  
                        strValue,
                        bChanged);

      if (bChanged)
        {
        if (!m_CurrentPlugin) // plugin mods don't really count
          SetModifiedFlag (TRUE);   // document has changed
        trigger_item->nUpdateNumber    = App.GetUniqueNumber ();   // for concurrency checks
        }

      return iResult;
      }  // end of found alpha option
    }  // end of not numeric option

 return eUnknownOption;
}   // end of SetTriggerOption
Esempio n. 12
0
VARIANT CMUSHclientDoc::GetTriggerOption(LPCTSTR TriggerName, LPCTSTR OptionName) 
{
CString strTriggerName = TriggerName;
CTrigger * trigger_item;

	VARIANT vaResult;
	VariantInit(&vaResult);

  vaResult.vt = VT_NULL;

  // trim spaces from name, make lower-case
  CheckObjectName (strTriggerName, false);

  vaResult.vt = VT_EMPTY;

  // see if trigger exists, if not return EMPTY
  if (!GetTriggerMap ().Lookup (strTriggerName, trigger_item))
	  return vaResult;

int iItem;
int iResult = FindBaseOption (OptionName, TriggerOptionsTable, iItem);

  
  if (iResult == eOK)
    {

    // numeric option

    if (m_CurrentPlugin &&
        (TriggerOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_READ))
    	return vaResult;  // not available to plugin

    long Value =  GetBaseOptionItem (iItem, 
                              TriggerOptionsTable, 
                              NUMITEMS (TriggerOptionsTable),
                              (char *) trigger_item);  

    SetUpVariantLong (vaResult, Value);
    }  // end of found numeric option
  else
    { // not numeric option, try alpha
    int iResult = FindBaseAlphaOption (OptionName, TriggerAlphaOptionsTable, iItem);
    if (iResult == eOK)
      {

      // alpha option

      if (m_CurrentPlugin &&
          (TriggerAlphaOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_READ))
    	  return vaResult;  // not available to plugin

      CString strValue =  GetBaseAlphaOptionItem (iItem, 
                                                 TriggerAlphaOptionsTable,
                                                 NUMITEMS (TriggerAlphaOptionsTable),
                                                 (char *) trigger_item);

      SetUpVariantString (vaResult, strValue);
      }  // end of found
    }

	return vaResult;
} // end of GetTriggerOption
Esempio n. 13
0
CMUSHclientDoc::CMUSHclientDoc()
  :	m_eventScriptFileChanged(FALSE, TRUE)

{    // constructor

int i;

  // each document will have a unique number
  m_iUniqueDocumentNumber = App.GetUniqueNumber ();

  m_whenWorldStarted = CTime::GetCurrentTime();
  QueryPerformanceCounter (&m_whenWorldStartedHighPrecision);

  AllocateConfigurationArrays ();

  m_bTrace = false;   // not tracing yet

// note - these initialisations merely make the hash lookup more efficient.
// until v 3.21 they were the default of 20, so this should help somewhat
// The number should be a prime number, hence the strange figures.

  m_VariableMap.InitHashTable (997); // allow for 1000 variables (at least)
  m_AliasMap.InitHashTable (293);    // probably won't have many more than 300 aliases
  m_TriggerMap.InitHashTable (293);  // probably won't have many more than 300 triggers
  m_TimerMap.InitHashTable (293);    // probably won't have many more than 300 timers

  SetDefaults (false);        // set up numeric/boolean defaults
  SetAlphaDefaults (false);   // set up alpha defaults

  m_strWorldID = GetUniqueID ();      // default world ID

  m_CurrentPlugin = NULL;     // no plugin active right now

  m_iBackgroundMode = 0;
  m_iForegroundMode = 0;
  m_iBackgroundColour = NO_COLOUR;

  m_TextRectangle = CRect (0, 0, 0, 0);
  m_TextRectangleBorderOffset = 0;           
  m_TextRectangleBorderColour = 0;           
  m_TextRectangleBorderWidth = 0;            
  m_TextRectangleOutsideFillColour = 0;      
  m_TextRectangleOutsideFillStyle = 0;   

  m_iCurrentActionSource = eUnknownActionSource;
  m_nBytesIn = 0;
  m_nBytesOut = 0;
  m_bTabCompleteFunctions = true;

  m_iTriggersEvaluatedCount = 0; 
  m_iTriggersMatchedCount = 0;   
  m_iAliasesEvaluatedCount = 0;  
  m_iAliasesMatchedCount = 0;    
  m_iTimersFiredCount = 0;       
  m_iTriggersMatchedThisSessionCount = 0;   
  m_iAliasesMatchedThisSessionCount = 0;    
  m_iTimersFiredThisSessionCount = 0;       

  m_bLoaded = false;
  m_bMapping = false;
  m_bRemoveMapReverses = true;
  m_MapFailureRegexp = NULL;
  m_bPluginProcessingCommand = false;
  m_bPluginProcessingSend = false;
  m_bPluginProcessingSent = false;
  m_iLastCommandCount = 0;
  m_iExecutionDepth = 0;
  m_iNextChatID = 0;
  m_tLastMessageTime = 0;
  m_tLastGroupMessageTime = 0;
  m_bOmitFromCommandHistory = false;
  m_bUTF_8 = false;
  m_bWorldClosing = false;
  m_bInSendToScript = true;

  m_bInPlaySoundFilePlugin = false;
  m_bInCancelSoundFilePlugin = false;

  m_strStatusMessage = Translate ("Ready");
  m_bShowingMapperStatus = false;
  m_iMCCP_type = 0;
  m_bSupports_MCCP_2 = false;
  m_bNoEcho = false;
  m_bDebugIncomingPackets = false;
  m_iInputPacketCount = 0;
  m_iOutputPacketCount = 0;
  m_iUTF8ErrorCount = 0;
  m_lastGoTo = 1;
  m_bNAWS_wanted = false;
  m_bCHARSET_wanted = false;
  m_bSuppressNewline = false;
  m_echo_colour = SAMECOLOUR;
  m_bAlwaysRecordCommandHistory = false;
  m_bDoNotShowOutstandingLines = false;
  m_bDoNotTranslateIACtoIACIAC = false;
  m_bAutoResizeCommandWindow = false;
  m_bLogScriptErrors = false;
  m_bOmitSavedDateFromSaveFiles = false;
  m_iAutoResizeMinimumLines = 1;   
  m_iAutoResizeMaximumLines = 20;   
  m_bDoNotAddMacrosToCommandHistory = false;
  m_bCopySelectionToClipboard = false;
  m_bCarriageReturnClearsLine = false;
  m_bConvertGAtoNewline = false;
  m_bSendMXP_AFK_Response = true;
  m_bMudCanChangeOptions = true;
//  m_bShowGridLinesInListViews = true;  // NB - app-wide :P
  m_bEnableSpamPrevention = false;
  m_strSpamMessage = "look";
  m_iSpamLineCount = 20;
  m_iLastOutgoingChatPort = DEFAULT_CHAT_PORT;
  m_bScrollBarWanted = TRUE;

  m_iSocksProcessing = 0;   // no socks processing wanted
  m_iProxyServerPort = 1080; // default socks port

  // deprecated options  - set to zero for saving comparison (for XML testing)

  m_page_colour = 0;
  m_whisper_colour= 0;
  m_mail_colour = 0;
  m_game_colour = 0;
  m_chat_colour = 0;
  m_remove_channels1 = 0;
  m_remove_channels2 = 0;
  m_remove_pages= 0;
  m_remove_whispers = 0;
  m_remove_set= 0;
  m_remove_mail = 0;
  m_remove_game = 0;

  // things I found to be not initialised in version 3.43

  m_timestamps = 0;
  m_iFlags1 = 0;
  m_iFlags2 = 0;
  m_iListMode = 0;
  m_iListCount = 0;
  m_iMXP_previousMode = eMXP_open;
  m_code = 0;

  // sound buffers
  for (i = 0; i < MAX_SOUND_BUFFERS; i++)
    m_pDirectSoundSecondaryBuffer [i] = NULL;

  /*---------------------------------------------------------
  I want to be able to time speed walking delays (for pulling things
  out of the list, so I need a window that can take timer events, however
  a CDocument isn't a window. Thus, I'll make a hidden window for this
  specific purpose.

  I previously had speed walking tied to the CSendView window but this was
  pretty crappy, because you could have multiple send views, thus the timers
  would be all over the shop, and it was very fiddly when firing a "send" from
  a trigger, because a trigger is not related to a particular send view.

  --------------------------------------------------------- */


  // create window that we can use for firing timers
  m_pTimerWnd = new CTimerWnd (this);

	m_pTimerWnd->m_hWnd = NULL;
	if (!m_pTimerWnd->CreateEx(0, AfxRegisterWndClass(0),
		_T("Document timer window"),
		WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))
	  {
		TRACE0("Warning: unable to create document timer window!\n");
		AfxThrowResourceException();
  	}
	ASSERT(m_pTimerWnd->m_hWnd != NULL);
	ASSERT(CWnd::FromHandlePermanent(m_pTimerWnd->m_hWnd) == m_pTimerWnd);


  for (i = 0; i < 8; i++)  
    m_font [i] = NULL;
  m_input_font = NULL;
  m_FontHeight = 0;
  m_FontWidth = 0;
  m_InputFontHeight = 0;
  m_InputFontWidth = 0;
  m_total_lines = 0;
  m_newlines_received = 0;
  m_last_line_with_IAC_GA = 0;
  m_nTotalLinesSent = 0;
  m_nTotalLinesReceived = 0;
  m_phase = NONE;
  m_ttype_sequence = 0;

  m_bVariablesChanged = false;

  m_view_number = 0;
  m_LastFlushTime = CTime::GetCurrentTime();

  m_bCompress = false;    // no compression yet
  m_bCompressInitOK = false;
  m_CompressInput = NULL;
  m_CompressOutput = NULL;

  // initialise zlib decompression 

  m_zCompress.next_in = Z_NULL; 
  m_zCompress.avail_in = 0; 
  m_zCompress.zalloc = Z_NULL; 
  m_zCompress.zfree = Z_NULL; 
  m_zCompress.opaque = Z_NULL; 
  m_nTotalUncompressed = 0;
  m_nTotalCompressed = 0;
  m_iCompressionTimeTaken = 0;
  m_nCompressionOutputBufferSize = COMPRESS_BUFFER_LENGTH;  // initial value

  // we will defer initialising zlib until we really have to

	m_pSocket = NULL;
  m_pChatListenSocket = NULL;    // no listening socket
  m_logfile = NULL;
  m_match_width = 30;

  m_bSelected = true;

  m_bNotesInRGB = false;    // notes are in palette colour right now
  m_iNoteStyle = NORMAL;    // notes are not bold right now

// MXP

  m_bMXP = false;   // no MXP yet
  m_bPuebloActive = false; // no Pueblo yet either <evil grin>
  m_bInParagraph = false;
  m_bMXP_script = false;
  m_bPreMode = false;
  m_iMXP_defaultMode = eMXP_open;
  m_iMXP_mode = m_iMXP_defaultMode;
  m_cLastChar = 0;

  // initial styles

  m_iFlags = 0;
  m_iForeColour = WHITE;
  m_iBackColour = BLACK;

  if (m_bCustom16isDefaultColour)
    {
    m_iForeColour = 15;   // use custom colour 16
    m_iBackColour = 15;
    m_iFlags |= COLOUR_CUSTOM;
    }

//  m_normalcolour [BLACK]    = RGB (192, 192, 192) | PALETTE;    // black   
//  m_normalcolour [RED]      = RGB (128,   0,  64) | PALETTE;    // red     
//  m_normalcolour [GREEN]    = RGB (128, 255, 128) | PALETTE;    // green   
//  m_normalcolour [YELLOW]   = RGB (255, 255, 128) | PALETTE;    // yellow  
//  m_normalcolour [BLUE]     = RGB (  0, 255, 255) | PALETTE;    // blue    
//  m_normalcolour [MAGENTA]  = RGB (255,   0, 128) | PALETTE;    // magenta 
//  m_normalcolour [CYAN]     = RGB (128, 255, 255) | PALETTE;    // cyan    
//  m_normalcolour [WHITE]    = RGB (  0, 128,   0) | PALETTE;    // white   

//  m_boldcolour [BLACK]      = RGB (  0,   0,   0) |  PALETTE;    // black   
//  m_boldcolour [RED]        = RGB (255,   0,   0) |  PALETTE;    // red     
//  m_boldcolour [GREEN]      = RGB (  0, 255,   0) |  PALETTE;    // green   
//  m_boldcolour [YELLOW]     = RGB (255, 255,   0) |  PALETTE;    // yellow  
//  m_boldcolour [BLUE]       = RGB (  0,  64, 128) |  PALETTE;    // blue    
//  m_boldcolour [MAGENTA]    = RGB (255,   0, 255) |  PALETTE;    // magenta 
//  m_boldcolour [CYAN]       = RGB (  0, 255, 255) |  PALETTE;    // cyan    
//  m_boldcolour [WHITE]      = RGB (255, 255, 255) |  PALETTE;    // white   

  // better use ANSI colours as the default

  SetDefaultAnsiColours (m_normalcolour, m_boldcolour);

  // and some nice custom colours
  SetDefaultCustomColours (m_customtext, m_customback);

  // default custom colour names
  for (i = 0; i < NUMITEMS (m_strCustomColourName); i++)
    m_strCustomColourName [i].Format ("Custom%i", i + 1);

  for (i = 0; i < NUMITEMS (m_macro_type); i++)
    m_macro_type [i] = SEND_NOW;

// printer styles for printing from the screen

  for (i = 0; i < 8; i++)
    {
     m_nNormalPrintStyle [i] = 0;
     m_nBoldPrintStyle [i] = FONT_BOLD;
    }

  m_bUseDefaultOutputFont = !App.m_strDefaultOutputFont.IsEmpty (); 

  m_bUseDefaultColours   = !App.m_strDefaultColoursFile.IsEmpty ();   
  m_bUseDefaultTriggers  = !App.m_strDefaultTriggersFile.IsEmpty ();   
  m_bUseDefaultAliases   = !App.m_strDefaultAliasesFile.IsEmpty ();    
  m_bUseDefaultMacros    = !App.m_strDefaultMacrosFile.IsEmpty ();     
  m_bUseDefaultTimers    = !App.m_strDefaultTimersFile.IsEmpty ();     
  m_bUseDefaultInputFont = !App.m_strDefaultInputFont.IsEmpty ();  
  
  setupstrings ();

  m_tStatusTime = CTime::GetCurrentTime(); 
  m_tConnectTime = CTime::GetCurrentTime();
  m_tLastPlayerInput = CTime::GetCurrentTime();
  m_timeScriptFileMod = 0;

  m_tsConnectDuration = CTimeSpan (0, 0, 0, 0);

  m_iConnectPhase = eConnectNotConnected;
                                      
  gdoccount++;

  m_pActiveCommandView = NULL;
  m_pActiveOutputView = NULL;

  m_new_lines = 0;

  m_last_prefs_page = 1;

  App.m_bUpdateActivity = TRUE;

// for looking up host names

  ZeroMemory (&m_sockAddr, sizeof m_sockAddr);
  ZeroMemory (&m_ProxyAddr, sizeof m_ProxyAddr);
  m_hNameLookup = NULL;
  m_pGetHostStruct = NULL;
  m_pLinePositions = NULL;

  m_pCurrentLine = NULL;
  m_total_lines = 0;

  // set up the dialog box headings for the finding dialogs
  m_DisplayFindInfo.m_strTitle    = "Find in output buffer...";
  m_MacrosFindInfo.m_strTitle     = "Find macro...";
  m_AliasesFindInfo.m_strTitle    = "Find alias...";
  m_TriggersFindInfo.m_strTitle   = "Find trigger...";
  m_TimersFindInfo.m_strTitle     = "Find timer...";
  m_VariablesFindInfo.m_strTitle  = "Find variable...";
  m_NotesFindInfo.m_strTitle  = "Find in notes...";
  m_RecallFindInfo.m_strTitle    = "Recall...";
          
  m_bRecallCommands = true;
  m_bRecallOutput = true;
  m_bRecallNotes = true;

  // set up column counts for use in the loading and saving of the column orders etc.
  m_MacrosFindInfo.m_iControlColumns    = CPrefsP6::eColumnCount;
  m_AliasesFindInfo.m_iControlColumns   = CPrefsP7::eColumnCount;
  m_TriggersFindInfo.m_iControlColumns  = CPrefsP8::eColumnCount;
  m_TimersFindInfo.m_iControlColumns    = CPrefsP16::eColumnCount;
  m_VariablesFindInfo.m_iControlColumns = CPrefsP18::eColumnCount;

  m_bDisconnectOK = true;    // so we don't try to reconnect to prematurely
  
  m_iMXPerrors = 0;     
  m_iMXPtags = 0;       
  m_iMXPentities = 0;   

  // scripting support

	EnableAutomation();     // not needed?

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

  m_ScriptEngine = NULL;

  m_bInScriptFileChanged = false;
  m_pThread = NULL;
  m_bSyntaxErrorOnly = false;

  m_dispidWorldOpen = DISPID_UNKNOWN;
  m_dispidWorldClose = DISPID_UNKNOWN;
  m_dispidWorldSave = DISPID_UNKNOWN;
  m_dispidWorldConnect = DISPID_UNKNOWN;
  m_dispidWorldDisconnect = DISPID_UNKNOWN;
  m_dispidWorldGetFocus = DISPID_UNKNOWN;
  m_dispidWorldLoseFocus = DISPID_UNKNOWN;
  m_dispidOnMXP_Start = DISPID_UNKNOWN;        
  m_dispidOnMXP_Stop = DISPID_UNKNOWN;         
  m_dispidOnMXP_OpenTag = DISPID_UNKNOWN;      
  m_dispidOnMXP_CloseTag = DISPID_UNKNOWN;     
  m_dispidOnMXP_SetVariable = DISPID_UNKNOWN;  
  m_dispidOnMXP_Error = DISPID_UNKNOWN;    

  m_iScriptTimeTaken = 0;   // time taken on scripts

  m_bPluginProcessesOpenTag = false;    
  m_bPluginProcessesCloseTag = false;   
  m_bPluginProcessesSetVariable = false;
  m_bPluginProcessesSetEntity = false;
  m_bPluginProcessesError = false;      

  ZeroMemory (&m_bClient_sent_IAC_DO,   sizeof m_bClient_sent_IAC_DO);
  ZeroMemory (&m_bClient_sent_IAC_DONT, sizeof m_bClient_sent_IAC_DONT);
  ZeroMemory (&m_bClient_sent_IAC_WILL, sizeof m_bClient_sent_IAC_WILL);
  ZeroMemory (&m_bClient_sent_IAC_WONT, sizeof m_bClient_sent_IAC_WONT);

  ZeroMemory (&m_bClient_got_IAC_DO,   sizeof m_bClient_got_IAC_DO);
  ZeroMemory (&m_bClient_got_IAC_DONT, sizeof m_bClient_got_IAC_DONT);
  ZeroMemory (&m_bClient_got_IAC_WILL, sizeof m_bClient_got_IAC_WILL);
  ZeroMemory (&m_bClient_got_IAC_WONT, sizeof m_bClient_got_IAC_WONT);

  m_nCount_IAC_DO = 0;      
  m_nCount_IAC_DONT = 0;    
  m_nCount_IAC_WILL = 0;    
  m_nCount_IAC_WONT = 0;    
  m_nCount_IAC_SB = 0;      

  m_iOutputWindowRedrawCount = 0;

  m_bTreeviewTriggers = true;      
  m_bTreeviewAliases = true;       
  m_bTreeviewTimers = true;        

  // set up some default triggers for MUSHes

  /*
  The parameter are:

  Trigger Name
  Match Text 
  Response Text 
  Flags 
  Colour 
  Wildcard to copy to clipboard
  Sound File Name 
  Script Name
  */

  /*  No, don't. It just confuses Diku MUD people

  AddTrigger ("Game_messages", "GAME:*", "", eEnabled, 0, 0, "", ""); 
  AddTrigger ("Page_poses", "From afar,*", "", eEnabled, 1, 0, "", ""); 
  AddTrigger ("Pages", "^\\w+ pages.*$", "", eEnabled | eTriggerRegularExpression, 1, 0, "", ""); 
  AddTrigger ("Whisper_poses", "You sense:*", "", eEnabled, 2, 0, "", ""); 
  AddTrigger ("Whispers", "^\\w+ whispers.*$", "", eEnabled | eTriggerRegularExpression, 2, 0, "", ""); 
  AddTrigger ("Mail_messages", "MAIL:*", "", eEnabled, 3, 0, "", ""); 
  AddTrigger ("Chat_channel_1", "^\\<.+?\\>.*$", "", eEnabled | eTriggerRegularExpression, 4, 0, "", ""); 
  AddTrigger ("Chat_channel_2", "^\\[.+?\\].*$", "", eEnabled | eTriggerRegularExpression, 4, 0, "", ""); 
  */

  m_nextAcceleratorCommand = ACCELERATOR_FIRST_COMMAND;
  m_accelerator = NULL;

}  // end of CMUSHclientDoc::CMUSHclientDoc()
Esempio n. 14
0
BSTR CMUSHclientDoc::ExportXML(short Type, LPCTSTR Name) 
{
	CString strResult;
  CString strName = Name;

  // trim spaces, force name to lower-case
  CheckObjectName (strName, false);

  char * p = NULL;

  try
    {
    CMemFile f;      // open memory file for writing
    CArchive ar(&f, CArchive::store);


    // see if trigger exists, if not return EMPTY

    switch (Type)
      {
      case 0:   // trigger
        {
        CTrigger * t;
        if (GetTriggerMap ().Lookup (strName, t))
          {
          Save_Header_XML (ar, "triggers", false);
          Save_One_Trigger_XML (ar, t);
          Save_Footer_XML (ar, "triggers");
          } // end of item existing
        }
        break;

      case 1:   // alias
        {
        CAlias * t;
        if (GetAliasMap ().Lookup (strName, t))
          {
          Save_Header_XML (ar, "aliases", false);
          Save_One_Alias_XML (ar, t);
          Save_Footer_XML (ar, "aliases");
          } // end of item existing
        }
        break;

      case 2:   // timer
        {
        CTimer * t;
        if (GetTimerMap ().Lookup (strName, t))
          {
          Save_Header_XML (ar, "timers", false);
          Save_One_Timer_XML (ar, t);
          Save_Footer_XML (ar, "timers");
          } // end of item existing
        }
        break;

      case 3:   // macro
        {
        for (int i = 0; i < NUMITEMS (strMacroDescriptions); i++)
          {
          if (strMacroDescriptions [i].CompareNoCase (strName) == 0)
            {
            Save_Header_XML (ar, "macros", false);
            Save_One_Macro_XML (ar, i);
            Save_Footer_XML (ar, "macros");
            } // end of item existing
          } // end of finding which one
        }
        break;

      case 4:   // variable
        {
        CVariable * t;
        if (GetVariableMap ().Lookup (strName, t))
          {
          Save_Header_XML (ar, "variables", false);
          Save_One_Variable_XML (ar, t);
          Save_Footer_XML (ar, "variables");
          } // end of item existing
        }
        break;

      case 5:   // keypad
        {
        for (int i = 0; i < NUMITEMS (strKeypadNames); i++)
          {
          if (strKeypadNames [i].CompareNoCase (strName) == 0)
            {
            Save_Header_XML (ar, "keypad", false);
            Save_One_Keypad_XML (ar, i);
            Save_Footer_XML (ar, "keypad");
            } // end of item existing
          } // end of finding which one

        }
        break;

      } // end of switch

    ar.Close();

    int nLength = f.GetLength ();
    p = (char *) f.Detach ();

    strResult = CString (p, nLength);

    free (p);   // remove memory allocated in CMemFile
    p = NULL;

    }   // end of try block

  catch (CException* e)
	  {
    if (p)
      free (p);   // remove memory allocated in CMemFile
	  e->Delete();
    strResult.Empty ();
	  }   // end of catch


	return strResult.AllocSysString();
}   // end of CMUSHclientDoc::ExportXML
Esempio n. 15
0
long CMUSHclientDoc::SetTimerOption(LPCTSTR TimerName, LPCTSTR OptionName, LPCTSTR Value)
{
    CString strTimerName = TimerName;
    CString strValue = Value;
    CTimer * Timer_item;

    // trim spaces from name, make lower-case
    CheckObjectName (strTimerName, false);

    if (!GetTimerMap ().Lookup (strTimerName, Timer_item))
        return eTimerNotFound;

    CString strOptionName = OptionName;

    strOptionName.MakeLower();
    strOptionName.TrimLeft ();
    strOptionName.TrimRight ();

    int iItem;
    int iResult = FindBaseOption (strOptionName, TimerOptionsTable, iItem);

    bool bChanged;

    if (iResult == eOK)
    {
        // this is a numeric option

        // for boolean options, accept "y" or "n"
        if (TimerOptionsTable [iItem].iMinimum == 0 &&
                TimerOptionsTable [iItem].iMaximum == 0)
        {
            if (strValue == "Y" || strValue == "y")
                Value = "1";
            else if (strValue == "N" || strValue == "n")
                Value = "0";
        }

        long iValue = 0;
        double fValue = 0;

        if (strOptionName == "second")
            fValue = atof (Value);
        else
        {
            if (!IsNumber (Value, true))
                return eOptionOutOfRange;

            iValue = atol (Value);
        }

        if (m_CurrentPlugin &&
                (TimerOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_WRITE))
            return ePluginCannotSetOption;  // not available to plugin

        if (TimerOptionsTable [iItem].iFlags & OPT_CANNOT_WRITE)
            return ePluginCannotSetOption;  // not available for writing at all

        iResult = SetBaseOptionItem (iItem,
                                     TimerOptionsTable,
                                     NUMITEMS (TimerOptionsTable),
                                     (char *) Timer_item,
                                     iValue,
                                     bChanged);

        if (bChanged)
        {
            if (!m_CurrentPlugin) // plugin mods don't really count
                SetModifiedFlag (TRUE);   // document has changed
            Timer_item->nUpdateNumber    = App.GetUniqueNumber ();   // for concurrency checks
        }

        if (iResult == eOK && Timer_item->iType == CTimer::eInterval)
        {   // need to set "every" time, not "at" time
            if (strOptionName == "hour")
            {
                Timer_item->iEveryHour = iValue;
                ResetOneTimer (Timer_item);
            } // end of option "hour"
            else if (strOptionName == "minute")
            {
                Timer_item->iEveryMinute = iValue;
                ResetOneTimer (Timer_item);
            } // end of option "minute"
            else if (strOptionName == "second")
            {
                Timer_item->fEverySecond = fValue;
                ResetOneTimer (Timer_item);
            } // end of option "second"

        } // end of need to fiddle with hour/minute/second

        // need to reset if we are changing this
        if (strOptionName == "at_time" && bChanged)
        {
            // copy from at to every or vice-versa
            if (Timer_item->iType == CTimer::eInterval)
            {
                Timer_item->iEveryHour    = Timer_item->iAtHour;
                Timer_item->iEveryMinute  = Timer_item->iAtHour;
                Timer_item->fEverySecond  = Timer_item->fAtSecond;
            }
            else
            {
                Timer_item->iAtHour    = Timer_item->iEveryHour;
                Timer_item->iAtMinute  = Timer_item->iEveryHour;
                Timer_item->fAtSecond  = Timer_item->fEverySecond;
            }
            ResetOneTimer (Timer_item);
        }

        return iResult;

    }  // end of found
    else
    {   // not numeric option, try alpha
        int iResult = FindBaseAlphaOption (strOptionName, TimerAlphaOptionsTable, iItem);
        if (iResult == eOK)
        {

            // alpha option

            if (m_CurrentPlugin &&
                    (TimerAlphaOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_WRITE))
                return ePluginCannotSetOption;  // not available to plugin

            if (TimerAlphaOptionsTable [iItem].iFlags & OPT_CANNOT_WRITE)
                return ePluginCannotSetOption;  // not available for writing at all

            // ------ preliminary validation before setting the option

            if (strOptionName == "script")
            {

                // get Timer dispatch ID

                if (GetScriptEngine () && !strValue.IsEmpty ())
                {
                    DISPID dispid = DISPID_UNKNOWN;
                    CString strMessage;
                    dispid = GetProcedureDispid (strValue, "Timer", TimerName, strMessage);
                    if (dispid == DISPID_UNKNOWN)
                        return eScriptNameNotLocated;
                    Timer_item->dispid  = dispid;   // update dispatch ID
                }
            } // end of option "script"


            // set the option now

            iResult = SetBaseAlphaOptionItem (iItem,
                                              TimerAlphaOptionsTable,
                                              NUMITEMS (TimerAlphaOptionsTable),
                                              (char *) Timer_item,
                                              strValue,
                                              bChanged);

            if (bChanged)
            {
                if (!m_CurrentPlugin) // plugin mods don't really count
                    SetModifiedFlag (TRUE);   // document has changed
                Timer_item->nUpdateNumber    = App.GetUniqueNumber ();   // for concurrency checks
            }

            return iResult;
        }  // end of found alpha option
    }  // end of not numeric option

    return eUnknownOption;
} // end of SetTimerOption
Esempio n. 16
0
VARIANT CMUSHclientDoc::GetTimerOption(LPCTSTR TimerName, LPCTSTR OptionName)
{
    CString strTimerName = TimerName;
    CTimer * Timer_item;

    VARIANT vaResult;
    VariantInit(&vaResult);

    vaResult.vt = VT_NULL;

    // trim spaces from name, make lower-case
    CheckObjectName (strTimerName, false);

    vaResult.vt = VT_EMPTY;

    // see if Timer exists, if not return EMPTY
    if (!GetTimerMap ().Lookup (strTimerName, Timer_item))
        return vaResult;


    CString strOptionName = OptionName;

    strOptionName.MakeLower();
    strOptionName.TrimLeft ();
    strOptionName.TrimRight ();

    int iItem;
    int iResult = FindBaseOption (strOptionName, TimerOptionsTable, iItem);


    if (iResult == eOK)
    {

        // numeric option

        if (m_CurrentPlugin &&
                (TimerOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_READ))
            return vaResult;  // not available to plugin

        double Value;

        // this is a pest!
        if (strOptionName == "hour")
        {
            if (Timer_item->iType == CTimer::eInterval)
                Value = Timer_item->iEveryHour;
            else
                Value = Timer_item->iAtHour;
        } // end of option "hour"
        else if (strOptionName == "minute")
        {
            if (Timer_item->iType == CTimer::eInterval)
                Value = Timer_item->iEveryMinute;
            else
                Value = Timer_item->iAtMinute;
        } // end of option "minute"
        else if (strOptionName == "second")
        {
            if (Timer_item->iType == CTimer::eInterval)
                Value = Timer_item->fEverySecond;
            else
                Value = Timer_item->fAtSecond;
        } // end of option "second"
        else
            Value =  GetBaseOptionItem (iItem,
                                        TimerOptionsTable,
                                        NUMITEMS (TimerOptionsTable),
                                        (char *) Timer_item);

        SetUpVariantDouble (vaResult, Value);
    }  // end of found numeric option
    else
    {   // not numeric option, try alpha
        int iResult = FindBaseAlphaOption (OptionName, TimerAlphaOptionsTable, iItem);
        if (iResult == eOK)
        {

            // alpha option

            if (m_CurrentPlugin &&
                    (TimerAlphaOptionsTable [iItem].iFlags & OPT_PLUGIN_CANNOT_READ))
                return vaResult;  // not available to plugin

            CString strValue =  GetBaseAlphaOptionItem (iItem,
                                TimerAlphaOptionsTable,
                                NUMITEMS (TimerAlphaOptionsTable),
                                (char *) Timer_item);

            SetUpVariantString (vaResult, strValue);
        }  // end of found
    }

    return vaResult;
} // end of GetTimerOption