#include "stdafx.h"
#include "mainfrm.h"
#include "MUSHclient.h"
#include "doc.h"
#include "errors.h"
#include "winplace.h"
#include "TextDocument.h"
#include "TextView.h"
#include "sendvw.h"
#include "DebugLuaDlg.h"

#ifdef USE_LUA

const char mushclient_typename[] = "mushclient.world";

/*------------------------------------------------------------------------
   This whole file is basically "glue" routines to bind the Lua calls to the
   normal MUSHclient script calls. As far as possible the calls will be compatible
   with existing ones.
 
   A couple of exceptions will be things like GetAlias which return results 
   by reference, these are changed to return multiple results.

   Written: 20th November 2004 by Nick Gammon

   Multiple-world support
   ----------------------

   The functions will automatically check if the first argument is a userdatum, 
   and if so, check that it is a mushclient.world userdatum.

   This lets you direct commands to other worlds, like this:

   other = world.GetWorld ("my other world")

   world.Note (other, "hello there")
   world.AddMapperComment (other, "this is a comment")
   
  ------------------------------------------------------------------------ */

// same as luaL_checkudata but just returns NULL if not correct type

LUALIB_API void *isudata (lua_State *L, int ud, const char *tname) {
  void *p = lua_touserdata(L, ud);
  if (p != NULL) {  /* value is a userdata? */
    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */
      int bCorrectType = lua_rawequal(L, -1, -2);
      lua_pop(L, 2);  /* remove both metatables */
      if (bCorrectType) /* does it have the correct mt? */
        return p;
    }   // has metatable
  }  // is userdata
  return NULL;  /* to avoid warnings */
}


// checks user data is mushclient.doc, and returns pointer to world
static CMUSHclientDoc *doc (lua_State *L) 
  { 
CMUSHclientDoc **ud = (CMUSHclientDoc **) isudata (L, 1, mushclient_typename);

  // if first argument is a world userdatum, take that as our world

  if (ud)
    {
    CMUSHclientDoc * pWantedDoc = *ud;
    luaL_argcheck(L, ud != NULL, 1, "'world' expected");
    lua_remove (L, 1);    // remove the userdata, we don't need it now

    // for safety, check that world still exists
    for (POSITION docPos = App.m_pWorldDocTemplate->GetFirstDocPosition();
        docPos != NULL; )
      {
      CMUSHclientDoc * pDoc = (CMUSHclientDoc *) App.m_pWorldDocTemplate->GetNextDoc(docPos);

      if (pDoc == pWantedDoc)
        return pDoc;
      } // end of doing each document

    luaL_error (L, "world is no longer available");
    }

 // retrieve our state
  CMUSHclientDoc * pDoc;
  
  /* retrieve the document */
  lua_pushstring(L, DOCUMENT_STATE);  /* push address */
  lua_gettable(L, LUA_ENVIRONINDEX);  /* retrieve value */

  pDoc = (CMUSHclientDoc *) lua_touserdata(L, -1);  /* convert to data */
  lua_pop(L, 1);  /* pop result */

  return pDoc;
  }

// helper function for pushing results returned by normal MUSHclient methods
// (stored in a variant)

int pushVariant (lua_State *L, COleVariant & v)
  {
  switch (v.vt)
    {
    case VT_BSTR:
      lua_pushstring (L, CString (v.bstrVal));
      break;
    case VT_I2:
      lua_pushnumber (L, v.iVal);
      break;
    case VT_I4:
      lua_pushnumber (L, v.lVal);
      break;
    case VT_R4:
      lua_pushnumber (L, v.fltVal);
      break;
    case VT_R8:
      lua_pushnumber (L, v.dblVal);
      break;
    case VT_BOOL:
      lua_pushboolean (L, v.boolVal);
      break;
    case VT_DATE:
      {
// maybe not, let the user format the date
//      COleDateTime d (v.date);
//      lua_pushstring (L, d.Format (0, 0));

//      lua_pushnumber (L, v.date);

      COleDateTime dt (v.date);   // convert to  COleDateTime

      SYSTEMTIME sysTime;

      dt.GetAsSystemTime (sysTime);  // now get as SYSTEMTIME
      CTime tm (sysTime);         // import into CTime

      lua_pushnumber (L, tm.GetTime ());  // return as Lua-style system time

      break;
      }

    case (VT_ARRAY + VT_VARIANT): // array of variants
      {
      lua_newtable(L);                                                            

      COleSafeArray sa (&v);
      long lLBound, lUBound;
      sa.GetLBound(1, &lLBound);
      sa.GetUBound(1, &lUBound);
      VARIANT val;
      int extra = 0;
      if (lLBound == 0)
        extra = 1;
      for (int i = lLBound; i <= lUBound; i++)
        {
        long index[2];
        index [0] = i;
        index [1] = 0;
        sa.GetElement(index, &val);
        COleVariant element (val);
        pushVariant (L, element);   // recurse to push the element value
        lua_rawseti(L, -2, i + extra);  // make 1-relative
        }   // end of doing each row
      luaL_setn (L, -1, i + extra - 1);   // set table size now
      }   // end of VT_ARRAY
      break;

    default:
      lua_pushnil (L);
      break;
    }  // end of switch on type
  return 1;  // number of result fields
  } // end of pushVariant

// helper function for pushing results returned by normal MUSHclient methods
// (stored in a BSTR)

int pushBstr (lua_State *L, BSTR & str)
  {
  lua_pushstring (L, CString (str));
  SysFreeString (str);
  return 1;  // number of result fields
  }   // end of pushBstr

// helper function for things like print, note, send etc. to combine all arguments
// into a string

string concatArgs (lua_State *L, const char * delimiter = "", const int first = 1)
  {
  int n = lua_gettop(L);  /* number of arguments */
  int i;
  string sOutput;
  lua_getglobal(L, "tostring");
  for (i= first; i<=n; i++) 
    {
    const char *s;
    lua_pushvalue(L, -1);  /* function to be called */
    lua_pushvalue(L, i);   /* value to print */
    lua_call(L, 1, 1);
    s = lua_tostring(L, -1);  /* get result */
    if (s == NULL)
      luaL_error(L, "`tostring' must return a string to `print'");
        
    if (i>1)
      sOutput += delimiter;
    sOutput += s;
    lua_pop(L, 1);  /* pop result */
    }

  return sOutput;

  } // end of concatArgs

static void GetVariableListHelper (lua_State *L, CMUSHclientDoc *pDoc)
  {
  lua_newtable(L);                                                            

  for (POSITION pos = pDoc->GetVariableMap ().GetStartPosition(); pos; )
    {
    CString strVariableName;
    CVariable * variable_item;

    pDoc->GetVariableMap ().GetNextAssoc (pos, strVariableName, variable_item);

    lua_pushstring (L, strVariableName);
    lua_pushstring (L, variable_item->strContents);
    lua_rawset(L, -3);
    }      // end of looping through each Variable

  } // end of GetVariableListHelper

//----- My checking routines that do not witter on about "bad self" -----


LUALIB_API int my_argerror (lua_State *L, int narg, const char *extramsg) {
  lua_Debug ar;
  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
    return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
  lua_getinfo(L, "n", &ar);
  if (ar.name == NULL)
    ar.name = "?";
  return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
                        narg, ar.name, extramsg);
}

LUALIB_API int my_typerror (lua_State *L, int narg, const char *tname) {
  const char *msg = lua_pushfstring(L, "%s expected, got %s",
                                    tname, luaL_typename(L, narg));
  return my_argerror(L, narg, msg);
}


static void my_tag_error (lua_State *L, int narg, int tag) {
  my_typerror(L, narg, lua_typename(L, tag));
}

LUALIB_API const char *my_checklstring (lua_State *L, int narg, size_t *len) {
  const char *s = lua_tolstring(L, narg, len);
  if (!s) my_tag_error(L, narg, LUA_TSTRING);
  return s;
}


LUALIB_API const char *my_optlstring (lua_State *L, int narg,
                                        const char *def, size_t *len) {
  if (lua_isnoneornil(L, narg)) {
    if (len)
      *len = (def ? strlen(def) : 0);
    return def;
  }
  else return my_checklstring(L, narg, len);
}


LUALIB_API lua_Number my_checknumber (lua_State *L, int narg) {
  lua_Number d = lua_tonumber(L, narg);
  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
    my_tag_error(L, narg, LUA_TNUMBER);
  return d;
}


LUALIB_API lua_Number my_optnumber (lua_State *L, int narg, lua_Number def) {
  return luaL_opt(L, my_checknumber, narg, def);
}


LUALIB_API lua_Integer my_checkinteger (lua_State *L, int narg) {
  lua_Integer d = lua_tointeger(L, narg);
  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
    my_tag_error(L, narg, LUA_TNUMBER);
  return d;
}


LUALIB_API lua_Integer my_optinteger (lua_State *L, int narg,
                                                      lua_Integer def) {
  return luaL_opt(L, my_checkinteger, narg, def);
}

#define my_checkstring(L,n)	(my_checklstring(L, (n), NULL))
#define my_optstring(L,n,d)	(my_optlstring(L, (n), (d), NULL))
#define my_checkint(L,n)	((int)my_checkinteger(L, (n)))
#define my_optint(L,n,d)	((int)my_optinteger(L, (n), (d)))
#define my_checklong(L,n)	((long)my_checkinteger(L, (n)))
#define my_optlong(L,n,d)	((long)my_optinteger(L, (n), (d)))

//-------------- end of special checks --------------------



static const bool optboolean (lua_State *L, const int narg, const int def) 
  {
  // that argument not present, take default
  if (lua_gettop (L) < narg)
    return def;

  // nil will default to the default
  if (lua_isnil (L, narg))
    return def;

  // try to convert boolean
  if (lua_isboolean (L, narg))
    return lua_toboolean (L, narg);

  return my_checknumber (L, narg) != 0;
}

//----------------------------------------
//  world.Accelerator
//----------------------------------------
static int L_Accelerator (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->Accelerator (
        my_checkstring (L, 1),       // Key
        my_checkstring (L, 2)        // Send
        ));
  return 1;  // number of result fields
  } // end of L_Accelerator

//----------------------------------------
//  world.AcceleratorList
//----------------------------------------
static int L_AcceleratorList (lua_State *L)
  {
  COleVariant v = doc (L)->AcceleratorList ();
  return pushVariant (L, v);
  } // end of L_AcceleratorList

//----------------------------------------
//  world.Activate
//----------------------------------------
static int L_Activate (lua_State *L)
  {
  doc (L)->Activate ();
  return 0;  // number of result fields
  } // end of L_Activate

//----------------------------------------
//  world.ActivateClient
//----------------------------------------
static int L_ActivateClient (lua_State *L)
  {
  doc (L)->ActivateClient ();
  return 0;  // number of result fields
  } // end of L_ActivateClient


//----------------------------------------
//  world.ActivateNotepad
//----------------------------------------
static int L_ActivateNotepad (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushboolean (L, pDoc->ActivateNotepad (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ActivateNotepad


//----------------------------------------
//  world.AddAlias
//----------------------------------------
static int L_AddAlias (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->AddAlias (
                  my_checkstring (L, 1),  // AliasName
                  my_checkstring (L, 2),  // MatchText  
                  my_checkstring (L, 3),  // ResponseText
                  my_checknumber (L, 4),  // Flags
                  my_optstring (L, 5, "")   // ScriptName - optional
                  ));
  return 1;  // number of result fields
  } // end of L_AddAlias


//----------------------------------------
//  world.AddMapperComment
//----------------------------------------
static int L_AddMapperComment (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->AddMapperComment (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_AddMapperComment


//----------------------------------------
//  world.AddSpellCheckWord
//----------------------------------------
static int L_AddSpellCheckWord (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L,  pDoc->AddSpellCheckWord (
              my_checkstring (L, 1), // Original word
              my_checkstring (L, 2), // Action
              my_optstring (L, 3, "") // Replacement word - optional
              ));
  return 1;  // number of result fields
  } // end of L_AddSpellCheckWord

//----------------------------------------
//  world.AddTimer
//----------------------------------------
static int L_AddTimer (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->AddTimer (
                  my_checkstring (L, 1),  // TimerName
                  my_checknumber (L, 2),  // Hour
                  my_checknumber (L, 3),  // Minute
                  my_checknumber (L, 4),  // Second
                  my_checkstring (L, 5),  // ResponseText  
                  my_checknumber (L, 6),  // Flags
                  my_optstring (L, 7, "")   // ScriptName - optional
                  ));
  return 1;  // number of result fields
  } // end of L_AddTimer


//----------------------------------------
//  world.AddToMapper
//----------------------------------------
static int L_AddToMapper (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L,  pDoc->AddToMapper (
              my_checkstring (L, 1), // Direction
              my_optstring (L, 2, "") // Reverse - optional
              ));
  return 1;  // number of result fields
  } // end of L_AddToMapper


//----------------------------------------
//  world.AddTrigger
//----------------------------------------
static int L_AddTrigger (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->AddTrigger (
                  my_checkstring (L, 1),  // TriggerName
                  my_checkstring (L, 2),  // MatchText
                  my_checkstring (L, 3),  // ResponseText
                  my_checknumber (L, 4),  // Flags  
                  my_checknumber (L, 5),  // Colour
                  my_checknumber (L, 6),  // Wildcard
                  my_checkstring (L, 7),  // SoundFileName  
                  my_optstring (L, 8, "")   // ScriptName - optional
                  ));
  return 1;  // number of result fields
  } // end of L_AddTrigger


//----------------------------------------
//  world.AddTriggerEx
//----------------------------------------
static int L_AddTriggerEx (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->AddTriggerEx (
                  my_checkstring (L, 1),  // TriggerName
                  my_checkstring (L, 2),  // MatchText
                  my_checkstring (L, 3),  // ResponseText
                  my_checknumber (L, 4),  // Flags  
                  my_checknumber (L, 5),  // Colour
                  my_checknumber (L, 6),  // Wildcard
                  my_checkstring (L, 7),  // SoundFileName  
                  my_checkstring (L, 8),  // ScriptName
                  my_checknumber (L, 9),  // SendTo  
                  my_optnumber (L, 10, DEFAULT_TRIGGER_SEQUENCE)   // Sequence  - optional
                  ));
  return 1;  // number of result fields
  } // end of L_AddTriggerEx


//----------------------------------------
//  world.AdjustColour
//----------------------------------------
static int L_AdjustColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->AdjustColour (
                  my_checknumber (L, 1),    // Colour
                  my_checknumber (L, 2)     // Method
                  ));
  return 1;  // number of result fields
  } // end of L_AdjustColour


//----------------------------------------
//  world.ANSI
//----------------------------------------
static int L_ANSI (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first

  int n = lua_gettop(L);  /* number of arguments */
  int i;
  CString sOutput;
  for (i= 1; i <= n; i++) 
    sOutput += CFormat ("%c[%im", ESC, (int) my_checknumber (L, i));

  lua_pushstring (L, sOutput);
  return 1;
  } // end of L_ANSI


//----------------------------------------
//  world.AnsiNote
//----------------------------------------
static int L_AnsiNote (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first

  pDoc->AnsiNote (concatArgs (L).c_str ());

//  lua_concat (L, lua_gettop (L));
//  pDoc->AnsiNote (my_checkstring (L, 1));
  return 0;  // number of result fields
  } // end of L_AnsiNote


//----------------------------------------
//  world.AppendToNotepad
//----------------------------------------
static int L_AppendToNotepad (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first

  lua_pushboolean (L, pDoc->AppendToNotepad (
                    my_checkstring (L, 1), // title
                    concatArgs (L, "", 2).c_str ()  // contents
                    ));

//  lua_concat (L, lua_gettop (L) - 1);
//  lua_pushboolean (L, pDoc->AppendToNotepad (
//                    my_checkstring (L, 1), // title
//                    my_checkstring (L, 2)  // contents
//                    ));
  return 1;  // number of result fields
  } // end of L_AppendToNotepad


