private void OnChatFromClient(object sender, OSChatMessage msg)
        {
            if (msg.Sender == null)
            {
                return;
            }

            //m_log.DebugFormat("chan {0} msg {1}", msg.Channel, msg.Message);

            IClientAPI client = msg.Sender;

            if (!m_floaters.ContainsKey(client.AgentId))
            {
                return;
            }

            string[] parts = msg.Message.Split(new char[] { ':' });
            if (parts.Length == 0)
            {
                return;
            }

            ScenePresence sp = m_scene.GetScenePresence(client.AgentId);

            if (sp == null || sp.IsChildAgent)
            {
                return;
            }

            Dictionary <int, FloaterData> d = m_floaters[client.AgentId];

            // Work around a viewer bug - VALUE from any
            // dialog can appear on this channel and needs to
            // be dispatched to ALL open dialogs for the user
            if (msg.Channel == 427169570)
            {
                if (parts[0] == "VALUE")
                {
                    foreach (FloaterData dd in d.Values)
                    {
                        if (dd.Handler(client, dd, parts))
                        {
                            m_floaters[client.AgentId].Remove(dd.Channel);
                            SendToClient(sp, String.Format("># floater {0} destroy", dd.FloaterName));
                            break;
                        }
                    }
                }
                return;
            }

            if (!d.ContainsKey(msg.Channel))
            {
                return;
            }

            FloaterData data = d[msg.Channel];

            if (parts[0] == "NOTIFY")
            {
                if (parts[1] == "cancel" || parts[1] == data.FloaterName)
                {
                    m_floaters[client.AgentId].Remove(data.Channel);
                    SendToClient(sp, String.Format("># floater {0} destroy", data.FloaterName));
                }
            }

            if (data.Handler != null && data.Handler(client, data, parts))
            {
                m_floaters[client.AgentId].Remove(data.Channel);
                SendToClient(sp, String.Format("># floater {0} destroy", data.FloaterName));
            }
        }
        public void FloaterControl(ScenePresence sp, FloaterData d, string msg)
        {
            string sendData = String.Format("># floater {0} {1}", d.FloaterName, msg);

            SendToClient(sp, sendData);
        }
        public void DoUserFloater(UUID agentID, FloaterData dialogData, string configuration)
        {
            ScenePresence sp = m_scene.GetScenePresence(agentID);

            if (sp == null || sp.IsChildAgent)
            {
                return;
            }

            if (!m_floaters.ContainsKey(agentID))
            {
                m_floaters[agentID] = new Dictionary <int, FloaterData>();
            }

            if (m_floaters[agentID].ContainsKey(dialogData.Channel))
            {
                return;
            }

            m_floaters[agentID].Add(dialogData.Channel, dialogData);

            string xml;

            if (dialogData.XmlText != null && dialogData.XmlText != String.Empty)
            {
                xml = dialogData.XmlText;
            }
            else
            {
                using (FileStream fs = File.Open(dialogData.XmlName + ".xml", FileMode.Open))
                {
                    using (StreamReader sr = new StreamReader(fs))
                        xml = sr.ReadToEnd().Replace("\n", "");
                }
            }

            List <string> xparts = new List <string>();

            while (xml.Length > 0)
            {
                string x = xml;
                if (x.Length > 600)
                {
                    x   = x.Substring(0, 600);
                    xml = xml.Substring(600);
                }
                else
                {
                    xml = String.Empty;
                }

                xparts.Add(x);
            }

            for (int i = 0; i < xparts.Count; i++)
            {
                SendToClient(sp, String.Format("># floater {2} create {0}/{1} " + xparts[i], i + 1, xparts.Count, dialogData.FloaterName));
            }

            SendToClient(sp, String.Format("># floater {0} {{notify:1}} {{channel: {1}}} {{node:cancel {{notify:1}}}} {{node:ok {{notify:1}}}} {2}", dialogData.FloaterName, (uint)dialogData.Channel, configuration));
        }