//----------------------------------------
//  world.ArrayClear
//----------------------------------------
static int L_ArrayClear (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ArrayClear (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ArrayClear


//----------------------------------------
//  world.ArrayCount
//----------------------------------------
static int L_ArrayCount (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->ArrayCount ());
  return 1;  // number of result fields
  } // end of L_ArrayCount


//----------------------------------------
//  world.ArrayCreate
//----------------------------------------
static int L_ArrayCreate (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ArrayCreate (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ArrayCreate


//----------------------------------------
//  world.ArrayDelete
//----------------------------------------
static int L_ArrayDelete (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ArrayDelete (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ArrayDelete


//----------------------------------------
//  world.ArrayDeleteKey
//----------------------------------------
static int L_ArrayDeleteKey (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ArrayDeleteKey (
                  my_checkstring (L, 1),  // Name
                  my_checkstring (L, 2)   // Key
                  ));
  return 1;  // number of result fields
  } // end of L_ArrayDeleteKey


//----------------------------------------
//  world.ArrayExists
//----------------------------------------
static int L_ArrayExists (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushboolean (L,  pDoc->ArrayExists (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ArrayExists


//----------------------------------------
//  world.ArrayExport
//----------------------------------------
static int L_ArrayExport (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->ArrayExport (
            my_checkstring (L, 1),   // Name
            my_optstring (L, 2, ",") // Delimiter
            );
  return pushVariant (L, v);
  } // end of L_ArrayExport


//----------------------------------------
//  world.ArrayExportKeys
//----------------------------------------
static int L_ArrayExportKeys (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->ArrayExportKeys (
            my_checkstring (L, 1),   // Name
            my_optstring (L, 2, ",") // Delimiter
            );
  return pushVariant (L, v);
  } // end of L_ArrayExportKeys


//----------------------------------------
//  world.ArrayGet
//----------------------------------------
static int L_ArrayGet (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->ArrayGet (
            my_checkstring (L, 1),   // Name
            my_checkstring (L, 2)    // Key
            );
  return pushVariant (L, v);
  } // end of L_ArrayGet


//----------------------------------------
//  world.ArrayGetFirstKey
//----------------------------------------
static int L_ArrayGetFirstKey (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->ArrayGetFirstKey (my_checkstring (L, 1));
  return pushVariant (L, v);
  } // end of L_ArrayGetFirstKey


//----------------------------------------
//  world.ArrayGetLastKey
//----------------------------------------
static int L_ArrayGetLastKey (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->ArrayGetLastKey (my_checkstring (L, 1));
  return pushVariant (L, v);
  } // end of L_ArrayGetLastKey


//----------------------------------------
//  world.ArrayImport    
//  - extension - takes an optional table as 2nd argument
//----------------------------------------
static int L_ArrayImport (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first

  string name = my_checkstring (L, 1);

  // extension here - accept table as 2nd argument
  if (lua_istable (L, 2))
    {

    tStringMapOfMaps::iterator it = pDoc->GetArrayMap ().find (name);
                           
    // find table
    if (it == pDoc->GetArrayMap ().end ())
      {
      lua_pushnumber (L, eArrayDoesNotExist);
      return 1;
      }

    int iDuplicates = 0;

    lua_pushnil (L);  // first key for traversal
    while (lua_next (L, 2) != 0)
      {
      if (lua_type (L, -2) != LUA_TSTRING)
        luaL_error (L, "table must have string keys");

      // get key and value
      string sKey = lua_tostring (L, -2);
      string sValue = lua_tostring (L, -1);

      // insert into array
      pair<tStringToStringMap::iterator, bool> status = 
          it->second->insert (make_pair (sKey, sValue));

      // check if already there
      if (!status.second)
        {
        status.first->second = sValue;
        iDuplicates++;
        }

      lua_pop (L, 1); // remove value, keep key for next iteration

      } // end of looping through table

    if (iDuplicates)
      lua_pushnumber (L, eImportedWithDuplicates);
    else
      lua_pushnumber (L, eOK);
    return 1; // one result, which is error code

    }   // end of table for argument 2

  // not a table - normal string with delimiters
  lua_pushnumber (L, pDoc->ArrayImport (
                  name.c_str (),  // Name
                  my_checkstring (L, 2),  // Values
                  my_optstring (L, 3, ",")   // Delimiter
                  ));
  return 1;  // number of result fields
  } // end of L_ArrayImport


//----------------------------------------
//  world.ArrayKeyExists
//----------------------------------------
static int L_ArrayKeyExists (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushboolean (L,  pDoc->ArrayKeyExists (
            my_checkstring (L, 1),      // Name
            my_checkstring (L, 2)       // Key
            ));
  return 1;  // number of result fields
  } // end of L_ArrayKeyExists


//----------------------------------------
//  world.ArrayListAll
//----------------------------------------
static int L_ArrayListAll (lua_State *L)
  {
  COleVariant v = doc (L)->ArrayListAll ();
  return pushVariant (L, v);
  } // end of L_ArrayListAll


//----------------------------------------
//  world.ArrayListKeys
//----------------------------------------
static int L_ArrayListKeys (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->ArrayListKeys (my_checkstring (L, 1));
  return pushVariant (L, v);
  } // end of L_ArrayListKeys


//----------------------------------------
//  world.ArrayListValues
//----------------------------------------
static int L_ArrayListValues (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->ArrayListValues (my_checkstring (L, 1));
  return pushVariant (L, v);
  } // end of L_ArrayListValues

//----------------------------------------
//  world.ArrayList - Lua only
//----------------------------------------
static int L_ArrayList (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first

  tStringMapOfMaps::iterator it = pDoc->GetArrayMap ().find (my_checkstring (L, 1));
  if (it == pDoc->GetArrayMap ().end ())
    return 0;        // not found, no results

  lua_newtable(L);                                                            
  for (tStringToStringMap::iterator i = it->second->begin (); 
       i != it->second->end ();
       i++)
       {
        lua_pushstring (L, i->first.c_str ());
        lua_pushstring (L, i->second.c_str ());
        lua_rawset(L, -3);
       }
  return 1;   // one table
  } // end of L_ArrayList


//----------------------------------------
//  world.ArraySet
//----------------------------------------
static int L_ArraySet (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ArraySet (
                  my_checkstring (L, 1),  // Name
                  my_checkstring (L, 2),  // Key
                  my_checkstring (L, 3)   // Value
                  ));
  return 1;  // number of result fields
  } // end of L_ArraySet


//----------------------------------------
//  world.ArraySize
//----------------------------------------
static int L_ArraySize (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ArraySize (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ArraySize


//----------------------------------------
//  world.Base64Decode
//----------------------------------------
static int L_Base64Decode (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->Base64Decode (my_checkstring (L, 1));
  return pushVariant (L, v);
  } // end of L_Base64Decode


//----------------------------------------
//  world.Base64Encode
//----------------------------------------
static int L_Base64Encode (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->Base64Encode (
        my_checkstring (L, 1),  // Text
        optboolean (L, 2, 0)     // MultiLine
        );
  return pushVariant (L, v);
  } // end of L_Base64Encode


//----------------------------------------
//  world.GetBoldColour
//----------------------------------------
static int L_GetBoldColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetBoldColour (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of GetBoldColour

//----------------------------------------
//  world.SetBoldColour
//----------------------------------------
static int L_SetBoldColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetBoldColour (
      my_checknumber (L, 1),  // WhichColour
      my_checknumber (L, 2)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of SetBoldColour


//----------------------------------------
//  world.BroadcastPlugin
//----------------------------------------
static int L_BroadcastPlugin (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->BroadcastPlugin (
                  my_checknumber (L, 1),  // PluginID
                  my_optstring   (L, 2, "")   // Argument - optional
                  ));
  return 1;  // number of result fields
  } // end of L_BroadcastPlugin


//----------------------------------------
//  world.CallPlugin
//----------------------------------------
static int L_CallPlugin (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->CallPlugin (
                  my_checkstring (L, 1),  // PluginID
                  my_checkstring (L, 2),  // Routine  
                  my_optstring   (L, 3, "")   // Argument - optional
                  ));
  return 1;  // number of result fields
  } // end of L_CallPlugin

//----------------------------------------
//  world.ChangeDir
//----------------------------------------
static int L_ChangeDir (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChangeDir (
                  my_checkstring (L, 1)   // Directory
                  ));
  return 1;  // number of result fields
  } // end of L_ChangeDir


//----------------------------------------
//  world.ChatAcceptCalls
//----------------------------------------
static int L_ChatAcceptCalls (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatAcceptCalls (my_optnumber (L, 1, DEFAULT_CHAT_PORT)));
  return 1;  // number of result fields
  } // end of L_ChatAcceptCalls


//----------------------------------------
//  world.ChatCall
//----------------------------------------
static int L_ChatCall (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatCall (
                  my_checkstring (L, 1),  // Server
                  my_optnumber (L, 2, DEFAULT_CHAT_PORT)
                  ));
  return 1;  // number of result fields
  } // end of L_ChatCall


//----------------------------------------
//  world.ChatCallzChat
//----------------------------------------
static int L_ChatCallzChat (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatCallzChat (
                  my_checkstring (L, 1),  // Server
                  my_optnumber (L, 2, DEFAULT_CHAT_PORT)
                  ));
  return 1;  // number of result fields
  } // end of L_ChatCallzChat


//----------------------------------------
//  world.ChatDisconnect
//----------------------------------------
static int L_ChatDisconnect (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatDisconnect (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatDisconnect


//----------------------------------------
//  world.ChatDisconnectAll
//----------------------------------------
static int L_ChatDisconnectAll (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatDisconnectAll ());
  return 1;  // number of result fields
  } // end of L_ChatDisconnectAll


//----------------------------------------
//  world.ChatEverybody
//----------------------------------------
static int L_ChatEverybody (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatEverybody (
                  my_checkstring (L, 1),  // Message
                  optboolean (L, 2, 0)  // Emote
                  ));
  return 1;  // number of result fields
  } // end of L_ChatEverybody


//----------------------------------------
//  world.ChatGetID
//----------------------------------------
static int L_ChatGetID (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatGetID (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatGetID


//----------------------------------------
//  world.ChatGroup
//----------------------------------------
static int L_ChatGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatGroup (
                  my_checkstring (L, 1),  // Group
                  my_checkstring (L, 2),  // Message
                  optboolean (L, 3, 0)  // Emote
                  ));
  return 1;  // number of result fields
  } // end of L_ChatGroup


//----------------------------------------
//  world.ChatID
//----------------------------------------
static int L_ChatID (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatID (
                  my_checknumber (L, 1),  // ID
                  my_checkstring (L, 2),  // Message
                  optboolean (L, 3, 0)  // Emote
                  ));
  return 1;  // number of result fields
  } // end of L_ChatID


//----------------------------------------
//  world.ChatMessage
//----------------------------------------
static int L_ChatMessage (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatMessage (
                  my_checknumber (L, 1),  // ID
                  my_checknumber (L, 2),  // Message code
                  my_optstring (L, 3, "")  // Text - optional
                  ));
  return 1;  // number of result fields
  } // end of L_ChatMessage


//----------------------------------------
//  world.ChatNameChange
//----------------------------------------
static int L_ChatNameChange (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatNameChange (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatNameChange


//----------------------------------------
//  world.ChatNote
//----------------------------------------
static int L_ChatNote (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->ChatNote (
          my_checknumber (L, 1),  // NoteType
          my_optstring (L, 2, "")   // Message - optional
          );
  return 0;  // number of result fields
  } // end of L_ChatNote


//----------------------------------------
//  world.ChatPasteEverybody
//----------------------------------------
static int L_ChatPasteEverybody (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->ChatPasteEverybody ());
  return 1;  // number of result fields
  } // end of L_ChatPasteEverybody


//----------------------------------------
//  world.ChatPasteText
//----------------------------------------
static int L_ChatPasteText (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatPasteText (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatPasteText


//----------------------------------------
//  world.ChatPeekConnections
//----------------------------------------
static int L_ChatPeekConnections (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatPeekConnections (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatPeekConnections


//----------------------------------------
//  world.ChatPersonal
//----------------------------------------
static int L_ChatPersonal (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatPersonal (
                  my_checkstring (L, 1),  // Who
                  my_checkstring (L, 2),  // Message
                  optboolean (L, 3, 0)  // Emote
                  ));
  return 1;  // number of result fields
  } // end of L_ChatPersonal


//----------------------------------------
//  world.ChatPing
//----------------------------------------
static int L_ChatPing (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatPing (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatPing


//----------------------------------------
//  world.ChatRequestConnections
//----------------------------------------
static int L_ChatRequestConnections (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatRequestConnections (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatRequestConnections


//----------------------------------------
//  world.ChatSendFile
//----------------------------------------
static int L_ChatSendFile (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatSendFile (
                  my_checknumber (L, 1),  // ID
                  my_optstring (L, 2, "")   // FileName
                  ));
  return 1;  // number of result fields
  } // end of L_ChatSendFile


//----------------------------------------
//  world.ChatStopAcceptingCalls
//----------------------------------------
static int L_ChatStopAcceptingCalls (lua_State *L)
  {
  doc (L)->ChatStopAcceptingCalls ();
  return 0;  // number of result fields
  } // end of L_ChatStopAcceptingCalls


//----------------------------------------
//  world.ChatStopFileTransfer
//----------------------------------------
static int L_ChatStopFileTransfer (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ChatStopFileTransfer (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_ChatStopFileTransfer

//----------------------------------------
//  world.CloseLog
//----------------------------------------
static int L_CloseLog (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->CloseLog ());
  return 1;  // number of result fields
  } // end of L_CloseLog


//----------------------------------------
//  world.CloseNotepad
//----------------------------------------
static int L_CloseNotepad (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->CloseNotepad (
                  my_checkstring (L, 1),  // Title
                  optboolean (L, 2, 0)  // QuerySave
                  ));
  return 1;  // number of result fields
  } // end of L_CloseNotepad


//----------------------------------------
//  world.ColourNameToRGB
//----------------------------------------
static int L_ColourNameToRGB (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ColourNameToRGB (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ColourNameToRGB


//----------------------------------------
//  world.ColourNote
// extension - takes groups of 3 arguments 
//----------------------------------------
static int L_ColourNote (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  int n = lua_gettop(L);  /* number of arguments */
  int i;
  for (i=1; i<=n; i += 3) 
    {
    if ((i + 2) < n)    // not end of line yet
      pDoc->ColourTell (
            my_checkstring (L, i),       // TextColour
            my_checkstring (L, i + 1),   // BackgroundColour
            my_checkstring (L, i + 2)    // Text
                          );
    else
      pDoc->ColourNote (
            my_checkstring (L, i),       // TextColour
            my_checkstring (L, i + 1),   // BackgroundColour
            my_checkstring (L, i + 2)    // Text
                          );
    }
  return 0;  // number of result fields
  } // end of L_ColourNote


//----------------------------------------
//  world.ColourTell
// extension - takes groups of 3 arguments 
//----------------------------------------
static int L_ColourTell (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  int n = lua_gettop(L);  /* number of arguments */
  int i;
  for (i=1; i<=n; i += 3) 
    pDoc->ColourTell (
          my_checkstring (L, i),       // TextColour
          my_checkstring (L, i + 1),   // BackgroundColour
          my_checkstring (L, i + 2)    // Text
                      );
  return 0;  // number of result fields
  } // end of L_ColourTell


//----------------------------------------
//  world.Connect
//----------------------------------------
static int L_Connect (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->Connect ());
  return 1;  // number of result fields
  } // end of L_Connect


//----------------------------------------
//  world.CreateGUID
//----------------------------------------
static int L_CreateGUID (lua_State *L)
  {
  BSTR str = doc (L)->CreateGUID ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_CreateGUID


//----------------------------------------
//  world.GetCustomColourBackground
//----------------------------------------
static int L_GetCustomColourBackground (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetCustomColourBackground (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_GetCustomColourBackground

//----------------------------------------
//  world.SetCustomColourBackground
//----------------------------------------
static int L_SetCustomColourBackground (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetCustomColourBackground (
      my_checknumber (L, 1),  // WhichColour
      my_checknumber (L, 2)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of L_SetCustomColourBackground


//----------------------------------------
//  world.GetCustomColourText
//----------------------------------------
static int L_GetCustomColourText (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetCustomColourText (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_GetCustomColourText

//----------------------------------------
//  world.SetCustomColourText
//----------------------------------------
static int L_SetCustomColourText (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetCustomColourText (
      my_checknumber (L, 1),  // WhichColour
      my_checknumber (L, 2)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of L_SetCustomColourText


//----------------------------------------
//  world.Debug
//----------------------------------------
static int L_Debug (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->Debug (my_optstring (L, 1, ""));
  return pushVariant (L, v);  // number of result fields
  } // end of L_Debug


//----------------------------------------
//  world.DeleteAlias
//----------------------------------------
static int L_DeleteAlias (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteAlias (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteAlias


//----------------------------------------
//  world.DeleteAliasGroup
//----------------------------------------
static int L_DeleteAliasGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteAliasGroup (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteAliasGroup


//----------------------------------------
//  world.DeleteAllMapItems
//----------------------------------------
static int L_DeleteAllMapItems (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->DeleteAllMapItems ());
  return 1;  // number of result fields
  } // end of L_DeleteAllMapItems


//----------------------------------------
//  world.DeleteCommandHistory
//----------------------------------------
static int L_DeleteCommandHistory (lua_State *L)
  {
  doc (L)->DeleteCommandHistory ();
  return 0;  // number of result fields
  } // end of L_DeleteCommandHistory


//----------------------------------------
//  world.DeleteGroup
//----------------------------------------
static int L_DeleteGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteGroup (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteGroup


//----------------------------------------
//  world.DeleteLastMapItem
//----------------------------------------
static int L_DeleteLastMapItem (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->DeleteLastMapItem ());
  return 1;  // number of result fields
  } // end of L_DeleteLastMapItem

//----------------------------------------
//  world.DeleteLines
//----------------------------------------
static int L_DeleteLines (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->DeleteLines (my_checknumber (L, 1));
  return 0;  // number of result fields
  } // end of L_DeleteLines

//----------------------------------------
//  world.DeleteOutput
//----------------------------------------
static int L_DeleteOutput (lua_State *L)
  {
  doc (L)->DeleteOutput ();
  return 0;  // number of result fields
  } // end of L_DeleteOutput


//----------------------------------------
//  world.DeleteTemporaryAliases
//----------------------------------------
static int L_DeleteTemporaryAliases (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->DeleteTemporaryAliases ());
  return 1;  // number of result fields
  } // end of L_DeleteTemporaryAliases


//----------------------------------------
//  world.DeleteTemporaryTimers
//----------------------------------------
static int L_DeleteTemporaryTimers (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->DeleteTemporaryTimers ());
  return 1;  // number of result fields
  } // end of L_DeleteTemporaryTimers


//----------------------------------------
//  world.DeleteTemporaryTriggers
//----------------------------------------
static int L_DeleteTemporaryTriggers (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->DeleteTemporaryTriggers ());
  return 1;  // number of result fields
  } // end of L_DeleteTemporaryTriggers


//----------------------------------------
//  world.DeleteTimer
//----------------------------------------
static int L_DeleteTimer (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteTimer (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteTimer


//----------------------------------------
//  world.DeleteTimerGroup
//----------------------------------------
static int L_DeleteTimerGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteTimerGroup (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteTimerGroup


//----------------------------------------
//  world.DeleteTrigger
//----------------------------------------
static int L_DeleteTrigger (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteTrigger (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteTrigger


//----------------------------------------
//  world.DeleteTriggerGroup
//----------------------------------------
static int L_DeleteTriggerGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteTriggerGroup (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteTriggerGroup


//----------------------------------------
//  world.DeleteVariable
//----------------------------------------
static int L_DeleteVariable (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DeleteVariable (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DeleteVariable


//----------------------------------------
//  world.DiscardQueue
//----------------------------------------
static int L_DiscardQueue (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->DiscardQueue ());
  return 1;  // number of result fields
  } // end of L_DiscardQueue


//----------------------------------------
//  world.Disconnect
//----------------------------------------
static int L_Disconnect (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->Disconnect ());
  return 1;  // number of result fields
  } // end of L_Disconnect


//----------------------------------------
//  world.DoAfter
//----------------------------------------
static int L_DoAfter (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DoAfter (
                  my_checknumber (L, 1), // Seconds
                  my_checkstring (L, 2)  // SendText
                  ));
  return 1;  // number of result fields
  } // end of L_DoAfter


//----------------------------------------
//  world.DoAfterNote
//----------------------------------------
static int L_DoAfterNote (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DoAfterNote (
                  my_checknumber (L, 1), // Seconds
                  my_checkstring (L, 2)  // NoteText
                  ));
  return 1;  // number of result fields
  } // end of L_DoAfterNote


//----------------------------------------
//  world.DoAfterSpecial
//----------------------------------------
static int L_DoAfterSpecial (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DoAfterSpecial (
                  my_checknumber (L, 1),  // Seconds
                  my_checkstring (L, 2),  // NoteText
                  my_checknumber (L, 3)   // SendTo
                  ));
  return 1;  // number of result fields
  } // end of L_DoAfterSpecial


//----------------------------------------
//  world.DoAfterSpeedWalk
//----------------------------------------
static int L_DoAfterSpeedWalk (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DoAfterSpeedWalk (
                  my_checknumber (L, 1), // Seconds
                  my_checkstring (L, 2)  // SendText
                  ));
  return 1;  // number of result fields
  } // end of L_DoAfterSpeedWalk


//----------------------------------------
//  world.DoCommand
//----------------------------------------
static int L_DoCommand (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->DoCommand (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_DoCommand


//----------------------------------------
//  world.GetEchoInput
//----------------------------------------
static int L_GetEchoInput (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->GetEchoInput ());
  return 1;  // number of result fields
  } // end of L_GetEchoInput

//----------------------------------------
//  world.SetEchoInput
//----------------------------------------
static int L_SetEchoInput (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetEchoInput (optboolean (L, 1, 1));  // defaults to yes
  return 0;  // number of result fields
  } // end of L_SetEchoInput

//----------------------------------------
//  world.EditDistance
//----------------------------------------
static int L_EditDistance (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EditDistance (
      my_checkstring (L, 1),   // source
      my_checkstring (L, 2)    // target
      ));
  return 1;  // number of result fields
  } // end of L_EditDistance


//----------------------------------------
//  world.EnableAlias
//----------------------------------------
static int L_EnableAlias (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnableAlias (
      my_checkstring (L, 1),    // alias
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnableAlias


//----------------------------------------
//  world.EnableAliasGroup
//----------------------------------------
static int L_EnableAliasGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnableAliasGroup (
      my_checkstring (L, 1),    // Group
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnableAliasGroup


//----------------------------------------
//  world.EnableGroup
//----------------------------------------
static int L_EnableGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnableGroup (
      my_checkstring (L, 1),    // Group
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnableGroup


//----------------------------------------
//  world.EnableMapping
//----------------------------------------
static int L_EnableMapping (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->EnableMapping (optboolean (L, 1, 1));
  return 0;  // number of result fields
  } // end of L_EnableMapping


//----------------------------------------
//  world.EnablePlugin
//----------------------------------------
static int L_EnablePlugin (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnablePlugin (
      my_checkstring (L, 1),    // Plugin ID
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnablePlugin


//----------------------------------------
//  world.EnableTimer
//----------------------------------------
static int L_EnableTimer (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnableTimer (
      my_checkstring (L, 1),    // Timer
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnableTimer


//----------------------------------------
//  world.EnableTimerGroup
//----------------------------------------
static int L_EnableTimerGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnableTimerGroup (
      my_checkstring (L, 1),    // Group
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnableTimerGroup


//----------------------------------------
//  world.EnableTrigger
//----------------------------------------
static int L_EnableTrigger (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnableTrigger (
      my_checkstring (L, 1),    // Trigger
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnableTrigger


//----------------------------------------
//  world.EnableTriggerGroup
//----------------------------------------
static int L_EnableTriggerGroup (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->EnableTriggerGroup (
      my_checkstring (L, 1),    // Group
      optboolean (L, 2, 1)    // enabled flag, defaults to true
      ));
  return 1;  // number of result fields
  } // end of L_EnableTriggerGroup


//----------------------------------------
//  world.ErrorDesc
//----------------------------------------
static int L_ErrorDesc (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->ErrorDesc (my_checknumber (L, 1));
  return pushBstr (L, str);  // number of result fields
  } // end of L_ErrorDesc

//----------------------------------------
//  world.EvaluateSpeedwalk
//----------------------------------------
static int L_EvaluateSpeedwalk (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  // this is a helper function that returns a CString, not a BSTR
  lua_pushstring (L, pDoc->DoEvaluateSpeedwalk (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_EvaluateSpeedwalk


//----------------------------------------
//  world.Execute
//----------------------------------------
static int L_Execute (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->Execute (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_Execute


//----------------------------------------
//  world.ExportXML
//----------------------------------------
static int L_ExportXML (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->ExportXML (
                  my_checknumber (L, 1), // Type
                  my_checkstring (L, 2)  // Name
                  );
  return pushBstr (L, str);  // number of result fields
  } // end of L_ExportXML


//----------------------------------------
//  world.FixupEscapeSequences
//----------------------------------------
static int L_FixupEscapeSequences (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->FixupEscapeSequences (
                  my_checkstring (L, 1)  // Source
                  );
  return pushBstr (L, str);  // number of result fields
  } // end of L_FixupEscapeSequences


//----------------------------------------
//  world.FixupHTML
//----------------------------------------
static int L_FixupHTML (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->FixupHTML (
                  my_checkstring (L, 1)  // StringToConvert
                  );
  return pushBstr (L, str);  // number of result fields
  } // end of L_FixupHTML


//----------------------------------------
//  world.FlushLog
//----------------------------------------
static int L_FlushLog (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->FlushLog ());
  return 1;  // number of result fields
  } // end of L_FlushLog


//----------------------------------------
//  world.GenerateName
//----------------------------------------
static int L_GenerateName (lua_State *L)
  {
  COleVariant v = doc (L)->GenerateName ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GenerateName


//----------------------------------------
//  world.GetAlias
//
// Unlike the normal version this takes the alias name and
//  returns 5 fields: result, match, response, flags, script name
//----------------------------------------
static int L_GetAlias (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);

  COleVariant MatchText, 
              ResponseText, 
              Parameter, 
              Flags, 
              ScriptName;

  long result = pDoc->GetAlias(my_checkstring (L, 1),  // name
                                  &MatchText, 
                                  &ResponseText, 
                                  &Parameter,    // not used these days
                                  &Flags, 
                                  &ScriptName); 
  lua_pushnumber (L, result);         // 1
  pushVariant (L, MatchText);         // 2
  pushVariant (L, ResponseText);      // 3
  pushVariant (L, Flags);             // 4
  pushVariant (L, ScriptName);        // 5

  return 5;  // number of result fields
  } // end of L_GetAlias


//----------------------------------------
//  world.GetAliasInfo
//----------------------------------------
static int L_GetAliasInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetAliasInfo (
      my_checkstring (L, 1),    // Name
      my_checknumber (L, 2)     // Type
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetAliasInfo


//----------------------------------------
//  world.GetAliasList
//----------------------------------------
static int L_GetAliasList (lua_State *L)
  {
  COleVariant v = doc (L)->GetAliasList ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetAliasList


//----------------------------------------
//  world.GetAliasOption
//----------------------------------------
static int L_GetAliasOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetAliasOption (
      my_checkstring (L, 1),    // Name
      my_checkstring (L, 2)     // Option name
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetAliasOption


//----------------------------------------
//  world.GetAliasWildcard
//----------------------------------------
static int L_GetAliasWildcard (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetAliasWildcard (
      my_checkstring (L, 1),    // Name
      my_checkstring (L, 2)     // Wildcard name
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetAliasWildcard


//----------------------------------------
//  world.GetAlphaOption
//----------------------------------------
static int L_GetAlphaOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetAlphaOption (
      my_checkstring (L, 1) // Name
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetAlphaOption


//----------------------------------------
//  world.GetAlphaOptionList
//----------------------------------------
static int L_GetAlphaOptionList (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetAlphaOptionList ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetAlphaOptionList


//----------------------------------------
//  world.GetChatInfo
//----------------------------------------
static int L_GetChatInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetChatInfo (
      my_checknumber (L, 1),    // ChatID 
      my_checknumber (L, 2)     // InfoType
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetChatInfo


//----------------------------------------
//  world.GetChatList
//----------------------------------------
static int L_GetChatList (lua_State *L)
  {
  COleVariant v = doc (L)->GetChatList ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetChatList


//----------------------------------------
//  world.GetChatOption
//----------------------------------------
static int L_GetChatOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetChatOption (
      my_checknumber (L, 1),    // ChatID 
      my_checkstring (L, 2)     // OptionName
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetChatOption


//----------------------------------------
//  world.GetClipboard
//----------------------------------------
static int L_GetClipboard (lua_State *L)
  {
  BSTR str = doc (L)->GetClipboard ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetClipboard


//----------------------------------------
//  world.GetCommand
//----------------------------------------
static int L_GetCommand (lua_State *L)
  {
  BSTR str = doc (L)->GetCommand ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetCommand


//----------------------------------------
//  world.GetCommandList
//----------------------------------------
static int L_GetCommandList (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetCommandList (
      my_checknumber (L, 1) // Count
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetCommandList


//----------------------------------------
//  world.GetConnectDuration
//----------------------------------------
static int L_GetConnectDuration (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetConnectDuration ());
  return 1;  // number of result fields
  } // end of L_GetConnectDuration


//----------------------------------------
//  world.GetCurrentValue
//----------------------------------------
static int L_GetCurrentValue (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetCurrentValue (
            my_checkstring (L, 1)   // OptionName
            );
  return pushVariant (L, v);
  } // end of L_GetCurrentValue


//----------------------------------------
//  world.GetDefaultValue
//----------------------------------------
static int L_GetDefaultValue (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetDefaultValue (
            my_checkstring (L, 1)   // OptionName
            );
  return pushVariant (L, v);
  } // end of L_GetDefaultValue


//----------------------------------------
//  world.GetEntity
//----------------------------------------
static int L_GetEntity (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->GetEntity (my_checkstring (L, 1));
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetEntity

//----------------------------------------
//  world.GetXMLEntity
//----------------------------------------
static int L_GetXMLEntity (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->GetXMLEntity (my_checkstring (L, 1));
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetXMLEntity

//----------------------------------------
//  world.GetFrame
//----------------------------------------
static int L_GetFrame (lua_State *L)
  {
  lua_pushlightuserdata (L, (void *) doc (L)->GetFrame ());
  return 1;  // number of result fields
  } // end of L_GetFrame

//----------------------------------------
//  world.GetHostAddress
//----------------------------------------
static int L_GetHostAddress (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetHostAddress (
            my_checkstring (L, 1)   // HostName
            );
  return pushVariant (L, v);
  } // end of L_GetHostAddress


//----------------------------------------
//  world.GetHostName
//----------------------------------------
static int L_GetHostName (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->GetHostName (my_checkstring (L, 1));
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetHostName


//----------------------------------------
//  world.GetInfo
//----------------------------------------
static int L_GetInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetInfo (
            my_checknumber (L, 1)   // InfoType
            );
  return pushVariant (L, v);
  } // end of L_GetInfo


//----------------------------------------
//  world.GetInternalCommandsList
//----------------------------------------
static int L_GetInternalCommandsList (lua_State *L)
  {
  COleVariant v = doc (L)->GetInternalCommandsList ();
  return pushVariant (L, v);
  } // end of L_GetInternalCommandsList


//----------------------------------------
//  world.GetLineCount
//----------------------------------------
static int L_GetLineCount (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetLineCount ());
  return 1;  // number of result fields
  } // end of L_GetLineCount


//----------------------------------------
//  world.GetLineInfo
// extension - for info type 0 or omitted, returns a table
//----------------------------------------
static int L_GetLineInfo (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  int iLine = my_checknumber (L, 1);
  int iType = my_optnumber (L, 2, 0);
  
  if (iType == 0)
    {
    // check line exists
    if (iLine <= 0 || iLine > pDoc->m_LineList.GetCount ())
      return 0;     // no result for no line

  // get pointer to line in question

    CLine * pLine = pDoc->m_LineList.GetAt (pDoc->GetLinePosition (iLine - 1));

    lua_newtable(L);                                                            
    MakeTableItem     (L, "text",     CString (pLine->text, pLine->len)); // 1
    MakeTableItem     (L, "length",   pLine->len); // 2
    MakeTableItemBool (L, "newline",  pLine->hard_return); // 3
    MakeTableItemBool (L, "note",     (pLine->flags & COMMENT) != 0); // 4
    MakeTableItemBool (L, "user",     (pLine->flags & USER_INPUT) != 0); // 5
    MakeTableItemBool (L, "log",      (pLine->flags & LOG_LINE) != 0); // 6
    MakeTableItemBool (L, "bookmark", (pLine->flags & BOOKMARK) != 0); // 7
    MakeTableItemBool (L, "hr",       (pLine->flags & HORIZ_RULE) != 0); // 8
    MakeTableItem     (L, "time",     (int) pLine->m_theTime.GetTime ()); // 9a
    MakeTableItem     (L, "timestr",  COleDateTime (pLine->m_theTime.GetTime ())); // 9b
    MakeTableItem     (L, "line",     pLine->m_nLineNumber); // 10
    MakeTableItem     (L, "styles",   pLine->styleList.GetCount ()); // 11

    // high-performance timer
    double ticks = (double) pLine->m_lineHighPerformanceTime.QuadPart / (double) App.m_iCounterFrequency;
    MakeTableItem (L, "ticks", ticks);

    return 1;   // one table
    }     // end of returning a table

  // normal behaviour
  COleVariant v = pDoc->GetLineInfo (iLine, iType);
  return pushVariant (L, v);
  } // end of L_GetLineInfo


//----------------------------------------
//  world.GetLinesInBufferCount
//----------------------------------------
static int L_GetLinesInBufferCount (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetLinesInBufferCount ());
  return 1;  // number of result fields
  } // end of L_GetLinesInBufferCount


//----------------------------------------
//  world.GetLoadedValue
//----------------------------------------
static int L_GetLoadedValue (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetLoadedValue (
            my_checkstring (L, 1)   // OptionName
            );
  return pushVariant (L, v);
  } // end of L_GetLoadedValue

static void luaWindowPositionHelper (lua_State *L, const RECT & r)
  {
  lua_newtable(L);                                                            
  MakeTableItem     (L, "left",   r.left);
  MakeTableItem     (L, "top",    r.top);
  MakeTableItem     (L, "width",  r.right - r.left);
  MakeTableItem     (L, "height", r.bottom - r.top);
  } // end of luaWindowPositionHelper

//----------------------------------------
//  world.GetMainWindowPosition  
// - extension, return table rather than string
//----------------------------------------
static int L_GetMainWindowPosition (lua_State *L)
  {
  CWindowPlacement wp;
  Frame.GetWindowPlacement(&wp);  

  luaWindowPositionHelper (L, wp.rcNormalPosition);
  return 1;  // number of result fields
  } // end of L_GetMainWindowPosition

//----------------------------------------
//  world.GetNotepadWindowPosition  
// - extension, return table rather than string
//----------------------------------------
static int L_GetNotepadWindowPosition (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);

  CTextDocument * pTextDoc = pDoc->FindNotepad (my_checkstring (L, 1));

  if (pTextDoc)
    {
    CWindowPlacement wp;

    // get the view
    POSITION pos=pTextDoc->GetFirstViewPosition();

    if (pos)
      {
      CView* pView = pTextDoc->GetNextView(pos);

      if (pView->IsKindOf(RUNTIME_CLASS(CTextView)))
        {
        CTextView* pmyView = (CTextView*)pView;
        pmyView->GetParentFrame ()->GetWindowPlacement(&wp);
        luaWindowPositionHelper (L, wp.rcNormalPosition);
        return 1;  // number of result fields
        } // end of having the right type of view
      }   // end of having a view
    } // end of having an existing notepad document

  return 0;   // no results, notepad not found
  } // end of GetNotepadWindowPosition

//----------------------------------------
//  world.GetWorldWindowPosition  
// - extension, return table rather than string
//----------------------------------------
static int L_GetWorldWindowPosition (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  int which = my_optnumber (L, 1, 1);  // Which
  int count = 0;

  CWindowPlacement wp;

  for(POSITION pos=pDoc->GetFirstViewPosition();pos!=NULL;)
    {
    CView* pView = pDoc->GetNextView(pos);

    if (pView->IsKindOf(RUNTIME_CLASS(CSendView)))
      {
      CSendView* pmyView = (CSendView*)pView;

      count++;
      if (count != which)
        continue;      // wrong one

      pmyView->GetParentFrame ()->GetWindowPlacement(&wp); 
      luaWindowPositionHelper (L, wp.rcNormalPosition);
      return 1;  // number of result fields

      }	
    }

  return 0; // oops, that one not found (returns nil)

  } // end of L_GetWorldWindowPosition


//----------------------------------------
//  world.MakeRegularExpression
//----------------------------------------
static int L_MakeRegularExpression (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  // uses helper routine to avoid using BSTR
  lua_pushstring (L, ConvertToRegularExpression(my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_MakeRegularExpression

//----------------------------------------
//  world.GetMapColour
//----------------------------------------
static int L_GetMapColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetMapColour (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_GetMapColour

//----------------------------------------
//  world.GetMappingCount
//----------------------------------------
static int L_GetMappingCount (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetMappingCount ());
  return 1;  // number of result fields
  } // end of L_GetMappingCount


//----------------------------------------
//  world.GetMappingItem
//----------------------------------------
static int L_GetMappingItem (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetMappingItem (
            my_checknumber (L, 1)   // Item
            );
  return pushVariant (L, v);
  } // end of L_GetMappingItem


//----------------------------------------
//  world.GetMappingString
//----------------------------------------
static int L_GetMappingString (lua_State *L)
  {
  COleVariant v = doc (L)->GetMappingString ();
  return pushVariant (L, v);
  } // end of L_GetMappingString


//----------------------------------------
//  world.GetNotepadLength
//----------------------------------------
static int L_GetNotepadLength (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetNotepadLength (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_GetNotepadLength


//----------------------------------------
//  world.GetNotepadText
//----------------------------------------
static int L_GetNotepadText (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->GetNotepadText (my_checkstring (L, 1));
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetNotepadText


//----------------------------------------
//  world.GetNotes
//----------------------------------------
static int L_GetNotes (lua_State *L)
  {
  BSTR str = doc (L)->GetNotes ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetNotes


//----------------------------------------
//  world.GetNoteStyle
//----------------------------------------
static int L_GetNoteStyle (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetNoteStyle ());
  return 1;  // number of result fields
  } // end of L_GetNoteStyle


//----------------------------------------
//  world.GetOption
//----------------------------------------
static int L_GetOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetOption (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_GetOption


//----------------------------------------
//  world.GetOptionList
//----------------------------------------
static int L_GetOptionList (lua_State *L)
  {
  COleVariant v = doc (L)->GetOptionList ();
  return pushVariant (L, v);
  } // end of L_GetOptionList


//----------------------------------------
//  world.PickColour
//----------------------------------------
static int L_PickColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->PickColour (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_PickColour


//----------------------------------------
//  world.GetPluginAliasInfo
//----------------------------------------
static int L_GetPluginAliasInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginAliasInfo (
      my_checkstring (L, 1),    // PluginID
      my_checkstring (L, 2),    // Name
      my_checknumber (L, 3)     // Type
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginAliasInfo


//----------------------------------------
//  world.GetPluginAliasList
//----------------------------------------
static int L_GetPluginAliasList (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginAliasList (
      my_checkstring (L, 1)    // PluginID
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginAliasList


//----------------------------------------
//  world.GetPluginID
//----------------------------------------
static int L_GetPluginID (lua_State *L)
  {
  BSTR str = doc (L)->GetPluginID ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetPluginID


//----------------------------------------
//  world.GetPluginInfo
//----------------------------------------
static int L_GetPluginInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginInfo (
      my_checkstring (L, 1),    // PluginID
      my_checknumber (L, 2)     // Type
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginInfo


//----------------------------------------
//  world.GetPluginList
//----------------------------------------
static int L_GetPluginList (lua_State *L)
  {
  COleVariant v = doc (L)->GetPluginList ();
  return pushVariant (L, v);
  } // end of L_GetPluginList


//----------------------------------------
//  world.GetPluginName
//----------------------------------------
static int L_GetPluginName (lua_State *L)
  {
  BSTR str = doc (L)->GetPluginName ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetPluginName


//----------------------------------------
//  world.GetPluginTimerInfo
//----------------------------------------
static int L_GetPluginTimerInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginTimerInfo (
      my_checkstring (L, 1),    // PluginID
      my_checkstring (L, 2),    // Name
      my_checknumber (L, 3)     // Type
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginTimerInfo


//----------------------------------------
//  world.GetPluginTimerList
//----------------------------------------
static int L_GetPluginTimerList (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginTimerList (
      my_checkstring (L, 1)    // PluginID
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginTimerList


//----------------------------------------
//  world.GetPluginTriggerInfo
//----------------------------------------
static int L_GetPluginTriggerInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginTriggerInfo (
      my_checkstring (L, 1),    // PluginID
      my_checkstring (L, 2),    // Name
      my_checknumber (L, 3)     // Type
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginTriggerInfo


//----------------------------------------
//  world.GetPluginTriggerList
//----------------------------------------
static int L_GetPluginTriggerList (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginTriggerList (
      my_checkstring (L, 1)    // PluginID
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginTriggerList


//----------------------------------------
//  world.GetPluginVariable
//----------------------------------------
static int L_GetPluginVariable (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetPluginVariable (
      my_checkstring (L, 1),   // PluginID
      my_checkstring (L, 2)    // VariableName
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetPluginVariable


//----------------------------------------
//  world.GetPluginVariableList
//----------------------------------------
static int L_GetPluginVariableList (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);

  // plugin name
  const char * PluginID = my_checkstring (L, 1);

  // lookup plugin
  CPlugin * pPlugin = NULL;  
  if (strlen (PluginID) > 0)  
    {                         
    pPlugin = pDoc->GetPlugin (PluginID); 
    if (!pPlugin)             
	    return 0;   // no results - non-empty plugin not found     
    }                         
  // save current plugin
  CPlugin * pOldPlugin = pDoc->m_CurrentPlugin;  
  pDoc->m_CurrentPlugin = pPlugin;               
                      
  // now get the variable list 
  GetVariableListHelper (L, pDoc);                   

  // restore current plugin
  pDoc->m_CurrentPlugin = pOldPlugin;            

  return 1;     // one result (one table)

  } // end of L_GetPluginVariableList


//----------------------------------------
//  world.GetQueue
//----------------------------------------
static int L_GetQueue (lua_State *L)
  {
  COleVariant v = doc (L)->GetQueue ();
  return pushVariant (L, v);
  } // end of L_GetQueue


//----------------------------------------
//  world.GetReceivedBytes
//----------------------------------------
static int L_GetReceivedBytes (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->m_nBytesIn);
  return 1;  // number of result fields
  } // end of L_GetReceivedBytes


//----------------------------------------
//  world.GetRecentLines
//----------------------------------------
static int L_GetRecentLines (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->GetRecentLines (my_checknumber (L, 1));
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetRecentLines


//----------------------------------------
//  world.GetScriptTime
//----------------------------------------
static int L_GetScriptTime (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetScriptTime ());
  return 1;  // number of result fields
  } // end of L_GetScriptTime


//----------------------------------------
//  world.GetSelectionEndColumn
//----------------------------------------
static int L_GetSelectionEndColumn (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetSelectionEndColumn ());
  return 1;  // number of result fields
  } // end of L_GetSelectionEndColumn


//----------------------------------------
//  world.GetSelectionEndLine
//----------------------------------------
static int L_GetSelectionEndLine (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetSelectionEndLine ());
  return 1;  // number of result fields
  } // end of L_GetSelectionEndLine


//----------------------------------------
//  world.GetSelectionStartColumn
//----------------------------------------
static int L_GetSelectionStartColumn (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetSelectionStartColumn ());
  return 1;  // number of result fields
  } // end of L_GetSelectionStartColumn


//----------------------------------------
//  world.GetSelectionStartLine
//----------------------------------------
static int L_GetSelectionStartLine (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetSelectionStartLine ());
  return 1;  // number of result fields
  } // end of L_GetSelectionStartLine


//----------------------------------------
//  world.GetSentBytes
//----------------------------------------
static int L_GetSentBytes (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->m_nBytesOut);
  return 1;  // number of result fields
  } // end of L_GetSentBytes


static bool DoStyle (lua_State *L, 
                      CMUSHclientDoc *pDoc, 
                      CLine * pLine, 
                      int iStyleNumber,
                      CString & strText)
  {

  // check style exists
  if (iStyleNumber <= 0 || iStyleNumber > pLine->styleList.GetCount ())
    return true;   // error, style doesn't exist

  CStyle * pStyle;
  POSITION pos;
  int iCol = 0;
  int iCount = 1;

  // search for it sequentially so we know the column number, 
  // so we can get its text
  for (pos = pLine->styleList.GetHeadPosition(); pos; iCount++)
    {
    pStyle = pLine->styleList.GetNext (pos);
    if (iCount == iStyleNumber)
      break;  // found right one
    
    if (!pos)
      return true;   // error, style doesn't exist

    iCol += pStyle->iLength; // new column

    } // end of looping looking for it

    int iAction = 0;
    switch (pStyle->iFlags & ACTIONTYPE)
      {
      case ACTION_NONE:       iAction = 0; break;
      case ACTION_SEND:       iAction = 1; break;
      case ACTION_HYPERLINK:  iAction = 2; break;
      case ACTION_PROMPT:     iAction = 3; break;
      } // end of switch


    COLORREF colour1,
             colour2;

    pDoc->GetStyleRGB (pStyle, colour1, colour2);
    CAction * pAction = pStyle->pAction;

//  1: text of style
//  2: length of style run
//  3: starting column of style
//  4: action type - 0=none, 1=send to mud, 2=hyperlink, 3=prompt
//  5: action   (eg. what to send)
//  6: hint     (what to show)
//  7: variable (variable to set)
//  8: true if bold
//  9: true if underlined
// 10: true if blinking
// 11: true if inverse
// 12: true if changed by trigger from original
// 13: true if start of a tag (action is tag name)
// 14: foreground (text) colour in RGB
// 15: background colour in RGB

  lua_newtable(L);                                                            
  MakeTableItem     (L, "text",     strText.Mid (iCol, pStyle->iLength)); // 1
  MakeTableItem     (L, "length",   pStyle->iLength); // 2
  MakeTableItem     (L, "column",   iCol + 1); // 3
  MakeTableItem     (L, "actiontype", iAction); // 4
  MakeTableItem     (L, "action",   pAction ? pAction->m_strAction : ""); // 5
  MakeTableItem     (L, "hint",     pAction ? pAction->m_strHint : ""); // 6
  MakeTableItem     (L, "variable", pAction ? pAction->m_strVariable : ""); // 7
  MakeTableItemBool (L, "bold",     (pStyle->iFlags & HILITE) != 0); // 8
  MakeTableItemBool (L, "ul",       (pStyle->iFlags & UNDERLINE) != 0); // 9
  MakeTableItemBool (L, "blink",    (pStyle->iFlags & BLINK) != 0); // 10
  MakeTableItemBool (L, "inverse",  (pStyle->iFlags & INVERSE) != 0); // 11
  MakeTableItemBool (L, "changed",  (pStyle->iFlags & CHANGED) != 0); // 12
  MakeTableItemBool (L, "starttag", (pStyle->iFlags & START_TAG) != 0); // 13
  MakeTableItem     (L, "textcolour", colour1); // 14
  MakeTableItem     (L, "backcolour", colour2); // 15

  return false;   // OK return
  } // end of DoStyle

//----------------------------------------
//  world.GetStyleInfo
// - extension will return a table of types, or table of tables
//----------------------------------------
static int L_GetStyleInfo (lua_State *L)
  {

  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  int iLine = my_checknumber (L, 1);            // LineNumber  
  int iStyleNumber = my_optnumber (L, 2, 0);    // StyleNumber 
  int iType = my_optnumber (L, 3, 0);           // InfoType    

  CLine * pLine = NULL;
  CString strText;

  if (iStyleNumber == 0 || iType == 0)  // extension
    {
    // check line exists
    if (iLine <= 0 || iLine > pDoc->m_LineList.GetCount ())
      return 0;     // no result for no line

    // get pointer to line in question

    pLine = pDoc->m_LineList.GetAt (pDoc->GetLinePosition (iLine - 1));
    strText = CString (pLine->text, pLine->len);

    }

  // if style is zero, make a table per style
  if (iStyleNumber == 0)  // do all styles
    {
    lua_newtable(L);    // table has one entry per style                                                         
    for (iStyleNumber = 1; iStyleNumber <= pLine->styleList.GetCount (); iStyleNumber++)
      {
      if (iType == 0)   // all types wanted
        DoStyle (L, pDoc, pLine, iStyleNumber, strText);
      else
        {   // a single type, use our usual routine to get it
        COleVariant v = pDoc->GetStyleInfo (iLine, iStyleNumber, iType); 
        pushVariant (L, v);
        }

      lua_rawseti(L, -2, iStyleNumber);  // put individual style table into line table
      }  // for each style
    luaL_setn (L, -1, iStyleNumber - 1);   // set table size now
    return 1;   // one table
    }

  // only one style, however they want all types for it
  if (iType == 0)
    {
    if (DoStyle (L, pDoc, pLine, iStyleNumber, strText))
      return 0;   // error, no table returned
    return 1;   // one table
    }

  // here for usual behaviour
  COleVariant v = pDoc->GetStyleInfo (iLine, iStyleNumber, iType); 
  return pushVariant (L, v);
  } // end of L_GetStyleInfo

//----------------------------------------
//  world.GetSysColor
//----------------------------------------
static int L_GetSysColor (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetSysColor (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_GetSysColor

//----------------------------------------
//  world.GetSystemMetrics
//----------------------------------------
static int L_GetSystemMetrics (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetSystemMetrics (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of L_GetSystemMetrics

//----------------------------------------
//  world.GetTimer
//----------------------------------------
static int L_GetTimer (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);

  COleVariant Hour, 
              Minute, 
              Second, 
              ResponseText, 
              Flags, 
              ScriptName;

  long result = pDoc->GetTimer(my_checkstring (L, 1),  // name
                                  &Hour, 
                                  &Minute, 
                                  &Second, 
                                  &ResponseText, 
                                  &Flags, 
                                  &ScriptName); 

  lua_pushnumber (L, result);       // 1
  pushVariant (L, Hour);            // 2
  pushVariant (L, Minute);          // 3
  pushVariant (L, Second);          // 4
  pushVariant (L, ResponseText);    // 5
  pushVariant (L, Flags);           // 6
  pushVariant (L, ScriptName);      // 7

  return 7;  // number of result fields
  } // end of L_GetTimer


//----------------------------------------
//  world.GetTimerInfo
//----------------------------------------
static int L_GetTimerInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetTimerInfo (
      my_checkstring (L, 1),    // TimerName
      my_checknumber (L, 2)     // Type
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetTimerInfo


//----------------------------------------
//  world.GetTimerList
//----------------------------------------
static int L_GetTimerList (lua_State *L)
  {
  COleVariant v = doc (L)->GetTimerList ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetTimerList


//----------------------------------------
//  world.GetTimerOption
//----------------------------------------
static int L_GetTimerOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetTimerOption (
      my_checkstring (L, 1),    // TimerName
      my_checkstring (L, 2)     // Option name
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetTimerOption


//----------------------------------------
//  world.GetTrigger
//----------------------------------------
static int L_GetTrigger (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);

  COleVariant MatchText, 
              ResponseText, 
              Flags, 
              Colour, 
              Wildcard, 
              SoundFileName, 
              ScriptName;

  long result = pDoc->GetTrigger(my_checkstring (L, 1),  // name
                                  &MatchText, 
                                  &ResponseText, 
                                  &Flags, 
                                  &Colour, 
                                  &Wildcard, 
                                  &SoundFileName, 
                                  &ScriptName); 

  lua_pushnumber (L, result);      // 1
  pushVariant (L, MatchText);      // 2
  pushVariant (L, ResponseText);   // 3
  pushVariant (L, Flags);          // 4
  pushVariant (L, Colour);         // 5
  pushVariant (L, Wildcard);       // 6
  pushVariant (L, SoundFileName);  // 7
  pushVariant (L, ScriptName);     // 8

  return 8;  // number of result fields
  } // end of L_GetTrigger


//----------------------------------------
//  world.GetTriggerInfo
//----------------------------------------
static int L_GetTriggerInfo (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetTriggerInfo (
      my_checkstring (L, 1),    // TriggerName
      my_checknumber (L, 2)     // Type
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetTriggerInfo


//----------------------------------------
//  world.GetTriggerList
//----------------------------------------
static int L_GetTriggerList (lua_State *L)
  {
  COleVariant v = doc (L)->GetTriggerList ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetTriggerList


//----------------------------------------
//  world.GetTriggerOption
//----------------------------------------
static int L_GetTriggerOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetTriggerOption (
      my_checkstring (L, 1),    // TriggerName
      my_checkstring (L, 2)     // Option name
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetTriggerOption


//----------------------------------------
//  world.GetTriggerWildcard
//----------------------------------------
static int L_GetTriggerWildcard (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetTriggerWildcard (
      my_checkstring (L, 1),    // Name
      my_checkstring (L, 2)     // Wildcard name
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetTriggerWildcard


//----------------------------------------
//  world.GetUdpPort
//----------------------------------------
static int L_GetUdpPort (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetUdpPort (
      my_checknumber (L, 1),    // First
      my_checknumber (L, 2)     // Last
    ));
  return 1;  // number of result fields
  } // end of L_GetUdpPort


//----------------------------------------
//  world.GetUniqueID
//----------------------------------------
static int L_GetUniqueID (lua_State *L)
  {
  BSTR str = doc (L)->GetUniqueID ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetUniqueID


//----------------------------------------
//  world.GetUniqueNumber
//----------------------------------------
static int L_GetUniqueNumber (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetUniqueNumber ());
  return 1;  // number of result fields
  } // end of L_GetUniqueNumber


//----------------------------------------
//  world.GetVariable
//----------------------------------------
static int L_GetVariable (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->GetVariable (
      my_checkstring (L, 1)    // VariableName
    );
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetVariable


//----------------------------------------
//  world.GetVariableList
// extension - returns variable name *and* value
//----------------------------------------
static int L_GetVariableList (lua_State *L)
  {
  GetVariableListHelper (L, doc (L));
  return 1;  // number of result fields  (one table)
  } // end of L_GetVariableList


//----------------------------------------
//  world.GetWorld
//----------------------------------------
static int L_GetWorld (lua_State *L)
  {
  CString strName = my_checkstring (L, 1);

  for (POSITION docPos = App.m_pWorldDocTemplate->GetFirstDocPosition();
      docPos != NULL; )
    {
    CMUSHclientDoc * pDoc = (CMUSHclientDoc *) App.m_pWorldDocTemplate->GetNextDoc(docPos);
  
    if (pDoc->m_mush_name.CompareNoCase (strName) == 0)
      {
      // our "world" is a userdatum which is a pointer (to a pointer) to the world
      CMUSHclientDoc **ud = (CMUSHclientDoc **)lua_newuserdata(L, sizeof (CMUSHclientDoc *));
      luaL_getmetatable(L, mushclient_typename);
      lua_setmetatable(L, -2);
      *ud = pDoc;    // store pointer to this world in the userdata
      return 1;

      } // end of world found
    } // end of doing each document

  return 0;  // number of result fields
  } // end of L_GetWorld


//----------------------------------------
//  world.GetWorldById
//----------------------------------------
static int L_GetWorldById (lua_State *L)
  {
  CString WorldID = my_checkstring (L, 1);

  for (POSITION docPos = App.m_pWorldDocTemplate->GetFirstDocPosition();
      docPos != NULL; )
    {
    CMUSHclientDoc * pDoc = (CMUSHclientDoc *) App.m_pWorldDocTemplate->GetNextDoc(docPos);
  
    if (pDoc->m_strWorldID.CompareNoCase (WorldID) == 0)
      {
      // our "world" is a userdatum which is a pointer (to a pointer) to the world
      CMUSHclientDoc **ud = (CMUSHclientDoc **)lua_newuserdata(L, sizeof (CMUSHclientDoc *));
      luaL_getmetatable(L, mushclient_typename);
      lua_setmetatable(L, -2);
      *ud = pDoc;    // store pointer to this world in the userdata
      return 1;

      } // end of world found
    } // end of doing each document

  return 0;  // number of result fields
  } // end of L_GetWorldById


//----------------------------------------
//  world.GetWorldID
//----------------------------------------
static int L_GetWorldID (lua_State *L)
  {
  BSTR str = doc (L)->GetWorldID ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_GetWorldID

//----------------------------------------
//  world.GetWorldIdList
//----------------------------------------
static int L_GetWorldIdList (lua_State *L)
  {
  COleVariant v = doc (L)->GetWorldIdList ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetWorldIdList


//----------------------------------------
//  world.GetWorldList
//----------------------------------------
static int L_GetWorldList (lua_State *L)
  {
  COleVariant v = doc (L)->GetWorldList ();
  return pushVariant (L, v);  // number of result fields
  } // end of L_GetWorldList


//----------------------------------------
//  world.Hash
//----------------------------------------
static int L_Hash (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->Hash (my_checkstring (L, 1));
  return pushBstr (L, str);  // number of result fields
  } // end of L_Hash

//----------------------------------------
//  world.Help
//----------------------------------------
static int L_Help (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->Help (my_optstring (L, 1, ""));
  return 0;  // number of result fields
  } // end of L_Help

//----------------------------------------
//  world.Hyperlink
//----------------------------------------
static int L_Hyperlink (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->Hyperlink (
                      my_checkstring (L, 1),  // Action
                      my_checkstring (L, 2),  // Text
                      my_checkstring (L, 3),  // Hint
                      my_checkstring (L, 4),  // TextColour
                      my_checkstring (L, 5),  // BackColour
                      optboolean (L, 6, 0)   // URL  - optional
                      );
  return 0;  // number of result fields
  } // end of L_Hyperlink


//----------------------------------------
//  world.ImportXML
//----------------------------------------
static int L_ImportXML (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ImportXML (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ImportXML


//----------------------------------------
//  world.Info
//----------------------------------------
static int L_Info (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  pDoc->Info (concatArgs (L).c_str ());
//  lua_concat (L, lua_gettop (L));
//  pDoc->Info (my_checkstring (L, 1));
  return 0;  // number of result fields
  } // end of L_Info


//----------------------------------------
//  world.InfoBackground
//----------------------------------------
static int L_InfoBackground (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->InfoBackground (my_checkstring (L, 1));
  return 0;  // number of result fields
  } // end of L_InfoBackground


//----------------------------------------
//  world.InfoClear
//----------------------------------------
static int L_InfoClear (lua_State *L)
  {
  doc (L)->InfoClear ();
  return 0;  // number of result fields
  } // end of L_InfoClear


//----------------------------------------
//  world.InfoColour
//----------------------------------------
static int L_InfoColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->InfoColour (my_checkstring (L, 1));
  return 0;  // number of result fields
  } // end of L_InfoColour


//----------------------------------------
//  world.InfoFont
//----------------------------------------
static int L_InfoFont (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->InfoFont (
                    my_checkstring (L, 1),    // FontName
                    my_checknumber (L, 2),    // Size
                    my_checknumber (L, 3)     // Style
                    );
  return 0;  // number of result fields
  } // end of L_InfoFont


//----------------------------------------
//  world.IsAlias
//----------------------------------------
static int L_IsAlias (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->IsAlias (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_IsAlias


//----------------------------------------
//  world.IsConnected
//----------------------------------------
static int L_IsConnected (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->IsConnected ());
  return 1;  // number of result fields
  } // end of L_IsConnected


//----------------------------------------
//  world.IsLogOpen
//----------------------------------------
static int L_IsLogOpen (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->IsLogOpen ());
  return 1;  // number of result fields
  } // end of L_IsLogOpen


//----------------------------------------
//  world.IsPluginInstalled
//----------------------------------------
static int L_IsPluginInstalled (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushboolean (L, pDoc->IsPluginInstalled (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_IsPluginInstalled


//----------------------------------------
//  world.IsTimer
//----------------------------------------
static int L_IsTimer (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->IsTimer (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_IsTimer


//----------------------------------------
//  world.IsTrigger
//----------------------------------------
static int L_IsTrigger (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->IsTrigger (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_IsTrigger


//----------------------------------------
//  world.LoadPlugin
//----------------------------------------
static int L_LoadPlugin (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->LoadPlugin (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_LoadPlugin


//----------------------------------------
//  world.GetLogInput
//----------------------------------------
static int L_GetLogInput (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->m_log_input);
  return 1;  // number of result fields
  } // end of L_GetLogInput

//----------------------------------------
//  world.SetLogInput
//----------------------------------------
static int L_SetLogInput (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->m_log_input = optboolean (L, 1, 1) != 0;
  return 0;  // number of result fields
  } // end of L_SetLogInput


//----------------------------------------
//  world.GetLogNotes
//----------------------------------------
static int L_GetLogNotes (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->m_bLogNotes);
  return 1;  // number of result fields
  } // end of L_GetLogNotes

//----------------------------------------
//  world.SetLogNotes
//----------------------------------------
static int L_SetLogNotes (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->m_bLogNotes = optboolean (L, 1, 1) != 0;
  return 0;  // number of result fields
  } // end of L_SetLogNotes


//----------------------------------------
//  world.GetLogOutput
//----------------------------------------
static int L_GetLogOutput (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->m_bLogOutput);
  return 1;  // number of result fields
  } // end of L_GetLogOutput

//----------------------------------------
//  world.SetLogOutput
//----------------------------------------
static int L_SetLogOutput (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->m_bLogOutput = optboolean (L, 1, 1) != 0;
  return 0;  // number of result fields
  } // end of L_SetLogOutput

//----------------------------------------
//  world.LogSend
//----------------------------------------
static int L_LogSend (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushnumber (L, pDoc->LogSend (concatArgs (L).c_str ()));

//  lua_concat (L, lua_gettop (L));
//  lua_pushnumber (L, pDoc->LogSend (my_checkstring (L, 1)));

  return 1;  // number of result fields
  } // end of L_LogSend

//----------------------------------------
//  world.MapColour
//----------------------------------------
static int L_MapColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->MapColour (
      my_checknumber (L, 1),  // Original
      my_checknumber (L, 2)   // Replacement
      );
  return 0;  // number of result fields
  } // end of L_MapColour

//----------------------------------------
//  world.MapColourList
//----------------------------------------
static int L_MapColourList (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_newtable(L);                                                            

  map<COLORREF, COLORREF>::const_iterator it;

  for (it = pDoc->m_ColourTranslationMap.begin (); 
       it != pDoc->m_ColourTranslationMap.end (); it++)
    {
    lua_pushnumber (L, it->first);
    lua_pushnumber (L, it->second);
    lua_rawset(L, -3);
    }      // end of looping through each colour

  return 1;  // 1 table
  } // end of L_MapColourList

//----------------------------------------
//  world.GetMapping
//----------------------------------------
static int L_GetMapping (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->m_bMapping);
  return 1;  // number of result fields
  } // end of L_GetMapping

//----------------------------------------
//  world.SetMapping
//----------------------------------------
static int L_SetMapping (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->m_bMapping = optboolean (L, 1, 1) != 0;
  return 0;  // number of result fields
  } // end of L_SetMapping

//----------------------------------------
//  world.Metaphone
//----------------------------------------
static int L_Metaphone (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->Metaphone (my_checkstring (L, 1),
                              my_optnumber (L, 2, 4));
  return pushBstr (L, str);
  } // end of L_Metaphone

//----------------------------------------
//  world.GetNormalColour
//----------------------------------------
static int L_GetNormalColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetNormalColour (my_checknumber (L, 1)));
  return 1;  // number of result fields
  } // end of GetNormalColour

//----------------------------------------
//  world.SetNormalColour
//----------------------------------------
static int L_SetNormalColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetNormalColour (
      my_checknumber (L, 1),  // WhichColour
      my_checknumber (L, 2)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of SetNormalColour

//----------------------------------------
//  world.MoveMainWindow
//----------------------------------------
static int L_MoveMainWindow (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->MoveMainWindow (
      my_checknumber (L, 1),  // Left
      my_checknumber (L, 2),  // Top
      my_checknumber (L, 3),  // Width
      my_checknumber (L, 4)   // Height
      );
  return 0;  // number of result fields
  } // end of L_MoveMainWindow

//----------------------------------------
//  world.MoveWorldWindow
//----------------------------------------
static int L_MoveWorldWindow (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->MoveWorldWindowX (
      my_checknumber (L, 1),  // Left
      my_checknumber (L, 2),  // Top
      my_checknumber (L, 3),  // Width
      my_checknumber (L, 4),   // Height
      my_optnumber (L, 5, 1)  // Which
      );
  return 0;  // number of result fields
  } // end of L_MoveWorldWindow

//----------------------------------------
//  world.MoveNotepadWindow
//----------------------------------------
static int L_MoveNotepadWindow (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushboolean (L, pDoc->MoveNotepadWindow (
      my_checkstring (L, 1),  // title
      my_checknumber (L, 2),  // Left
      my_checknumber (L, 3),  // Top
      my_checknumber (L, 4),  // Width
      my_checknumber (L, 5)   // Height
      ));
  return 1;  // number of result fields
  } // end of L_MoveNotepadWindow

//----------------------------------------
//  world.MtSrand
//----------------------------------------
static int L_MtSrand (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);

// Lua extension - allow for table of seeds

  if (lua_istable (L, 1))
    {
    vector <unsigned long> v;
    lua_pushnil (L);  // first key
    while (lua_next (L, 1) != 0)
      {
      if (!lua_isnumber (L, -1))
        luaL_error (L, "MtSrand table must consist of numbers");

      v.push_back (lua_tonumber (L, -1));
      lua_pop (L, 1);   // remove value, keep key for next iteration
      } // end of extracting vector of keys
    if (v.size () == 0)
      luaL_error (L, "MtSrand table must not be empty");

    init_by_array (&v [0], v.size ());
    }
  else
    pDoc->MtSrand (my_checknumber (L, 1));
  return 0;  // number of result fields
  } // end of L_MtSrand

//----------------------------------------
//  world.MtRand
//----------------------------------------
static int L_MtRand (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->MtRand ());
  return 1;  // number of result fields
  } // end of L_MtRand

//----------------------------------------
//  world.Note
//----------------------------------------
static int L_Note (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  pDoc->Note (concatArgs (L).c_str ());

//  lua_concat (L, lua_gettop (L));
//  pDoc->Note (my_checkstring (L, 1));

  return 0;  // number of result fields
  } // end of L_Note

//----------------------------------------
//  world.NoteHr
//----------------------------------------
static int L_NoteHr (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  pDoc->NoteHr ();
  return 0;  // number of result fields
  } // end of L_NoteHr


//----------------------------------------
//  world.GetNoteColour
//----------------------------------------
static int L_GetNoteColour (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetNoteColour ());
  return 1;  // number of result fields
  } // end of GetNoteColour

//----------------------------------------
//  world.SetNoteColour
//----------------------------------------
static int L_SetNoteColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetNoteColour (
      my_checknumber (L, 1)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of SetNoteColour


//----------------------------------------
//  world.GetNoteColourBack
//----------------------------------------
static int L_GetNoteColourBack (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetNoteColourBack ());
  return 1;  // number of result fields
  } // end of GetNoteColourBack

//----------------------------------------
//  world.SetNoteColourBack
//----------------------------------------
static int L_SetNoteColourBack (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetNoteColourBack (
      my_checknumber (L, 1)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of SetNoteColourBack


//----------------------------------------
//  world.GetNoteColourFore
//----------------------------------------
static int L_GetNoteColourFore (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->GetNoteColourFore ());
  return 1;  // number of result fields
  } // end of GetNoteColourFore

//----------------------------------------
//  world.SetNoteColourFore
//----------------------------------------
static int L_SetNoteColourFore (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetNoteColourFore (
      my_checknumber (L, 1)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of SetNoteColourFore


//----------------------------------------
//  world.NoteColourName
//----------------------------------------
static int L_NoteColourName (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->NoteColourName (
      my_checkstring (L, 1),    // Foreground
      my_checkstring (L, 2)     // Background
      );
  return 0;  // number of result fields
  } // end of L_NoteColourName


//----------------------------------------
//  world.NoteColourRGB
//----------------------------------------
static int L_NoteColourRGB (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->NoteColourRGB (
      my_checknumber (L, 1),    // Foreground
      my_checknumber (L, 2)     // Background
      );
  return 0;  // number of result fields
  } // end of L_NoteColourRGB

//----------------------------------------
//  world.NotepadColour
//----------------------------------------
static int L_NotepadColour (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->NotepadColour (
        my_checkstring (L, 1),   // Title
        my_checkstring (L, 2),   // TextColour
        my_checkstring (L, 3)    // BackgroundColour
                      ));
  return 1;  // number of result fields
  } // end of L_NotepadColour

//----------------------------------------
//  world.NotepadFont
//----------------------------------------
static int L_NotepadFont (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->NotepadFont (
        my_checkstring (L, 1),   // Title
        my_checkstring (L, 2),   // FontName
        my_checknumber (L, 3),   // Size
        my_checknumber (L, 4),   // Style
        my_optnumber (L, 5, 0)   // Charset
                      ));
  return 1;  // number of result fields
  } // end of L_NotepadFont

//----------------------------------------
//  world.NotepadSaveMethod
//----------------------------------------
static int L_NotepadSaveMethod (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->NotepadSaveMethod (
        my_checkstring (L, 1),   // Title
        my_checknumber (L, 2)    // Method (0-2)
                      ));
  return 1;  // number of result fields
  } // end of L_NotepadSaveMethod

//----------------------------------------
//  world.NoteStyle
//----------------------------------------
static int L_NoteStyle (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->NoteStyle (
      my_checknumber (L, 1)    // Style
      );
  return 0;  // number of result fields
  } // end of L_NoteStyle


//----------------------------------------
//  world.Open
//----------------------------------------
static int L_Open (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  // this is pushing it - what if it isn't a MUSHclient world?
  // I think I won't support this right now

//  pDoc->Open (my_checkstring (L, 1));
  return 0;  // number of result fields
  } // end of L_Open

//----------------------------------------
//  world.OpenBrowser
//----------------------------------------
static int L_OpenBrowser (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);

  lua_pushnumber (L, pDoc->OpenBrowser (
      my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_OpenBrowser

//----------------------------------------
//  world.OpenLog
//----------------------------------------
static int L_OpenLog (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->OpenLog (
      my_checkstring (L, 1),      // LogFileName
      optboolean (L, 2, 0)      // Append - optional
      ));
  return 1;  // number of result fields
  } // end of L_OpenLog


//----------------------------------------
//  world.PasteCommand
//----------------------------------------
static int L_PasteCommand (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->PasteCommand (my_checkstring (L, 1));
  return pushBstr (L, str);
  } // end of L_PasteCommand

//----------------------------------------
//  world.Pause
//----------------------------------------
static int L_Pause (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->Pause (optboolean (L, 1, 1));
  return 0;  // number of result fields
  } // end of L_Pause


//----------------------------------------
//  world.PluginSupports
//----------------------------------------
static int L_PluginSupports (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->PluginSupports (
      my_checkstring (L, 1),      // PluginID
      my_checkstring (L, 2)       // Routine
      ));
  return 1;  // number of result fields
  } // end of L_PluginSupports


//----------------------------------------
//  world.PushCommand
//----------------------------------------
static int L_PushCommand (lua_State *L)
  {
  BSTR str = doc (L)->PushCommand ();
  return pushBstr (L, str);
  } // end of L_PushCommand


//----------------------------------------
//  world.Queue
//----------------------------------------
static int L_Queue (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->Queue (
      my_checkstring (L, 1),      // Message
      optboolean (L, 2, 1)      // Echo - optional
      ));
  return 1;  // number of result fields
  } // end of L_Queue


//----------------------------------------
//  world.ReadNamesFile
//----------------------------------------
static int L_ReadNamesFile (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ReadNamesFile (
      my_checkstring (L, 1)      // FileName
      ));
  return 1;  // number of result fields
  } // end of L_ReadNamesFile


//----------------------------------------
//  world.Redraw
//----------------------------------------
static int L_Redraw (lua_State *L)
  {
  doc (L)->Redraw ();
  return 0;  // number of result fields
  } // end of L_Redraw


//----------------------------------------
//  world.ReloadPlugin
//----------------------------------------
static int L_ReloadPlugin (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ReloadPlugin (
      my_checkstring (L, 1)      // PluginID
      ));
  return 1;  // number of result fields
  } // end of L_ReloadPlugin


//----------------------------------------
//  world.RemoveBacktracks
//----------------------------------------
static int L_RemoveBacktracks (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->RemoveBacktracks (my_checkstring (L, 1));
  return pushBstr (L, str);
  } // end of L_RemoveBacktracks


//----------------------------------------
//  world.GetRemoveMapReverses
//----------------------------------------
static int L_GetRemoveMapReverses (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->m_bRemoveMapReverses);
  return 1;  // number of result fields
  } // end of L_GetRemoveMapReverses

//----------------------------------------
//  world.SetRemoveMapReverses
//----------------------------------------
static int L_SetRemoveMapReverses (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->m_bRemoveMapReverses = my_checknumber (L, 1) != 0;
  return 0;  // number of result fields
  } // end of L_SetRemoveMapReverses


//----------------------------------------
//  world.Replace
//----------------------------------------
static int L_Replace (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->Replace (
      my_checkstring (L, 1),    // Source
      my_checkstring (L, 2),    // SearchFor
      my_checkstring (L, 3),    // ReplaceWith
      optboolean (L, 4, 1)    // Multiple - optional
      );
  return pushBstr (L, str);
  } // end of L_Replace


//----------------------------------------
//  world.ReplaceNotepad
//----------------------------------------
static int L_ReplaceNotepad (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushboolean (L, pDoc->ReplaceNotepad (
      my_checkstring (L, 1),  // Title
      concatArgs (L, "", 2).c_str ()   // Contents
      ));
  return 0;  // number of result fields
  } // end of L_ReplaceNotepad


//----------------------------------------
//  world.Reset
//----------------------------------------
static int L_Reset (lua_State *L)
  {
  doc (L)->Reset ();
  return 0;  // number of result fields
  } // end of L_Reset


//----------------------------------------
//  world.ResetIP
//----------------------------------------
static int L_ResetIP (lua_State *L)
  {
  doc (L)->ResetIP ();
  return 0;  // number of result fields
  } // end of ResetIP


//----------------------------------------
//  world.ResetStatusTime
//----------------------------------------
static int L_ResetStatusTime (lua_State *L)
  {
  doc (L)->ResetStatusTime ();
  return 0;  // number of result fields
  } // end of L_ResetStatusTime


//----------------------------------------
//  world.ResetTimer
//----------------------------------------
static int L_ResetTimer (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->ResetTimer (
      my_checkstring (L, 1)      // TimerName
      ));
  return 1;  // number of result fields
  } // end of L_ResetTimer


//----------------------------------------
//  world.ResetTimers
//----------------------------------------
static int L_ResetTimers (lua_State *L)
  {
  doc (L)->ResetTimers ();
  return 0;  // number of result fields
  } // end of L_ResetTimers


//----------------------------------------
//  world.ReverseSpeedwalk
//----------------------------------------
static int L_ReverseSpeedwalk (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  // this is a helper function that returns a CString, not a BSTR
  lua_pushstring (L, pDoc->DoReverseSpeedwalk (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_ReverseSpeedwalk


//----------------------------------------
//  world.RGBColourToName
//----------------------------------------
static int L_RGBColourToName (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->RGBColourToName (my_checknumber (L, 1));
  return pushBstr (L, str);
  } // end of L_RGBColourToName


//----------------------------------------
//  world.Save
//----------------------------------------
static int L_Save (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushboolean (L, pDoc->Save (
      my_optstring (L, 1, "")  // Name
      ));
  return 1;  // number of result fields
  } // end of L_Save


//----------------------------------------
//  world.SaveNotepad
//----------------------------------------
static int L_SaveNotepad (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SaveNotepad (
      my_checkstring (L, 1),     // Title
      my_checkstring (L, 2),     // FileName
      optboolean (L, 3, 0)     // ReplaceExisting
      ));
  return 1;  // number of result fields
  } // end of L_SaveNotepad


//----------------------------------------
//  world.SaveState
//----------------------------------------
static int L_SaveState (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SaveState ());
  return 1;  // number of result fields
  } // end of L_SaveState


//----------------------------------------
//  world.SelectCommand
//----------------------------------------
static int L_SelectCommand (lua_State *L)
  {
  doc (L)->SelectCommand ();
  return 0;  // number of result fields
  } // end of L_SelectCommand


//----------------------------------------
//  world.Send
//----------------------------------------
static int L_Send (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushnumber (L, pDoc->Send (concatArgs (L).c_str ()));
  return 1;  // number of result fields
  } // end of L_Send


//----------------------------------------
//  world.SendImmediate
//----------------------------------------
static int L_SendImmediate (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushnumber (L, pDoc->SendImmediate (concatArgs (L).c_str ()));
  return 1;  // number of result fields
  } // end of L_SendImmediate


//----------------------------------------
//  world.SendNoEcho
//----------------------------------------
static int L_SendNoEcho (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushnumber (L, pDoc->SendNoEcho (concatArgs (L).c_str ()));
  return 1;  // number of result fields
  } // end of L_SendNoEcho

//----------------------------------------
//  world.SendPkt
//----------------------------------------
static int L_SendPkt (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first

  long result = eWorldClosed;

  if (pDoc->m_iConnectPhase == eConnectConnectedToMud)
    {
    // get text to send (can include nulls)
    size_t textLength;
    const char * text = my_checklstring (L, 1, &textLength);
    pDoc->SendPacket (text, textLength);
	  result = eOK;
    }

  lua_pushnumber (L, result);
  return 1;  // number of result fields
  } // end of L_SendPkt

//----------------------------------------
//  world.SendPush
//----------------------------------------
static int L_SendPush (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushnumber (L, pDoc->SendPush (concatArgs (L).c_str ()));
  return 1;  // number of result fields
  } // end of L_SendPush


//----------------------------------------
//  world.SendToNotepad
//----------------------------------------
static int L_SendToNotepad (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushboolean (L, pDoc->SendToNotepad (
      my_checkstring (L, 1), // Title
      concatArgs (L, "", 2).c_str ()  // Contents
      ));
  return 1;  // number of result fields
  } // end of L_SendToNotepad


//----------------------------------------
//  world.SetAliasOption
//----------------------------------------
static int L_SetAliasOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetAliasOption (
      my_checkstring (L, 1),    // AliasName
      my_checkstring (L, 2),    // OptionName
      my_checkstring (L, 3)     // Value
      ));
  return 1;  // number of result fields
  } // end of L_SetAliasOption


//----------------------------------------
//  world.SetAlphaOption
//----------------------------------------
static int L_SetAlphaOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetAlphaOption (
      my_checkstring (L, 1),    // OptionName
      my_checkstring (L, 2)     // Value
      ));
  return 1;  // number of result fields
  } // end of L_SetAlphaOption


//----------------------------------------
//  world.SetChatOption
//----------------------------------------
static int L_SetChatOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetChatOption (
      my_checknumber (L, 1),    // Chat ID
      my_checkstring (L, 2),    // OptionName
      my_checkstring (L, 3)     // Value
      ));
  return 1;  // number of result fields
  } // end of L_SetChatOption


//----------------------------------------
//  world.SetChanged
//----------------------------------------
static int L_SetChanged (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetChanged (optboolean (L, 1, 1));
  return 0;  // number of result fields
  } // end of L_SetChanged

//----------------------------------------
//  world.SetClipboard
//----------------------------------------
static int L_SetClipboard (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetClipboard (concatArgs (L).c_str ());
  return 0;  // number of result fields
  } // end of L_SetClipboard

//----------------------------------------
//  world.SetCommand
//----------------------------------------
static int L_SetCommand (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetCommand (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_SetCommand

//----------------------------------------
//  world.SetEntity
//----------------------------------------
static int L_SetEntity (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetEntity (my_checkstring (L, 1),
                   my_optstring (L, 2, ""));
  return 0;  // number of result fields
  } // end of L_SetEntity

//----------------------------------------
//  world.SetInputFont
//----------------------------------------
static int L_SetInputFont (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetInputFont (
      my_checkstring (L, 1),  // FontName
      my_checknumber (L, 2),  // PointSize
      my_checknumber (L, 3),  // Weight
      my_optnumber (L, 4, 0)  // Italic
      );
  return 0;  // number of result fields
  } // end of L_SetInputFont


//----------------------------------------
//  world.SetNotes
//----------------------------------------
static int L_SetNotes (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetNotes (my_checkstring (L, 1));
  return 0;  // number of result fields
  } // end of L_SetNotes


//----------------------------------------
//  world.SetOption
//----------------------------------------
static int L_SetOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetOption (
      my_checkstring (L, 1),    // OptionName
      my_checknumber (L, 2)     // Value
      ));
  return 1;  // number of result fields
  } // end of L_SetOption


//----------------------------------------
//  world.SetOutputFont
//----------------------------------------
static int L_SetOutputFont (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetOutputFont (
      my_checkstring (L, 1),  // FontName
      my_checknumber (L, 2)   // PointSize
      );
  return 0;  // number of result fields
  } // end of L_SetOutputFont


//----------------------------------------
//  world.SetStatus
//----------------------------------------
static int L_SetStatus (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  pDoc->SetStatus (concatArgs (L).c_str ());
  return 0;  // number of result fields
  } // end of L_SetStatus


//----------------------------------------
//  world.SetTimerOption
//----------------------------------------
static int L_SetTimerOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetTimerOption (
      my_checkstring (L, 1),    // AliasName
      my_checkstring (L, 2),    // OptionName
      my_checkstring (L, 3)     // Value
      ));
  return 1;  // number of result fields
  } // end of L_SetTimerOption


//----------------------------------------
//  world.SetTriggerOption
//----------------------------------------
static int L_SetTriggerOption (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetTriggerOption (
      my_checkstring (L, 1),    // AliasName
      my_checkstring (L, 2),    // OptionName
      my_checkstring (L, 3)     // Value
      ));
  return 1;  // number of result fields
  } // end of L_SetTriggerOption


//----------------------------------------
//  world.SetVariable
//----------------------------------------
static int L_SetVariable (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SetVariable (
      my_checkstring (L, 1),    // VariableName
      my_checkstring (L, 2)     // Contents
      ));
  return 1;  // number of result fields
  } // end of L_SetVariable

//----------------------------------------
//  world.SetWorldWindowStatus
//----------------------------------------
static int L_SetWorldWindowStatus (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetWorldWindowStatus (my_checknumber (L, 1));
  return 0;  // number of result fields
  } // end of L_SetWorldWindowStatus


//----------------------------------------
//  world.ShowInfoBar
//----------------------------------------
static int L_ShowInfoBar (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->ShowInfoBar (optboolean (L, 1, 1));
  return 0;  // number of result fields
  } // end of L_ShowInfoBar

//----------------------------------------
//  world.Simulate
//----------------------------------------
static int L_Simulate (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->Simulate (my_checkstring (L, 1));
  return 0;  // number of result fields
  } // end of L_Simulate

//----------------------------------------
//  world.Sound
//----------------------------------------
static int L_Sound (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->Sound (
      my_checkstring (L, 1)    // SoundFileName
      ));
  return 1;  // number of result fields
  } // end of L_Sound


//----------------------------------------
//  world.GetSpeedWalkDelay
//----------------------------------------
static int L_GetSpeedWalkDelay (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->GetSpeedWalkDelay ());
  return 1;  // number of result fields
  } // end of GetSpeedWalkDelay

//----------------------------------------
//  world.SetSpeedWalkDelay
//----------------------------------------
static int L_SetSpeedWalkDelay (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->SetSpeedWalkDelay (
      my_checknumber (L, 1)   // nNewValue
      );
  return 0;  // number of result fields
  } // end of SetSpeedWalkDelay

//----------------------------------------
//  world.SpellCheck
//----------------------------------------
static int L_SpellCheck (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->SpellCheck (my_checkstring (L, 1));
  return pushVariant (L, v);
  } // end of L_SpellCheck

//----------------------------------------
//  world.SpellCheckCommand
//----------------------------------------
static int L_SpellCheckCommand (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->SpellCheckCommand (
            my_optnumber (L, 1, -1),  // Start column
            my_optnumber (L, 2, -1)   // End column
            ));
  return 1;  // number of result fields
  } // end of SpellCheckCommand

//----------------------------------------
//  world.SpellCheckDlg
//----------------------------------------
static int L_SpellCheckDlg (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  COleVariant v = pDoc->SpellCheckDlg (my_checkstring (L, 1));
  return pushVariant (L, v);
  } // end of L_SpellCheckDlg

// prototype ;)
CString StripAnsi (const CString strMessage);

//----------------------------------------
//  world.StripANSI
//----------------------------------------
static int L_StripANSI (lua_State *L)
  {
  // this is a helper function that returns a CString, not a BSTR
  lua_pushstring (L, StripAnsi (my_checkstring (L, 1)));
  return 1;  // number of result fields
  } // end of L_StripANSI


//----------------------------------------
//  world.Tell
//----------------------------------------
static int L_Tell (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  pDoc->Tell (concatArgs (L).c_str ());
  return 0;  // number of result fields
  } // end of L_Tell


//----------------------------------------
//  world.GetTrace
//----------------------------------------
static int L_GetTrace (lua_State *L)
  {
  lua_pushboolean (L, doc (L)->m_bTrace);
  return 1;  // number of result fields
  } // end of L_GetTrace

//----------------------------------------
//  world.SetTrace
//----------------------------------------
static int L_SetTrace (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  pDoc->m_bTrace = optboolean (L, 1, 1) != 0;
  return 0;  // number of result fields
  } // end of L_SetTrace


//----------------------------------------
//  world.TraceOut
//----------------------------------------
static int L_TraceOut (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  pDoc->TraceOut (concatArgs (L).c_str ());
  return 0;  // number of result fields
  } // end of L_TraceOut

//----------------------------------------
//  world.TranslateGerman
//----------------------------------------
static int L_TranslateGerman (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->TranslateGerman (
                  my_checkstring (L, 1)  // Text
                  );
  return pushBstr (L, str);  // number of result fields
  } // end of L_TranslateGerman

//----------------------------------------
//  world.Transparency
//----------------------------------------
static int L_Transparency (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushboolean (L, pDoc->Transparency (
          my_checknumber (L, 1),    // Key
          my_checknumber (L, 2)    // Amount
      ));
  return 1;  // number of result fields
  } // end of L_Transparency

//----------------------------------------
//  world.Trim
//----------------------------------------
static int L_Trim (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  BSTR str = pDoc->Trim (
                  my_checkstring (L, 1)  // Source
                  );
  return pushBstr (L, str);  // number of result fields
  } // end of L_Trim

//----------------------------------------
//  world.UdpListen
//----------------------------------------
static int L_UdpListen (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->UdpListen (
            my_checkstring (L, 1),  // IP
            my_checknumber (L, 2),  // Port
            my_checkstring (L, 3)   // Script
            ));
  return 1;  // number of result fields
  } // end of L_UdpListen

//----------------------------------------
//  world.UdpPortList
//----------------------------------------
static int L_UdpPortList (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  COleVariant v = pDoc->UdpPortList ();
  return pushVariant (L, v);
  } // end of L_UdpPortList

//----------------------------------------
//  world.UdpSend
//----------------------------------------
static int L_UdpSend (lua_State *L)
  {
  CMUSHclientDoc *pDoc = doc (L);
  lua_pushnumber (L, pDoc->UdpSend (
            my_checkstring (L, 1),  // IP
            my_checknumber (L, 2),  // Port
            my_checkstring (L, 3)   // Text
            ));
  return 1;  // number of result fields
  } // end of L_UdpSend

//----------------------------------------
//  world.Version
//----------------------------------------
static int L_Version (lua_State *L)
  {
  BSTR str = doc (L)->Version ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_Version


//----------------------------------------
//  world.WorldAddress
//----------------------------------------
static int L_WorldAddress (lua_State *L)
  {
  BSTR str = doc (L)->WorldAddress ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_WorldAddress


//----------------------------------------
//  world.WorldName
//----------------------------------------
static int L_WorldName (lua_State *L)
  {
  BSTR str = doc (L)->WorldName ();
  return pushBstr (L, str);  // number of result fields
  } // end of L_WorldName


//----------------------------------------
//  world.WorldPort
//----------------------------------------
static int L_WorldPort (lua_State *L)
  {
  lua_pushnumber (L, doc (L)->WorldPort ());
  return 1;  // number of result fields
  } // end of L_WorldPort

//----------------------------------------
//  world.WriteLog
//----------------------------------------
static int L_WriteLog (lua_State *L)
  {
  CMUSHclientDoc * pDoc = doc (L);  // must do this first
  lua_pushnumber (L, pDoc->WriteLog (concatArgs (L).c_str ()));
  return 1;  // number of result fields
  } // end of L_WriteLog

// methods implemented in Lua
// warning - case-sensitive!

// eg. world.Note ("hello ", "world")

static const struct luaL_reg worldlib [] = 
  {

  {"Accelerator", L_Accelerator},
  {"AcceleratorList", L_AcceleratorList},
  {"Activate", L_Activate},
  {"ActivateClient", L_ActivateClient},
  {"ActivateNotepad", L_ActivateNotepad},
  {"AddAlias", L_AddAlias},
  {"AddMapperComment", L_AddMapperComment},
  {"AddSpellCheckWord", L_AddSpellCheckWord},
  {"AddTimer", L_AddTimer},
  {"AddToMapper", L_AddToMapper},
  {"AddTrigger", L_AddTrigger},
  {"AddTriggerEx", L_AddTriggerEx},
  {"AdjustColour", L_AdjustColour},
  {"ANSI", L_ANSI},
  {"AnsiNote", L_AnsiNote},
  {"AppendToNotepad", L_AppendToNotepad},
  {"ArrayClear", L_ArrayClear},
  {"ArrayCount", L_ArrayCount},
  {"ArrayCreate", L_ArrayCreate},
  {"ArrayDelete", L_ArrayDelete},
  {"ArrayDeleteKey", L_ArrayDeleteKey},
  {"ArrayExists", L_ArrayExists},
  {"ArrayExport", L_ArrayExport},
  {"ArrayExportKeys", L_ArrayExportKeys},
  {"ArrayGet", L_ArrayGet},
  {"ArrayGetFirstKey", L_ArrayGetFirstKey},
  {"ArrayGetLastKey", L_ArrayGetLastKey},
  {"ArrayImport", L_ArrayImport},
  {"ArrayKeyExists", L_ArrayKeyExists},
  {"ArrayList", L_ArrayList},
  {"ArrayListAll", L_ArrayListAll},
  {"ArrayListKeys", L_ArrayListKeys},
  {"ArrayListValues", L_ArrayListValues},
  {"ArraySet", L_ArraySet},
  {"ArraySize", L_ArraySize},
  {"Base64Decode", L_Base64Decode},
  {"Base64Encode", L_Base64Encode},
  {"GetBoldColour", L_GetBoldColour},
  {"SetBoldColour", L_SetBoldColour},
  {"BroadcastPlugin", L_BroadcastPlugin},
  {"CallPlugin", L_CallPlugin},
  {"ChangeDir", L_ChangeDir},
  {"ChatAcceptCalls", L_ChatAcceptCalls},
  {"ChatCall", L_ChatCall},
  {"ChatCallzChat", L_ChatCallzChat},
  {"ChatDisconnect", L_ChatDisconnect},
  {"ChatDisconnectAll", L_ChatDisconnectAll},
  {"ChatEverybody", L_ChatEverybody},
  {"ChatGetID", L_ChatGetID},
  {"ChatGroup", L_ChatGroup},
  {"ChatID", L_ChatID},
  {"ChatMessage", L_ChatMessage},
  {"ChatNameChange", L_ChatNameChange},
  {"ChatNote", L_ChatNote},
  {"ChatPasteEverybody", L_ChatPasteEverybody},
  {"ChatPasteText", L_ChatPasteText},
  {"ChatPeekConnections", L_ChatPeekConnections},
  {"ChatPersonal", L_ChatPersonal},
  {"ChatPing", L_ChatPing},
  {"ChatRequestConnections", L_ChatRequestConnections},
  {"ChatSendFile", L_ChatSendFile},
  {"ChatStopAcceptingCalls", L_ChatStopAcceptingCalls},
  {"ChatStopFileTransfer", L_ChatStopFileTransfer},
  {"CloseLog", L_CloseLog},
  {"CloseNotepad", L_CloseNotepad},
  {"ColourNameToRGB", L_ColourNameToRGB},
  {"ColourNote", L_ColourNote},
  {"ColourTell", L_ColourTell},
  {"Connect", L_Connect},
  {"CreateGUID", L_CreateGUID},
  {"SetCustomColourBackground", L_SetCustomColourBackground},
  {"GetCustomColourBackground", L_GetCustomColourBackground},
  {"SetCustomColourText", L_SetCustomColourText},
  {"GetCustomColourText", L_GetCustomColourText},
  {"Debug", L_Debug},
  {"DeleteAlias", L_DeleteAlias},
  {"DeleteAliasGroup", L_DeleteAliasGroup},
  {"DeleteAllMapItems", L_DeleteAllMapItems},
  {"DeleteCommandHistory", L_DeleteCommandHistory},
  {"DeleteGroup", L_DeleteGroup},
  {"DeleteLastMapItem", L_DeleteLastMapItem},
  {"DeleteLines", L_DeleteLines},
  {"DeleteOutput", L_DeleteOutput},
  {"DeleteTemporaryAliases", L_DeleteTemporaryAliases},
  {"DeleteTemporaryTimers", L_DeleteTemporaryTimers},
  {"DeleteTemporaryTriggers", L_DeleteTemporaryTriggers},
  {"DeleteTimer", L_DeleteTimer},
  {"DeleteTimerGroup", L_DeleteTimerGroup},
  {"DeleteTrigger", L_DeleteTrigger},
  {"DeleteTriggerGroup", L_DeleteTriggerGroup},
  {"DeleteVariable", L_DeleteVariable},
  {"DiscardQueue", L_DiscardQueue},
  {"Disconnect", L_Disconnect},
  {"DoAfter", L_DoAfter},
  {"DoAfterNote", L_DoAfterNote},
  {"DoAfterSpecial", L_DoAfterSpecial},
  {"DoAfterSpeedWalk", L_DoAfterSpeedWalk},
  {"DoCommand", L_DoCommand},
  {"GetEchoInput", L_GetEchoInput},
  {"SetEchoInput", L_SetEchoInput},
  {"EditDistance", L_EditDistance},
  {"EnableAlias", L_EnableAlias},
  {"EnableAliasGroup", L_EnableAliasGroup},
  {"EnableGroup", L_EnableGroup},
  {"EnableMapping", L_EnableMapping},
  {"EnablePlugin", L_EnablePlugin},
  {"EnableTimer", L_EnableTimer},
  {"EnableTimerGroup", L_EnableTimerGroup},
  {"EnableTrigger", L_EnableTrigger},
  {"EnableTriggerGroup", L_EnableTriggerGroup},
  {"ErrorDesc", L_ErrorDesc},
  {"EvaluateSpeedwalk", L_EvaluateSpeedwalk},
  {"Execute", L_Execute},
  {"ExportXML", L_ExportXML},
  {"FixupEscapeSequences", L_FixupEscapeSequences},
  {"FixupHTML", L_FixupHTML},
  {"FlushLog", L_FlushLog},
  {"GenerateName", L_GenerateName},
  {"GetAlias", L_GetAlias},
  {"GetAliasInfo", L_GetAliasInfo},
  {"GetAliasList", L_GetAliasList},
  {"GetAliasOption", L_GetAliasOption},
  {"GetAliasWildcard", L_GetAliasWildcard},
  {"GetAlphaOption", L_GetAlphaOption},
  {"GetAlphaOptionList", L_GetAlphaOptionList},
  {"GetChatInfo", L_GetChatInfo},
  {"GetChatList", L_GetChatList},
  {"GetChatOption", L_GetChatOption},
  {"GetClipboard", L_GetClipboard},
  {"GetCommand", L_GetCommand},
  {"GetCommandList", L_GetCommandList},
  {"GetConnectDuration", L_GetConnectDuration},
  {"GetCurrentValue", L_GetCurrentValue},
  {"GetDefaultValue", L_GetDefaultValue},
  {"GetEntity", L_GetEntity},
  {"GetXMLEntity", L_GetXMLEntity},
  {"GetFrame", L_GetFrame},
  {"GetHostAddress", L_GetHostAddress},
  {"GetHostName", L_GetHostName},
  {"GetInfo", L_GetInfo},
  {"GetInternalCommandsList", L_GetInternalCommandsList},
  {"GetLineCount", L_GetLineCount},
  {"GetLineInfo", L_GetLineInfo},
  {"GetLinesInBufferCount", L_GetLinesInBufferCount},
  {"GetLoadedValue", L_GetLoadedValue},
  {"GetMainWindowPosition", L_GetMainWindowPosition},
  {"GetWorldWindowPosition", L_GetWorldWindowPosition},
  {"GetNotepadWindowPosition", L_GetNotepadWindowPosition},
  {"GetMapColour", L_GetMapColour},
  {"GetMappingCount", L_GetMappingCount},
  {"GetMappingItem", L_GetMappingItem},
  {"GetMappingString", L_GetMappingString},
  {"GetNotepadLength", L_GetNotepadLength},
  {"GetNotepadText", L_GetNotepadText},
  {"GetNotes", L_GetNotes},
  {"GetNoteStyle", L_GetNoteStyle},
  {"GetOption", L_GetOption},
  {"GetOptionList", L_GetOptionList},
  {"GetPluginAliasInfo", L_GetPluginAliasInfo},
  {"GetPluginAliasList", L_GetPluginAliasList},
  {"GetPluginID", L_GetPluginID},
  {"GetPluginInfo", L_GetPluginInfo},
  {"GetPluginList", L_GetPluginList},
  {"GetPluginName", L_GetPluginName},
  {"GetPluginTimerInfo", L_GetPluginTimerInfo},
  {"GetPluginTimerList", L_GetPluginTimerList},
  {"GetPluginTriggerInfo", L_GetPluginTriggerInfo},
  {"GetPluginTriggerList", L_GetPluginTriggerList},
  {"GetPluginVariable", L_GetPluginVariable},
  {"GetPluginVariableList", L_GetPluginVariableList},
  {"GetQueue", L_GetQueue},
  {"GetReceivedBytes", L_GetReceivedBytes},
  {"GetRecentLines", L_GetRecentLines},
  {"GetScriptTime", L_GetScriptTime},
  {"GetSelectionEndColumn", L_GetSelectionEndColumn},
  {"GetSelectionEndLine", L_GetSelectionEndLine},
  {"GetSelectionStartColumn", L_GetSelectionStartColumn},
  {"GetSelectionStartLine", L_GetSelectionStartLine},
  {"GetSentBytes", L_GetSentBytes},
  {"GetStyleInfo", L_GetStyleInfo},
  {"GetSysColor", L_GetSysColor},
  {"GetSystemMetrics", L_GetSystemMetrics},
  {"GetTimer", L_GetTimer},
  {"GetTimerInfo", L_GetTimerInfo},
  {"GetTimerList", L_GetTimerList},
  {"GetTimerOption", L_GetTimerOption},
  {"GetTrigger", L_GetTrigger},
  {"GetTriggerInfo", L_GetTriggerInfo},
  {"GetTriggerList", L_GetTriggerList},
  {"GetTriggerOption", L_GetTriggerOption},
  {"GetTriggerWildcard", L_GetTriggerWildcard},
  {"GetUdpPort", L_GetUdpPort},
  {"GetUniqueID", L_GetUniqueID},
  {"GetUniqueNumber", L_GetUniqueNumber},
  {"GetVariable", L_GetVariable},
  {"GetVariableList", L_GetVariableList},
  {"GetWorld", L_GetWorld},
  {"GetWorldById", L_GetWorldById},
  {"GetWorldID", L_GetWorldID},
  {"GetWorldIdList", L_GetWorldIdList},
  {"GetWorldList", L_GetWorldList},
  {"Hash", L_Hash},
  {"Help", L_Help},
  {"Hyperlink", L_Hyperlink},
  {"ImportXML", L_ImportXML},
  {"Info", L_Info},
  {"InfoBackground", L_InfoBackground},
  {"InfoClear", L_InfoClear},
  {"InfoColour", L_InfoColour},
  {"InfoFont", L_InfoFont},
  {"IsAlias", L_IsAlias},
  {"IsConnected", L_IsConnected},
  {"IsLogOpen", L_IsLogOpen},
  {"IsPluginInstalled", L_IsPluginInstalled},
  {"IsTimer", L_IsTimer},
  {"IsTrigger", L_IsTrigger},
  {"LoadPlugin", L_LoadPlugin},
  {"GetLogInput", L_GetLogInput},
  {"SetLogInput", L_SetLogInput},
  {"GetLogNotes", L_GetLogNotes},
  {"SetLogNotes", L_SetLogNotes},
  {"GetLogOutput", L_GetLogOutput},
  {"SetLogOutput", L_SetLogOutput},
  {"LogSend", L_LogSend},
  {"MakeRegularExpression", L_MakeRegularExpression},
  {"MapColour", L_MapColour},
  {"MapColourList", L_MapColourList},
  {"Metaphone", L_Metaphone},
  {"GetMapping", L_GetMapping},
  {"SetMapping", L_SetMapping},
  {"GetNormalColour", L_GetNormalColour},
  {"SetNormalColour", L_SetNormalColour},
  {"MoveMainWindow", L_MoveMainWindow},
  {"MoveWorldWindow", L_MoveWorldWindow},
  {"MoveNotepadWindow", L_MoveNotepadWindow},
  {"MtSrand", L_MtSrand},
  {"MtRand", L_MtRand},
  {"Note", L_Note},
  {"NoteHr", L_NoteHr},
  {"GetNoteColour", L_GetNoteColour},
  {"SetNoteColour", L_SetNoteColour},
  {"GetNoteColourBack", L_GetNoteColourBack},
  {"SetNoteColourBack", L_SetNoteColourBack},
  {"GetNoteColourFore", L_GetNoteColourFore},
  {"SetNoteColourFore", L_SetNoteColourFore},
  {"NoteColourName", L_NoteColourName},
  {"NoteColourRGB", L_NoteColourRGB},
  {"NotepadColour", L_NotepadColour},
  {"NotepadFont", L_NotepadFont},
  {"NotepadSaveMethod", L_NotepadSaveMethod},
  {"NoteStyle", L_NoteStyle},
  {"Open", L_Open},
  {"OpenBrowser", L_OpenBrowser},
  {"OpenLog", L_OpenLog},
  {"PasteCommand", L_PasteCommand},
  {"Pause", L_Pause},
  {"PickColour", L_PickColour},
  {"PluginSupports", L_PluginSupports},
  {"PushCommand", L_PushCommand},
  {"Queue", L_Queue},
  {"ReadNamesFile", L_ReadNamesFile},
  {"Redraw", L_Redraw},
  {"ReloadPlugin", L_ReloadPlugin},
  {"RemoveBacktracks", L_RemoveBacktracks},
  {"GetRemoveMapReverses", L_GetRemoveMapReverses},
  {"SetRemoveMapReverses", L_SetRemoveMapReverses},
  {"Replace", L_Replace},
  {"ReplaceNotepad", L_ReplaceNotepad},
  {"Reset", L_Reset},
  {"ResetIP",  L_ResetIP},
  {"ResetStatusTime", L_ResetStatusTime},
  {"ResetTimer", L_ResetTimer},
  {"ResetTimers", L_ResetTimers},
  {"ReverseSpeedwalk", L_ReverseSpeedwalk},
  {"RGBColourToName", L_RGBColourToName},
  {"Save", L_Save},
  {"SaveNotepad", L_SaveNotepad},
  {"SaveState", L_SaveState},
  {"SelectCommand", L_SelectCommand},
  {"Send", L_Send},
  {"SendImmediate", L_SendImmediate},
  {"SendNoEcho", L_SendNoEcho},
  {"SendPkt", L_SendPkt},
  {"SendPush", L_SendPush},
  {"SendToNotepad", L_SendToNotepad},
  {"SetAliasOption", L_SetAliasOption},
  {"SetAlphaOption", L_SetAlphaOption},
  {"SetChatOption", L_SetChatOption},
  {"SetChanged", L_SetChanged},
  {"SetClipboard", L_SetClipboard},
  {"SetCommand", L_SetCommand},
  {"SetEntity", L_SetEntity},
  {"SetInputFont", L_SetInputFont},
  {"SetNotes", L_SetNotes},
  {"SetOption", L_SetOption},
  {"SetOutputFont", L_SetOutputFont},
  {"SetStatus", L_SetStatus},
  {"SetTimerOption", L_SetTimerOption},
  {"SetTriggerOption", L_SetTriggerOption},
  {"SetVariable", L_SetVariable}, 
  {"SetWorldWindowStatus", L_SetWorldWindowStatus},
  {"ShowInfoBar", L_ShowInfoBar},
  {"Simulate", L_Simulate},
  {"Sound", L_Sound},
  {"GetSpeedWalkDelay", L_GetSpeedWalkDelay},
  {"SetSpeedWalkDelay", L_SetSpeedWalkDelay},
  {"SpellCheck", L_SpellCheck},
  {"SpellCheckCommand", L_SpellCheckCommand},
  {"SpellCheckDlg", L_SpellCheckDlg},
  {"StripANSI", L_StripANSI},
  {"Tell", L_Tell},
  {"GetTrace", L_GetTrace},
  {"SetTrace", L_SetTrace},
  {"TraceOut", L_TraceOut},
  {"TranslateGerman", L_TranslateGerman},
  {"Transparency", L_Transparency},
  {"Trim", L_Trim},
  {"UdpListen", L_UdpListen},
  {"UdpPortList", L_UdpPortList},
  {"UdpSend", L_UdpSend},
  {"Version", L_Version},
  {"WorldAddress", L_WorldAddress},
  {"WorldName", L_WorldName},
  {"WorldPort", L_WorldPort},
  {"WriteLog", L_WriteLog},
    
  {NULL, NULL}
  };


static int l_print (lua_State *L) 
  {
  CMUSHclientDoc * pDoc = doc (L);  // have to do it first
  pDoc->Note (concatArgs (L, " ").c_str ());
  return 0;
} // end of l_print


int world2string (lua_State *L) 
  {
//  CMUSHclientDoc *pDoc = doc(L);
//  lua_pushfstring(L, "world(%s)", pDoc->m_mush_name);

  lua_pushliteral (L, "world");
  return 1;
  }
  
static const struct luaL_reg worldlib_meta [] = 
  {
    {"__tostring", world2string},
    {NULL, NULL}
  };

static int MakeFlagsTable (lua_State *L, 
                           const char *name,
                           const flags_pair *arr)
{
  const flags_pair *p;
  lua_newtable(L);
  for(p=arr; p->key != NULL; p++) {
    lua_pushstring(L, p->key);
    lua_pushnumber(L, p->val);
    lua_rawset(L, -3);
  }
  lua_setglobal (L, name);
  return 1;
}

static int MakeIntFlagsTable (lua_State *L, 
                             const char *name,
                             const int_flags_pair *arr)
{
  const int_flags_pair *p;
  lua_newtable(L);
  for(p=arr; p->val != NULL; p++) {
    lua_pushnumber(L, p->key);
    lua_pushstring(L, p->val);
    lua_rawset(L, -3);
  }
  lua_setglobal (L, name);
  return 1;
}

static flags_pair trigger_flags[] =
{

  { "Enabled", 1 },  // enable trigger 
  { "OmitFromLog", 2 },  // omit from log file 
  { "OmitFromOutput", 4 },  // omit trigger from output 
  { "KeepEvaluating", 8 },  // keep evaluating 
  { "IgnoreCase", 16 },  // ignore case when matching 
  { "RegularExpression", 32 },  // trigger uses regular expression 
  { "ExpandVariables", 512 },  // expand variables like @direction 
  { "Replace", 1024 },  // replace existing trigger of same name 
  { "LowercaseWildcard", 2048 },   // wildcards forced to lower-case
  { "Temporary", 16384 },  // temporary - do not save to world file 

  { NULL, 0 }
};

static flags_pair custom_colours[] =
{

  { "NoChange", -1 }, 
  { "Custom1", 0 }, 
  { "Custom2", 1 }, 
  { "Custom3", 2 },  
  { "Custom4", 3 }, 
  { "Custom5", 4 }, 
  { "Custom6", 5 }, 
  { "Custom7", 6 }, 
  { "Custom8", 7 }, 
  { "Custom9", 8 }, 
  { "Custom10", 9 }, 
  { "Custom11", 10 }, 
  { "Custom12", 11 }, 
  { "Custom13", 12 }, 
  { "Custom14", 13 }, 
  { "Custom15", 14 }, 
  { "Custom16", 15 }, 
  { "CustomOther", 16 },   // triggers only

  { NULL, 0 }
};

static flags_pair alias_flags[] =
{

  { "Enabled", 1 },  // same as for AddTrigger 
  { "IgnoreAliasCase", 32 },  // ignore case when matching 
  { "OmitFromLogFile", 64 },  // omit this alias from the log file 
  { "RegularExpression", 128 },  // alias is regular expressions 
  { "ExpandVariables", 512 },   // same as for AddTrigger 
  { "Replace", 1024 },   // same as for AddTrigger 
  { "AliasSpeedWalk", 2048 },  // interpret send string as a speed walk string 
  { "AliasQueue", 4096 },  // queue this alias for sending at the speedwalking delay interval 
  { "AliasMenu", 8192 },  // this alias appears on the alias menu 
  { "Temporary", 16384 },   // same as for AddTrigger 

  { NULL, 0 }
};

static flags_pair timer_flags[] =
{

  { "Enabled", 1 },  // same as for AddTrigger 
  { "AtTime", 2 },  // if not set, time is "every" 
  { "OneShot", 4 },  // if set, timer only fires once 
  { "TimerSpeedWalk", 8 },  // timer does a speed walk when it fires 
  { "TimerNote", 16 },  // timer does a world.note when it fires 
  { "ActiveWhenClosed", 32 },   // timer fires even when world is disconnected
  { "Replace", 1024 },  // same as for AddTrigger
  { "Temporary", 16384 },  // same as for AddTrigger

  { NULL, 0 }
};

static flags_pair error_codes[] =
{

  { "eOK", 0 },  // No error
  { "eWorldOpen", 30001 },  // The world is already open
  { "eWorldClosed", 30002 },  // The world is closed, this action cannot be performed
  { "eNoNameSpecified", 30003 },  // No name has been specified where one is required
  { "eCannotPlaySound", 30004 },  // The sound file could not be played
  { "eTriggerNotFound", 30005 },  // The specified trigger name does not exist
  { "eTriggerAlreadyExists", 30006 },  // Attempt to add a trigger that already exists
  { "eTriggerCannotBeEmpty", 30007 },  // The trigger "match" string cannot be empty
  { "eInvalidObjectLabel", 30008 },  // The name of this object is invalid
  { "eScriptNameNotLocated", 30009 },  // Script name is not in the script file
  { "eAliasNotFound", 30010 },  // The specified alias name does not exist
  { "eAliasAlreadyExists", 30011 },  // Attempt to add a alias that already exists
  { "eAliasCannotBeEmpty", 30012 },  // The alias "match" string cannot be empty
  { "eCouldNotOpenFile", 30013 },  // Unable to open requested file
  { "eLogFileNotOpen", 30014 },  // Log file was not open
  { "eLogFileAlreadyOpen", 30015 },  // Log file was already open
  { "eLogFileBadWrite", 30016 },  // Bad write to log file
  { "eTimerNotFound", 30017 },  // The specified timer name does not exist
  { "eTimerAlreadyExists", 30018 },  // Attempt to add a timer that already exists
  { "eVariableNotFound", 30019 },  // Attempt to delete a variable that does not exist
  { "eCommandNotEmpty", 30020 },  // Attempt to use SetCommand with a non-empty command window
  { "eBadRegularExpression", 30021 },  // Bad regular expression syntax
  { "eTimeInvalid", 30022 },  // Time given to AddTimer is invalid
  { "eBadMapItem", 30023 },  // Direction given to AddToMapper is invalid
  { "eNoMapItems", 30024 },  // No items in mapper
  { "eUnknownOption", 30025 },  // Option name not found
  { "eOptionOutOfRange", 30026 },  // New value for option is out of range
  { "eTriggerSequenceOutOfRange", 30027 },  // Trigger sequence value invalid
  { "eTriggerSendToInvalid", 30028 },  // Where to send trigger text to is invalid
  { "eTriggerLabelNotSpecified", 30029 },  // Trigger label not specified/invalid for 'send to variable'
  { "ePluginFileNotFound", 30030 },  // File name specified for plugin not found
  { "eProblemsLoadingPlugin", 30031 },  // There was a parsing or other problem loading the plugin
  { "ePluginCannotSetOption", 30032 },  // Plugin is not allowed to set this option
  { "ePluginCannotGetOption", 30033 },  // Plugin is not allowed to get this option
  { "eNoSuchPlugin", 30034 },  // Requested plugin is not installed
  { "eNotAPlugin", 30035 },  // Only a plugin can do this
  { "eNoSuchRoutine", 30036 },  // Plugin does not support that subroutine (subroutine not in script)
  { "ePluginDoesNotSaveState", 30037 },  // Plugin does not support saving state
  { "ePluginCouldNotSaveState", 30037 },  // Plugin could not save state (eg. no state directory)
  { "ePluginDisabled", 30039 },  // Plugin is currently disabled
  { "eErrorCallingPluginRoutine", 30040 },  // Could not call plugin routine
  { "eCommandsNestedTooDeeply", 30041 },  // Calls to "Execute" nested too deeply
  { "eCannotCreateChatSocket", 30042 },  // Unable to create socket for chat connection
  { "eCannotLookupDomainName", 30043 },  // Unable to do DNS (domain name) lookup for chat connection
  { "eNoChatConnections", 30044 },  // No chat connections open
  { "eChatPersonNotFound", 30045 },  // Requested chat person not connected
  { "eBadParameter", 30046 },  // General problem with a parameter to a script call
  { "eChatAlreadyListening", 30047 },  // Already listening for incoming chats
  { "eChatIDNotFound", 30048 },  // Chat session with that ID not found
  { "eChatAlreadyConnected", 30049 },  // Already connected to that server/port
  { "eClipboardEmpty", 30050 },  // Cannot get (text from the) clipboard
  { "eFileNotFound", 30051 },  // Cannot open the specified file
  { "eAlreadyTransferringFile", 30052 },  // Already transferring a file
  { "eNotTransferringFile", 30053 },  // Not transferring a file
  { "eNoSuchCommand", 30054 },  // There is not a command of that name
  { "eArrayAlreadyExists", 30055 },  // Chat session with that ID not found
  { "eArrayDoesNotExist", 30056 },  // Already connected to that server/port
  { "eArrayNotEvenNumberOfValues", 30057 },  // Cannot get (text from the) clipboard
  { "eImportedWithDuplicates", 30058 },  // Cannot open the specified file
  { "eBadDelimiter", 30059 },  // Already transferring a file
  { "eSetReplacingExistingValue", 30060 },  // Not transferring a file
  { "eKeyDoesNotExist", 30061 },  // There is not a command of that name
  { "eCannotImport", 30062 },  // There is not a command of that name
  { "eItemInUse",  30063 },    // Cannot delete trigger/alias/timer because it is executing a script 
  { "eSpellCheckNotActive", 30064 },  // spell checker is not active 

  { NULL, 0 }
};

int_flags_pair error_descriptions[] =
{

  {  0, "No error" },
  {  30001, "The world is already open" },
  {  30002, "The world is closed, this action cannot be performed" },
  {  30003, "No name has been specified where one is required" },
  {  30004, "The sound file could not be played" },
  {  30005, "The specified trigger name does not exist" },
  {  30006, "Attempt to add a trigger that already exists" },
  {  30007, "The trigger \"match\" string cannot be empty" },
  {  30008, "The name of this object is invalid" },
  {  30009, "Script name is not in the script file" },
  {  30010, "The specified alias name does not exist" },
  {  30011, "Attempt to add a alias that already exists" },
  {  30012, "The alias \"match\" string cannot be empty" },
  {  30013, "Unable to open requested file" },
  {  30014, "Log file was not open" },
  {  30015, "Log file was already open" },
  {  30016, "Bad write to log file" },
  {  30017, "The specified timer name does not exist" },
  {  30018, "Attempt to add a timer that already exists" },
  {  30019, "Attempt to delete a variable that does not exist" },
  {  30020, "Attempt to use SetCommand with a non-empty command window" },
  {  30021, "Bad regular expression syntax" },
  {  30022, "Time given to AddTimer is invalid" },
  {  30023, "Direction given to AddToMapper is invalid" },
  {  30024, "No items in mapper" },
  {  30025, "Option name not found" },
  {  30026, "New value for option is out of range" },
  {  30027, "Trigger sequence value invalid" },
  {  30028, "Where to send trigger text to is invalid" },
  {  30029, "Trigger label not specified/invalid for 'send to variable'" },
  {  30030, "File name specified for plugin not found" },
  {  30031, "There was a parsing or other problem loading the plugin" },
  {  30032, "Plugin is not allowed to set this option" },
  {  30033, "Plugin is not allowed to get this option" },
  {  30034, "Requested plugin is not installed" },
  {  30035, "Only a plugin can do this" },
  {  30036, "Plugin does not support that subroutine (subroutine not in script)" },
  {  30037, "Plugin does not support saving state" },
  {  30037, "Plugin could not save state (eg. no state directory)" },
  {  30039, "Plugin is currently disabled" },
  {  30040, "Could not call plugin routine" },
  {  30041, "Calls to \"Execute\" nested too deeply" },
  {  30042, "Unable to create socket for chat connection" },
  {  30043, "Unable to do DNS (domain name) lookup for chat connection" },
  {  30044, "No chat connections open" },
  {  30045, "Requested chat person not connected" },
  {  30046, "General problem with a parameter to a script call" },
  {  30047, "Already listening for incoming chats" },
  {  30048, "Chat session with that ID not found" },
  {  30049, "Already connected to that server/port" },
  {  30050, "Cannot get (text from the) clipboard" },
  {  30051, "Cannot open the specified file" },
  {  30052, "Already transferring a file" },
  {  30053, "Not transferring a file" },
  {  30054, "There is not a command of that name" },
  {  30055, "That array already exists" },
  {  30056, "That array does not exist" },
  {  30057, "Values to be imported into array are not in pairs" },
  {  30058, "Import succeeded, however some values were overwritten" },
  {  30059, "Import/export delimiter must be a single character, other than backslash" },
  {  30060, "Array element set, existing value overwritten" },
  {  30061, "Array key does not exist" },
  {  30062, "Cannot import because cannot find unused temporary character" },
  {  30063, "Cannot delete trigger/alias/timer because it is executing a script" },
  {  30064, "Spell checker is not active" },

  { NULL, 0 }
};


extern const struct luaL_reg *ptr_xmllib;

/*
static int l_errorhandler (lua_State *L) 
  {

  ::AfxMessageBox ("errorhandler");

  return 0;
} // end of l_errorhandler

*/


// int win_io_popen (lua_State *L);
// int win_io_pclose (lua_State *L);

int RegisterLuaRoutines (lua_State *L)
  {

  lua_newtable (L);  // environment
  lua_replace (L, LUA_ENVIRONINDEX);

  lua_settable(L, LUA_ENVIRONINDEX);

  // we want the global table so we can put a metatable on it
//  lua_getglobal (L, "_G");

  lua_pushvalue (L, LUA_GLOBALSINDEX);

  // load the "world" library
  luaL_register (L, WORLD_LIBRARY, worldlib);

  // add the __index metamethod to the world library
  lua_pushliteral(L, "__index");
  lua_pushvalue(L, -2);         // push metatable 
  lua_rawset(L, -3);            // metatable.__index = metatable 

  // we do this so you can just say "Note 'hello'" rather than
  // world.Note 'hello'

  // set the world library as the metatable for the global library
  lua_setmetatable (L, -2);


  // print function for debugging
  lua_pushcfunction(L, l_print);
  lua_setglobal(L, "print");

        
  /*

  // don't know why I had this ... debugging maybe?

  // error handler
  lua_pushcfunction(L, l_errorhandler);
  lua_setglobal(L, "errorhandler");

  */

  // see manual, 28.2, to see why we do this

  // we make a metatable for the world in case they do a world.GetWorld ("name")

  luaL_newmetatable(L, mushclient_typename);
  luaL_register (L, NULL, worldlib_meta);

  lua_pushliteral(L, "__index");
  lua_getglobal (L, WORLD_LIBRARY);
  lua_rawset(L, -3);            // metatable.__index = world 

  lua_settop(L, 0);             // pop everything

  // various constants for scripting (eg. AddTrigger, AddAlias)
  MakeFlagsTable (L, "trigger_flag", trigger_flags);
  MakeFlagsTable (L, "alias_flag", alias_flags);
  MakeFlagsTable (L, "timer_flag", timer_flags);
  // custom colour names
  MakeFlagsTable (L, "custom_colour", custom_colours);
  // return codes - map name to number
  MakeFlagsTable (L, "error_code", error_codes);
  // return codes - map number to description
  MakeIntFlagsTable (L, "error_desc", error_descriptions);

  // colour names

  lua_newtable(L);

  for (POSITION pos = App.m_ColoursMap.GetStartPosition(); pos; )
    {
    CColours * pColour;
    CString strColourName;
    App.m_ColoursMap.GetNextAssoc (pos, strColourName, pColour);
    lua_pushstring(L, strColourName);
    lua_pushnumber(L, pColour->iColour);
    lua_rawset(L, -3);
    }

  lua_setglobal (L, "colour_names");

  // extended colour values

  lua_newtable(L);

  int i;
  for (i = 0; i < 256; i++)
    {
    lua_pushnumber(L, xterm_256_colours [i]);
    lua_rawseti (L, -2, i);
    }

  lua_setglobal (L, "extended_colours");

  // add xml reader to utils lib
  luaL_register (L, "utils", ptr_xmllib);

  return 0;
  }


CString GetFromStack (lua_State *L, const char * what)
  {
  CString s;

  lua_pushstring (L, what);  
  lua_rawget    (L, -2);               // get it

  lua_getglobal(L, "tostring");
  lua_pushvalue (L, -2);    // make copy of result
  lua_call (L, 1, 1);       // convert to string

  s = lua_tostring (L, -1);
  lua_pop (L, 2);   // pop result and tostring function

  return s;
  } // end of GetFromStack


int our_lua_debug_function (lua_State *L)
  {

  CDebugLuaDlg dlg;

  dlg.L = L;    // Lua state for doing commands

  lua_pushstring(L, LUA_DBLIBNAME);  /* "debug" */
  lua_rawget    (L, LUA_GLOBALSINDEX);    // get debug library   

  if (!lua_istable (L, -1))
     luaL_error(L, "Cannot debug, no debug table");	

  // get a heap of info
  lua_pushstring(L, "getinfo");  
  lua_rawget    (L, -2);               // get getinfo function
  
  if (lua_isfunction (L, -1))
    {
    lua_pushnumber (L, 2);    // caller
    lua_pushstring (L, "nfSlu");  // everything except table of lines
    lua_call (L, 2, 1);   // 2 args, expect table as result

    // on stack now should be table of results

    if (lua_istable (L, -1))
      {
      // source of function
      dlg.m_strSource = GetFromStack (L, "short_src");

      // first line defined
      CString strFirstLine = GetFromStack (L, "linedefined");

      // last line defined
      CString strLastLine = GetFromStack (L, "lastlinedefined");
      dlg.m_strLines.Format ("%s, %s", (LPCTSTR) strFirstLine, (LPCTSTR) strLastLine);

      // current line executing
      dlg.m_strCurrentLine = GetFromStack (L, "currentline");

      // what function is: Lua, C, main
      dlg.m_strWhat = GetFromStack (L, "what");

      // what the "name" field is (might be empty)
      CString strNameWhat = GetFromStack (L, "namewhat");

      // if empty, there is no name field, otherwise get it
      if (!strNameWhat.IsEmpty ())
        {
        // name of function
        dlg.m_strFunctionName = GetFromStack (L, "name");
        dlg.m_strFunctionName += " (";
        dlg.m_strFunctionName += strNameWhat;
        dlg.m_strFunctionName += ")";
        }

      // number of upvalues
      dlg.m_strNups = GetFromStack (L, "nups");

      // function address
      dlg.m_strFunction = GetFromStack (L, "func");
      
      } // end of table returned

    } // we have getinfo function

  lua_settop (L, 0);  // discard any results now


  // preload with their last command

  dlg.m_strCommand = App.m_strLastDebugCommand;

  dlg.DoModal ();

  // put last command back, unless they blanked it out

  if (!dlg.m_strCommand.IsEmpty ())
    App.m_strLastDebugCommand = dlg.m_strCommand;

  if (dlg.m_bAbort)
      luaL_error(L, "Script aborted");	

  return 0;
  } // end of our_lua_debug_function

int our_exit_function (lua_State *L)
  {
  return luaL_error(L, LUA_QL("os.exit") " not implemented in MUSHclient");	
  }  // end of our_exit_function

int our_popen_function (lua_State *L)
  {
  return luaL_error(L, LUA_QL("io.popen") " not implemented in MUSHclient");	
  } // end of our_popen_function

int DisableDLLs (lua_State * L)
  {
  if (!App.m_bEnablePackageLibrary)
    {
    // grab package library
    lua_pushliteral (L, LUA_LOADLIBNAME);     // "package"    
    lua_rawget      (L, LUA_GLOBALSINDEX);    // get package library   

    // remove package.loadlib
    lua_pushliteral (L, "loadlib");           // package.loadlib
    lua_pushnil     (L);
    lua_rawset      (L, -3);                  //  package.loadlib = nil   

    // grab package.loaders table
    lua_pushliteral (L, "loaders");           // package.loaders
    lua_rawget      (L, -2);                  // get package.loaders table
    if (!lua_istable(L, -1))
      luaL_error(L, LUA_QL("package.loaders") " must be a table");

    // remove index 4 - all-in-one loader
    lua_pushnil     (L);
    lua_rawseti     (L, -2, 4);                  //  package.loaders [4] = nil   
  
    // remove index 3 - DLL loader
    lua_pushnil     (L);
    lua_rawseti     (L, -2, 3);                  //  package.loaders [3] = nil   

    lua_settop(L, 0);   // clear stack

    }

  // change debug.debug to ours

  lua_pushstring(L, LUA_DBLIBNAME);  /* "debug" */
  lua_rawget    (L, LUA_GLOBALSINDEX);    // get debug library   

  if (lua_istable(L, -1))
    {
    lua_pushstring(L, "debug");  /* debug.debug */
    lua_pushcfunction(L, our_lua_debug_function);
    lua_rawset    (L, -3);    // set debug.debug to our function   

    lua_pop(L, 1);  // pop debug table
    }  // debug library was there

  // get rid of os.exit

  lua_pushstring(L, LUA_OSLIBNAME);  /* "os" */
  lua_rawget    (L, LUA_GLOBALSINDEX);    // get os library   

  if (lua_istable(L, -1))
    {
    lua_pushstring(L, "exit");  /* os.exit */
    lua_pushcfunction(L, our_exit_function);
    lua_rawset    (L, -3);    // set os.exit to our function   
    
    lua_pop(L, 1);  // pop os table

    }  // os library was there

  // get rid of io.popen 

  lua_pushstring(L, LUA_IOLIBNAME);  /* "io" */
  lua_rawget    (L, LUA_GLOBALSINDEX);    // get io library   

  if (lua_istable(L, -1))
    {
    lua_pushstring(L, "popen");  /* io.popen */
    lua_pushcfunction(L, our_popen_function);
    lua_rawset    (L, -3);    // set io.popen to our function     

    lua_pop(L, 1);  // pop io table
    }  // io library was there

  lua_settop(L, 0);   // clear stack
  return 0;
  } // end of DisableDLLs

#endif  // LUA
  