/*---------------------------------------------------------------------------------------------------------------------------------------------------
Program Listing for:  securesockDlg.cpp
Project:  securesock
Namespace:  c++
----------------------------------------------------------------------------------------------------------------------------------------------------
*/

// securesockDlg.cpp : implementation file
//
// since this is the main window, sort of, a lot of stuff is put in here instead of
// in the application class.

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#include <vector>
#include "securesock.h"
#include "securesockDlg.h"
#include "DlgProxy.h"
#include "IconChooser.h"
#include "PersonalInfoDlg.h"
#include "InternetInfoDlg.h"
#include "CompDlg.h"
#include "WelcomeDlg.h"
#include "GetChatID.h"
#include "PersP1.h"
#include "PersP3.h"
#include "Pers_P2.h"
#include "PersP4.h"
#include "MyPropSheet.h"
#include "TreeEdit.h"
#include "SendDlg.h"
#include "stream_stuff.h"
#include "MyColorDialog.h"
#include "SockUser.h"
#include "Slot.h"
#include "LookupContacts.h"
#include "MySocket.h"
#include "SearchResults.h"
#include "MiscStuff1.h"
#include "PropDlg.h"
#include "MoveContactDlg.h"
#include "AcceptContact.h"
#include "MyTTC.h"
#include "ReadDlg.h"

#include <vfw.h>
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "vfw32.lib")

#include <iostream>
#include <iomanip>
#include <fstream>
#include <ios>

// required to make STL functions visible, which I use throughout the app
using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

int CSecuresockDlg::CHAT_ID_LOOKUP = 1;
int CSecuresockDlg::TYPE_LOOKUP = 2;
int CSecuresockDlg::PENDING_MSG_LOOKUP = 3;
int CSecuresockDlg::ONLINE_STATUS_MSG_LOOKUP = 4;
int CSecuresockDlg::BLINK_UPDATE_CALL = 5;

//         int m_imy_status;
int CSecuresockDlg::ACTIVE = 5;
int CSecuresockDlg::BUSY = 6;
int CSecuresockDlg::SHORT_AFK = 7;
int CSecuresockDlg::LONG_AFK = 8;
int CSecuresockDlg::INVISIBLE = 9;

VOID CALLBACK BlinkProc(UINT ntimerid, UINT msg, DWORD dwuser, 
                                                               DWORD dwparam1, DWORD dwparam2);

volatile bool g_ssd_insocket = false;
volatile bool gb_lookat = false;
volatile HWND g_md_hwnd = (HWND)0;
volatile int g_i_mystatus = 0;

HWND GetMainDlgHWND();
void SetMainDlgHWND(HWND x);
int GetMyOnlineStatus();
void SetMyOnlineStatus(int status);

// certain globals are useful when dealing with threads
volatile bool g_attempting_server_contact = false; // used with threads so not in a class (for now)
volatile bool g_getting_online_status = false;

// this also is accessed by threads hence global
vector<TreeStatusHelper> online_chk_vector;

// some of these functions are obsolete, they were globals I was using for a time, perhaps remove later
CString gettreetext( const CTreeCtrl &piTree, HTREEITEM pitem );

// saveone is a nice function for use with saving a single tree items info, needs to be "classed"
void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent,
                           int contact_id, int iimage, int isel_image, bool is_expanded = false);

void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent,
                           ChatItemInfo *pchatinfo, int iimage, int isel_image, bool is_expanded = false);

// this may now be obsolete not sure, created some new functions in the class to cover this stuff
void gettreeiconindexes( const CTreeCtrl &piTree, HTREEITEM pitem, int &image, int &sel_image, bool &is_expanded );
// another possible obsolete function which may need to be put into the class
void settreeexpanded( CTreeCtrl &piTree, HTREEITEM pitem, bool is_expanded );

unsigned int send_msg(LPVOID pParam);
unsigned int send_ack_msg(LPVOID pParam);
unsigned int check_online_status(LPVOID pParam);

vector<TreeGroupInfo> tgiVector;
int g_n = 0;

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
         CAboutDlg();

// Dialog Data
         //{{AFX_DATA(CAboutDlg)
         enum { IDD = IDD_ABOUTBOX };
         //}}AFX_DATA

         // ClassWizard generated virtual function overrides
         //{{AFX_VIRTUAL(CAboutDlg)
         protected:
         virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
         //}}AFX_VIRTUAL

// Implementation
protected:
         //{{AFX_MSG(CAboutDlg)
         //}}AFX_MSG
         DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
         //{{AFX_DATA_INIT(CAboutDlg)
         //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
         CDialog::DoDataExchange(pDX);
         //{{AFX_DATA_MAP(CAboutDlg)
         //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
         //{{AFX_MSG_MAP(CAboutDlg)
                  // No message handlers
         //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSecuresockDlg dialog

IMPLEMENT_DYNAMIC(CSecuresockDlg, CDialog);

CSecuresockDlg::CSecuresockDlg(CWnd* pParent /*=NULL*/)
                  : CDialog(CSecuresockDlg::IDD, pParent)
{

         //{{AFX_DATA_INIT(CSecuresockDlg)
         //}}AFX_DATA_INIT
         // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
         m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON27);
         m_ptreefont = (CFont *)0;
         m_pAutoProxy = NULL;
         //CDialog::Create(CSecuresockDlg::IDD, pParent);

}

CSecuresockDlg::~CSecuresockDlg()
{
         // If there is an automation proxy for this dialog, set
         //  its back pointer to this dialog to NULL, so it knows
         //  the dialog has been deleted.
         if (m_pAutoProxy != NULL)
                  m_pAutoProxy->m_pDialog = NULL;
}

void CSecuresockDlg::DoDataExchange(CDataExchange* pDX)
{
         CDialog::DoDataExchange(pDX);
         //{{AFX_DATA_MAP(CSecuresockDlg)
         DDX_Control(pDX, IDC_TREE1, m_TreeCtrl);
         DDX_Control(pDX, IDC_MYPERSONALBUTTON, m_mypersonalbutton);
         //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CSecuresockDlg, CDialog)
         //{{AFX_MSG_MAP(CSecuresockDlg)
         ON_WM_SYSCOMMAND()
         ON_WM_DESTROY()
         ON_WM_PAINT()
         ON_WM_QUERYDRAGICON()
         ON_WM_CLOSE()
         ON_NOTIFY(NM_RCLICK, IDC_TREE1, OnRclickTree1)
         ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
         ON_WM_SIZE()
         ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE1, OnEndlabeleditTree1)
         ON_NOTIFY(TVN_KEYDOWN, IDC_TREE1, OnKeydownTree1)
         ON_NOTIFY(NM_RETURN, IDC_TREE1, OnReturnTree1)
         ON_WM_CHAR()
         ON_BN_CLICKED(IDC_MYPERSONALBUTTON, OnMypersonalbutton)
         ON_WM_SHOWWINDOW()
         ON_WM_HELPINFO()
         ON_COMMAND(WM_TRAY_ICON, OnTrayIcon)
    ON_MESSAGE(WM_TRAY_IDD, OnTrayNotification)   
         ON_WM_CANCELMODE()
         ON_WM_SYSCHAR()
         ON_UPDATE_COMMAND_UI(ID_CHANGE_ICON1, OnUpdateChangeIcon1)
         ON_UPDATE_COMMAND_UI(IDC_MYPERSONALBUTTON, OnMyButtonUI)
         ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnDblclkTree1)
         ON_WM_CTLCOLOR()
         ON_WM_TIMER()
         ON_WM_SETCURSOR()
         //}}AFX_MSG_MAP
         ON_MESSAGE(WM_NEW_MSG, OnNewMessage)
         ON_MESSAGE(WM_CONNECT_STATUS, OnConnectStatus)
         ON_MESSAGE(WM_SEND_OUTGOING, OnOutgoingMsg)
         ON_MESSAGE(WM_SHOW_ONLINE_STATUS, ShowOnlineStatus)
         ON_MESSAGE(WM_TIMER_BLINK_EVENT, MakePendingsBlink)
         ON_BN_CLICKED(IDC_CONNECTION, OnConnectionButton)
         ON_BN_CLICKED(IDC_ADDGROUP, OnAddGroupButton)
         ON_BN_CLICKED(IDC_ADDCONTACT, OnAddContactButton)
         ON_BN_CLICKED(IDC_WEB, OnWebButton)
         ON_BN_CLICKED(IDC_TREESTUFF, OnTreeButton)
         ON_BN_CLICKED(IDC_STATUSBUTTON, OnStatusButton)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSecuresockDlg message handlers


BOOL CSecuresockDlg::OnInitDialog()
{
         CDialog::OnInitDialog();

         // Add "About..." menu item to system menu.
         fully_loaded = false;
         cntr = 0;

         // IDM_ABOUTBOX must be in the system command range.
         ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
         ASSERT(IDM_ABOUTBOX < 0xF000);

         CMenu* pSysMenu = GetSystemMenu(FALSE);
         if (pSysMenu != NULL)
         {
                  CString strAboutMenu;
                  strAboutMenu.LoadString(IDS_ABOUTBOX);
                  if (!strAboutMenu.IsEmpty())
                  {
                           pSysMenu->AppendMenu(MF_SEPARATOR);
                           pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
                  }
         }

         HICON hIconx = ::LoadIcon (AfxGetResourceHandle(), 
                              MAKEINTRESOURCE(IDI_ICON27));

         // Set the icon for this dialog.  The framework does this automatically
         //  when the application's main window is not a dialog
         //SetIcon(m_hIcon, TRUE);                           // Set big icon
         //SetIcon(m_hIcon, FALSE);                  // Set small icon
         SetIcon(hIconx, TRUE);                           // Set big icon
         SetIcon(hIconx, FALSE);                  // Set small icon


         
         // my stuff follows
         // for convenience save these two often used pointers to member variables
         pSockApp = (CSecuresockApp*)AfxGetApp();
         pCWnd = (CWnd *)this;

         pSockApp->pHwndMainDialog = &m_hWnd;
         pSockApp->pMainDlg = (CDialog *)this;
         ::SetMainDlgHWND(m_hWnd); // file level global used with threads

         // create the tool tips object
         m_TTC.Create(this);

         // create the buttons on the top of the dialog (note created via code for max flexibility, hard
         // to set the properties right via dialog controls for icon pushbuttons this way is easier than
         // defining a bunch of other change window style calls and so on).
         MyButtonCreate(m_connectionbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 , 3, 50 + 32 , 3+32, IDC_CONNECTION);

         // set the icon to the button
         CMiscStuff::SetButtonIcon(m_connectionbutton, IDI_ICON118);

         // add tool tip for button
         m_TTC.AddWindowTool( (CWnd *)&m_connectionbutton, "Connection Settings");

         // repeat, repeat, repeat
         MyButtonCreate(m_newgroupbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 + 32 + 2, 3, 50 + 32*2 + 2 , 3+32, IDC_ADDGROUP );

         CMiscStuff::SetButtonIcon(m_newgroupbutton, IDI_ICON119);

         m_TTC.AddWindowTool( (CWnd *)&m_newgroupbutton, "Add New Group");

         MyButtonCreate(m_addcontactbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 + (32 + 2)*2, 3, 50 + 32*3 + 2*2 , 3+32, IDC_ADDCONTACT);

         CMiscStuff::SetButtonIcon(m_addcontactbutton, IDI_ICON120);

         m_TTC.AddWindowTool( (CWnd *)&m_addcontactbutton, "Add New Contact");

         MyButtonCreate(m_treebutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 + (32 + 2)*3, 3, 50 + 32*4 + 2*3 , 3+32, IDC_TREESTUFF);

         CMiscStuff::SetButtonIcon(m_treebutton, IDI_ICON123);

         m_TTC.AddWindowTool( (CWnd *)&m_treebutton, "Tree Properties");

         MyButtonCreate(m_logbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 + (32 + 2)*4, 3, 50 + 32*5 + 2*4 , 3+32, IDC_LOGBUTTON);

         CMiscStuff::SetButtonIcon(m_logbutton, IDI_ICON124);

         m_TTC.AddWindowTool( (CWnd *)&m_logbutton, "Message Logs");

         MyButtonCreate(m_securitybutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 + (32 + 2)*5, 3, 50 + 32*6 + 2*5 , 3+32, IDC_SECURITYBUTTON);

         CMiscStuff::SetButtonIcon(m_securitybutton, IDI_ICON125);

         m_TTC.AddWindowTool( (CWnd *)&m_securitybutton, "Security");

         MyButtonCreate(m_websitebutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 + (32 + 2)*6, 3, 50 + 32*7 + 2*6 , 3+32, IDC_WEB);

         CMiscStuff::SetButtonIcon(m_websitebutton, IDI_ICON122);

         m_TTC.AddWindowTool( (CWnd *)&m_websitebutton, "Drakis Website");

         MyButtonCreate(m_setstatusbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 
                  50 + (32)*7, 3, 50 + 32*7 + 16 , 3+16, IDC_STATUSBUTTON);

         CMiscStuff::SetButtonIcon(m_setstatusbutton, IDI_ICON126);

         m_TTC.AddWindowTool( (CWnd *)&m_setstatusbutton, "Set My Status");

         // I create the status text "connecting...", etc.
         // in code because sometimes that lets you create special fonts a bit easier this is not a control
         // on the dialog, altho m_online_status member variable is Attached to it once it's created.
         CreateStatusText();

         // load in the image list's we use for the tree control, all tree controls have a related image list
         // an image list is actually somewhat useful in general for other things also
         LoadImageList();

         // I use a group icon vector for convenience when adding new groups (to know what next icon to use by default)
         iCIV_offset = 0;
         LoadGroupIconVector();

         m_inick = 0;

         HICON hIcon;
         int n2 = 0;

         // first call is member function useful for resizing, altho i think now it's unneeded
         firstcall = 0;


         // load up info in registry for previous window size & position, if the registry entry for
         // "Main Dialog" is found
         RECT this_rect;
         if (    pSockApp->GetPosInfo( "Main Dialog", &this_rect)  ) {

                  pCWnd->SetWindowPos(NULL, this_rect.left, this_rect.top,
                                             this_rect.right - this_rect.left ,
                                             this_rect.bottom - this_rect.top ,
                                             SWP_SHOWWINDOW  ); // SWP_SHOWWINDOW, SWP_HIDEWINDOW

         // otherwise default to standard position
         } else {

                  RECT chkrect;
                  pCWnd->GetWindowRect(&chkrect);
                  CWnd *pwnd = (CWnd *)(&m_TreeCtrl);
                  pwnd->SetWindowPos( NULL , 0, 40, chkrect.right - chkrect.left, chkrect.bottom - chkrect.top - 60, 0 );

         }

         bool bad_load = false;

         // try to open users.ids
         // users.ids contains a snapshot of all the users using this machine, like icq I am trying to support
         // multiple people on the same chat station concept.
         ifstream optionsFile ( "users.ids");

         // if users file doesn't exist this is a first time run so sign them up now
         if (! optionsFile) {

                  // attempt to signup, if they canceled along the way postquitmessage
                  if (!SignupUser() )  {
                           AfxGetMainWnd()->PostMessage(WM_QUIT);
                           return FALSE;
                  }

         } else {

                  // load in the users that use this machine into an application vector container
                  if (! LoadUserIds() ) {
                           bad_load = true;
                           AfxMessageBox("couldn't load in the users file or some error Notify programmer");
                           AfxGetMainWnd()->PostMessage(WM_QUIT);
                           return FALSE;
                  }
                  optionsFile.close();

                  // if we got here everything is okay, this now loads in the uXXX.ids property file settings
                  // for the current user.  their chat_id is now in pSockApp->my_controls.chat_id (amongst other places).
                  pSockApp->my_controls.RestoreFromFile();
                  //pSockApp->my_controls.MBDumpVals();

         }

         CString temp = pSockApp->my_controls.GetStringByTokenName("user_icon");
         int ICONIDD = atoi(temp.GetBuffer(0));
         if (ICONIDD == 0) {
                  AfxMessageBox("trouble retrieving your icon");
                  ICONIDD = IDI_ICON31;
         }

         hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                              MAKEINTRESOURCE(ICONIDD));

         m_mypersonalbutton.SetIcon( hIcon );         
         m_my_personal_icon_id = ICONIDD;

         CString response;
         /*
         double xx;
         xx = CMiscStuff::GetSeconds();
         CString display;
         display.Format("seconds:%e", xx);
         AfxMessageBox(display);
         Sleep( 1000 );
         double xy;
         xy = CMiscStuff::GetSeconds();
         unsigned long yy;
         yy = (unsigned long)(xy - xx);
         display.Format("%lu", yy);
         AfxMessageBox(display);
         */

         bool bUseMyUrlGet = false;

         // if using my special socket stuff, currently i'm not using it as the default windows stuff for getting
         // a url file (code in application->url_get method) appears fairly fast.
         /*
         if (bUseMyUrlGet) {

                  CMySocket newconn("www.drakis.com");
                  response = newconn.GetFileAsString("/cgi-bin/check_in.pl?my_scno=101",
                           "www.drakis.com");

         } else { // or use the generic wininet windows functions to do the same thing

                  CString log_in;
                  //log_in.Format("http://www.qwest.com/dsl/customerservice/downloads/docs/WIN_67x.pdf");
                  log_in.Format("http://www.drakis.com/cgi-bin/check_in.pl?my_scno=%lu", pSockApp->my_controls.chat_id);
                  //log_in.Format("http://63.230.230.146/cgi-bin/check_in.pl?my_scno=%lu", pSockApp->my_controls.chat_id);
                  response = pSockApp->url_get(log_in.GetBuffer(0));

         }

         // should get one of the two responses here, "err" or "ok"
         if ( response.Left(2) == "ok" ) {
                  pSockApp->bTroubleConnecting = FALSE;
         } else {
                  pSockApp->bTroubleConnecting = TRUE;
         }
         */

         //CMiscStuff::OpenRead("c:\\autoexec.bat");
         bStartupFlag = true;

         OnTimer(2);

         //UpdateStatusText();

         // add the tray icon (little icon on the system bar) for the App
         AddTrayIcon();

         // try to open saved tree file, if you can open, build the tree settings
         // from this file
         if (pSockApp->my_controls.chat_id == 0) {
                  AfxMessageBox("logic error assigning chat_id, notify programmer");
                  ASSERT(0);
                  return FALSE;
         }

         temp.Format("tf_u%lu.dra", pSockApp->my_controls.chat_id);

         //ifstream treeFile ( "treefile2.ids" );
         //ifstream treeFile ( temp.GetBuffer(0) );

         CFile *myfile = new CFile();

         bool bopenokay = true;
         try {
                  myfile->Open( temp.GetBuffer(0), CFile::modeRead );

         } catch (...) {

         }
         if (myfile->m_hFile == (UINT)CFile::hFileNull) {

                  MB("Trouble Opening tree list file related to this user, default tree created");
                  bopenokay = false;
                  delete myfile;
                  myfile = (CFile *)NULL; 

         }

         // if treeFile is NULL this is okay it recreates a generic tree
         BuildTreeFromFile(m_TreeCtrl, myfile, true );
         //m_TreeCtrl.SetFont(&m_mainfont);

         //CEdit *scooby;
         //scooby = m_TreeCtrl.GetEditControl();
         //scooby->SetFont(&m_mainfont);

         if (myfile)
                  delete myfile;

         // set back ground color for tree if available
         CString colors = pSockApp->my_controls.GetStringByTokenName("tree_back_color");
         if (! colors.IsEmpty() ) {
                  unsigned long ulcolor = strtoul(colors.GetBuffer(0), NULL, 10);
                  COLORREF x2 = (COLORREF)ulcolor;
                  m_TreeCtrl.SetBkColor(x2) ;
         }

         m_hitcancel = 0;

         srand( (unsigned)time( NULL ) );

         fully_loaded = true;
         m_ilast_dept_insert_icon = 30;

         // timer tracks whether person has an incoming message and causes their icon to flash, see OnTimer method
         bUpTimer = false;
         SetTimer(1, 1000, NULL);
         //SetTimer(2, 5000, NULL);
         SetTimer(3, 5000, NULL);
         SetTimer(4, 500, NULL);

         AfxBeginThread(send_ack_msg, (LPVOID)0);

         // blinking is sporadic with normal timer, trying a multimedia timer
         // is supposed to affect performance we will see
         //unsigned int ms = 500;
         //timeBeginPeriod(ms);
         //unsigned int ntimerid = timeSetEvent(ms, ms, BlinkProc, (DWORD)this->m_hWnd, TIME_PERIODIC);
         if (1) { // ! ntimerid) {
                  //AfxMessageBox("trouble creating blink timer");
                  //timeEndPeriod(ms);
                  m_n_mmtimer_id = 0;
         } else {
                  //m_n_mmtimer_id = ntimerid;
         }

         // socket stuff is handled in threads, the main listening thread is now called
         //CMessages ref = pSockApp->main_msg_list;
         //unsigned long ul;

         //HWND hwnd_temp = pSockApp->m_hWnd;

         if (1) 
                  AfxBeginThread(main_thread, &m_hWnd);

         //main_thread(&ref);
         CString tempstr;
         tempstr.Format("current chat user id: %lu", pSockApp->my_controls.chat_id);
         //AfxMessageBox( tempstr );

         CString temp2;
         temp2.Format("new one:%i", WM_USER);

         m_TTC.AddWindowTool( (CWnd *)&m_mypersonalbutton, "User Properties");

         ::ZeroMemory(&tree_lf, sizeof(tree_lf));

         GetTreeFontFromFile();

         bTreeFontChanged = false;

         double n = CMiscStuff::GetSeconds();
         temp2.Format("seconds %g", n);

         // get saved online status (ghost mode, busy, afk, or active, based on their last entry before
         // last save
         CString saved_status = pSockApp->my_controls.GetStringByTokenName("user_online_status");

         if ( saved_status.IsEmpty() || atoi(saved_status.GetBuffer(0)) == 0) 
                  m_imy_status = CSecuresockDlg::ACTIVE;
         else 
                  m_imy_status = atoi(saved_status.GetBuffer(0));

         ::SetMyOnlineStatus(m_imy_status);

         UpdateMyStatusText();

         //AfxMessageBox( temp2 );
         //CString tempx;
         //tempx = "hello";
         //CMiscStuff::WaitWindow( tempx, this);
         //Sleep(2000);
         //CMiscStuff::ClearWaitWindow();

         //AfxMessageBox( temp2 );
         return TRUE;  // return TRUE  unless you set the focus to a control

}


BOOL CSecuresockDlg::MyButtonCreate(CButton &button, long styles, int x, int y, int cx, int cy, int cID)
{
         RECT r1;
         r1.left = x; r1.top = y; r1.right = cx; r1.bottom = cy;
         return button.Create("", styles, r1, this, cID);

}

VOID CALLBACK BlinkProc(UINT ntimerid, UINT msg, DWORD dwuser, 
                                                               DWORD dwparam1, DWORD dwparam2)
{
         PostMessage((HWND)dwuser, WM_TIMER_BLINK_EVENT, 0, 0);
}

LONG CSecuresockDlg::MakePendingsBlink(WPARAM w, LPARAM l)
{

         double x1, x2;
         x1 = CMiscStuff::GetSeconds();

         bUpTimer = ! bUpTimer;
         TraverseTree(CSecuresockDlg::BLINK_UPDATE_CALL, 0);
         //MakePendingsBlink();
         x2 = CMiscStuff::GetSeconds();
         CString temp;
         temp.Format("%3.3f", x2 - x1);
         TRACE("timer 4:%s\n", temp.GetBuffer(0));
         return 0L;
}

void CSecuresockDlg::OnTimer(UINT ntimerid)
{

         double x1, x2;
         CString temp;

         // calculate which icons have pending messages and set bPendingMsgs chatiteminfo flag if so
         if (ntimerid == 1) {

                  x1 = CMiscStuff::GetSeconds();
                  TraverseTree(CSecuresockDlg::PENDING_MSG_LOOKUP, 0);
                  x2 = CMiscStuff::GetSeconds();
                  temp.Format("%3.3f", x2 - x1);
                  TRACE("timer 1:%s\n", temp.GetBuffer(0));

         } 
         // send "check in" message to server, yes I am on, this is my IP, via thread
         else if (ntimerid == 2) {
                  /*
                  x1 = CMiscStuff::GetSeconds();
                  if (g_attempting_server_contact) {
                           TRACE("still in routine, timer send_ack_msg AVOIDED\n");
                           return;
                  }

                  //AfxMessageBox("on timer 2");
                  MessageInfo *pMsgInfo = new MessageInfo();
                  pMsgInfo->ntype = 0;
                  pMsgInfo->chat_id = 0;
                  pMsgInfo->sender_id = unsigned long GetCurrentChatID(void)
                  //pSockApp->my_controls.chat_id;
                  pMsgInfo->msg = "";
                  // note this is this->m_hWnd (securesockdlg member item m_hWnd)
                  pMsgInfo->phwnd = &m_hWnd;
                  pMsgInfo->n_online_status = this->m_imy_status;

                  TRACE("send ack msg called as normal\n");

                  AfxBeginThread(send_ack_msg, (LPVOID)pMsgInfo);
                  x2 = CMiscStuff::GetSeconds();
                  temp.Format("%3.3f", x2 - x1);
                  TRACE("timer 2:%s\n", temp.GetBuffer(0));
                  */

         }
         // check online status of my chat contacts via thread
         else if (ntimerid == 3) {

                  x1 = CMiscStuff::GetSeconds();

                  // calling this function builds a vector of "to be looked up" chat_id's that are current on the
                  // tree control
                  if (g_getting_online_status) {
                           TRACE("still getting online status timer call avoided");
                           return;
                  }

                  // this vector is a file static global 
                  online_chk_vector.clear();

                  // this traverse tree call will add chat_id for contacts and their HTREEITEMs to the vector
                  TraverseTree(CSecuresockDlg::ONLINE_STATUS_MSG_LOOKUP, 0);

                  // call the thread that gets whether these users are online or not (and updates the tree control
                  // by sending a message back to the window).
                  MessageInfo *pMsgInfo = new MessageInfo();
                  pMsgInfo->ntype = 0;
                  pMsgInfo->chat_id = 0;
                  pMsgInfo->sender_id = 0;
                  pMsgInfo->msg = "";
                  // note this is this->m_hWnd (securesockdlg member item m_hWnd)
                  // dont need other info but do need a reference to the main dialog window so we can send
                  // the results of the check_online_status as a message to this window (standard way to return
                  // info from a thread).
                  pMsgInfo->phwnd = &m_hWnd;
                  
                  AfxBeginThread(check_online_status, (LPVOID)pMsgInfo);
                  x2 = CMiscStuff::GetSeconds();
                  temp.Format("%3.3f", x2 - x1);
                  TRACE("timer 3:%s\n", temp.GetBuffer(0));

         }
         // blink update call based on status of chatiteminfo bPendingMsgs
         else if (ntimerid == 4) {

                  x1 = CMiscStuff::GetSeconds();

                  bUpTimer = ! bUpTimer;
                  TraverseTree(CSecuresockDlg::BLINK_UPDATE_CALL, 0);
                  //MakePendingsBlink();
                  x2 = CMiscStuff::GetSeconds();
                  temp.Format("%3.3f", x2 - x1);
                  TRACE("timer 4:%s\n", temp.GetBuffer(0));
                  //m_TreeCtrl.Invalidate();

         }


}

void CSecuresockDlg::OnStatusButton()
{

         DWORD dp = ::GetMessagePos();
         CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) );

         UINT flags = NULL;

         CMenu menu;
         menu.LoadMenu(IDR_STATUS);
         CMenu *x;
         x = menu.GetSubMenu(0);

         /*if (m_imy_status;
         static int CSecuresockDlg::ACTIVE;
         static int CSecuresockDlg::BUSY;
         static int CSecuresockDlg::SHORT_AFK;
         static int CSecuresockDlg::LONG_AFK;
         static int CSecuresockDlg::INVISIBLE; */

         if (m_imy_status == CSecuresockDlg::ACTIVE)         {
                  x->CheckMenuItem( ID_ACTIVE, MF_CHECKED);
         }
         if (m_imy_status == CSecuresockDlg::BUSY) {
                  x->CheckMenuItem( ID_BUSY, MF_CHECKED);
         }
         if (m_imy_status == CSecuresockDlg::SHORT_AFK) {
                  x->CheckMenuItem( ID_SHORT_AFK, MF_CHECKED);
         }
         //if (m_imy_status == CSecuresockDlg::LONG_AFK) {
         //         x->CheckMenuItem( ID_LONG_AFK, MF_CHECKED);
         //}
         if (m_imy_status == CSecuresockDlg::INVISIBLE) {
                  x->CheckMenuItem( ID_INVISIBLE, MF_CHECKED);
         }

         CMenu users_menu;
         users_menu.CreatePopupMenu();

         CRect rect;
         GetWindowRect(rect);

         //CPoint y;
         //::GetCursorPos(&y);
         //ScreenToClient (&y);
         CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) );
         int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect );

         if (ncmd == ID_ACTIVE)  {
                  m_imy_status = CSecuresockDlg::ACTIVE;
                  UpdateMyStatusText();
         }
         if (ncmd == ID_BUSY) {
                  m_imy_status = CSecuresockDlg::BUSY;
                  UpdateMyStatusText();
         }
         if (ncmd == ID_SHORT_AFK) {
                  m_imy_status = CSecuresockDlg::SHORT_AFK;
                  UpdateMyStatusText();
         }
         //if (ncmd == ID_LONG_AFK) {
         //         m_imy_status = CSecuresockDlg::LONG_AFK;
         //         this->m_my_status.SetWindowText("User Status: Long AFK");
         //}
         if (ncmd == ID_INVISIBLE) {
                  m_imy_status = CSecuresockDlg::INVISIBLE;
                  UpdateMyStatusText();
         }
         ::SetMyOnlineStatus(m_imy_status);

         CString temp;
         temp.Format("%i", m_imy_status);

         if (! pSockApp->my_controls.SetStringByTokenName("user_online_status", temp)) {
                  AfxMessageBox("trouble saving online status setting in properties");
         } 

         pSockApp->SavePropsToFile();


}

void CSecuresockDlg::UpdateMyStatusText(void)
{
         if (m_imy_status == CSecuresockDlg::ACTIVE) 
                  this->m_my_status.SetWindowText("User Status: Active");
         if (m_imy_status == CSecuresockDlg::BUSY)
                  this->m_my_status.SetWindowText("User Status: Busy");
         if (m_imy_status == CSecuresockDlg::SHORT_AFK)
                  this->m_my_status.SetWindowText("User Status: AFK (Away From Keyboard)");
         if (m_imy_status == CSecuresockDlg::INVISIBLE)
                  this->m_my_status.SetWindowText("User Status: Invisible");
}

void CSecuresockDlg::OnTreeButton()
{

         DWORD dp = ::GetMessagePos();
         CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) );

         UINT flags = NULL;

         CMenu menu;
         menu.LoadMenu(IDR_TREESTUFF);
         CMenu *x;
         x = menu.GetSubMenu(0);

         CMenu users_menu;
         users_menu.CreatePopupMenu();

         CRect rect;
         GetWindowRect(rect);

         //CPoint y;
         //::GetCursorPos(&y);
         //ScreenToClient (&y);
         CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) );
         int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect );

         if (ncmd == ID_TREEBKCOLOR) {

                  //this is retarded but there is no getbackground color function calling set
                  // gets it's value, here we set it to white then quickly set it back
                  COLORREF old = m_TreeCtrl.GetBkColor(); 

                  CMyColorDialog x1(old, CC_RGBINIT );
                  x1.m_cc.lStructSize = sizeof( CHOOSECOLOR );
                  x1.m_cc.Flags = x1.m_cc.Flags | CC_FULLOPEN ;
                  x1.SetWindowCaption("Select Tree Background Color");

                  if (x1.DoModal() == IDOK ) {

                           COLORREF x2 = x1.GetColor();
                            m_TreeCtrl.SetBkColor(x2) ;

                           CString temp;
                           temp.Format("%lu", (unsigned long)x2);

                           if (! pSockApp->my_controls.SetStringByTokenName("tree_back_color", temp)) {
                                    AfxMessageBox("trouble saving tree backcolor in properties");
                           } else {
                                    pSockApp->SavePropsToFile();
                           }

                  }

         }
         if (ncmd == ID_TREEFONT) {

                  CHOOSEFONT chf;

                  HDC hDC;

                  hDC = ::GetDC (this->m_hWnd);
                  chf.hDC = CreateCompatibleDC (hDC);
                  ::ReleaseDC (this->m_hWnd, hDC);
                  chf.lStructSize = sizeof (CHOOSEFONT);
                  chf.hwndOwner = this->m_hWnd;
                  chf.lpLogFont = &tree_lf;
                  chf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ; 
                  chf.rgbColors = m_TreeCtrl.crForeColor;
                  chf.lCustData = 0;
                  chf.hInstance = AfxGetInstanceHandle();
                  chf.lpszStyle = (LPTSTR)NULL;
                  chf.nFontType = SCREEN_FONTTYPE;
                  chf.nSizeMin = 0;
                  chf.nSizeMax = 0;

                  int n = ::ChooseFont(&chf);
                  if (n != 0) {
                           if (m_ptreefont)
                                    delete m_ptreefont;

                           m_ptreefont = new CFont();
                           m_ptreefont->CreateFontIndirect(&tree_lf);
                           bTreeFontChanged = true;
                           m_TreeCtrl.SetFont(m_ptreefont);
                           m_TreeCtrl.crForeColor = chf.rgbColors;
                           //m_TreeCtrl.RedrawWindow();
                           SaveTreeFont();

                  }
                  
                  //m_TreeCtrl.SetFont(&m_mainfont);

         }

}

void CSecuresockDlg::OnAddContactButton()
{

         CLookupContacts lookupdlg;
         lookupdlg.DoModal();

}

void CSecuresockDlg::OnWebButton()
{

         // this should execute internet explorer or whatever browser is the default and open
         // up a browser window to point to our site's definition of stuff.
         ::ShellExecute(NULL, NULL, "http://www.drakis.com", NULL, "", SW_SHOW);

}

void CSecuresockDlg::OnAddGroupButton()
{

         HTREEITEM newone;

         CString last_icon = pSockApp->my_controls.GetStringByTokenName("last_new_dept_icon");
         int next_icon_offset;
         int next_icon_val;

         int max_size = m_GroupIcons_CIV_Vector.size();

         // remember if offset = max_size this is off the end so reset to zero since can't have
         // vector[n] where n= vector.size() (this is a bounds error)
         if ( atoi(last_icon.GetBuffer(0) ) >= max_size || atoi(last_icon.GetBuffer(0)) < 0 ) {
                  // reset offset to zero again
                  next_icon_offset = 0;
         } else {

                  int ival = atoi(last_icon.GetBuffer(0) );
                  ival++;
                  if (ival >= max_size )
                           ival = 0;
                  next_icon_offset = ival;
         }
         next_icon_val = GetIndexFromIconID(m_GroupIcons_CIV_Vector[next_icon_offset].ICONIDD);

         // this shouldn't happen but if it does use default first icon which  is currently
         // index 26 into the imagelist (this may change tho)
         if (next_icon_val == -1)
                  next_icon_val = 26;

         CString temp;
         temp.Format("%i", next_icon_offset);
         //AfxMessageBox( temp );

         pSockApp->my_controls.SetStringByTokenName("last_new_dept_icon", temp);
         pSockApp->SavePropsToFile();

         newone = m_TreeCtrl.InsertItem( "New Group", next_icon_val, 
                                                      next_icon_val, TVI_ROOT, TVI_LAST);

         ChatItemInfo *citemp;
         citemp = new ChatItemInfo;
         citemp->chat_id = 0;
         citemp->ntype = GROUP;
         citemp->create_time = GetTimeString() ;
         citemp->msg = "Contact Group";
         add_ptr_to_garbage(citemp, "ChatItemInfo");

         m_TreeCtrl.SetItemData( newone, (DWORD)citemp );

         m_TreeCtrl.EditLabel(newone);


}

void CSecuresockDlg::OnConnectionButton()
{

         DWORD dp = ::GetMessagePos();
         CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) );

         UINT flags = NULL;

         CMenu menu;
         menu.LoadMenu(IDR_CONNECTION);
         CMenu *x;
         x = menu.GetSubMenu(0);

         CMenu users_menu;
         users_menu.CreatePopupMenu();

         CRect rect;
         GetWindowRect(rect);

         //CPoint y;
         //::GetCursorPos(&y);
         //ScreenToClient (&y);
         CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) );
         int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect );

         if (ncmd == ID_CHECKLATENCY) {

                  GetLatency() ;

         }

         if (ncmd == ID_CONNPROPERTIES) {

                  AfxMessageBox("Under Construction");

         }
         //AfxMessageBox("cli");

}

void CSecuresockDlg::CreateStatusText() 
{


         CClientDC dc(this);

         LOGFONT lf;
         ::ZeroMemory(&lf, sizeof(lf));
         lf.lfHeight = 80;
         lf.lfWeight = FW_BOLD;
         lf.lfItalic = FALSE;
         ::lstrcpy( lf.lfFaceName, "Arial");
         m_mainfont.CreatePointFontIndirect(&lf);

         CFont *old_font = dc.SelectObject(&m_mainfont);
         TEXTMETRIC tm;
         dc.GetTextMetrics(&tm);
         int m_cxChar = tm.tmAveCharWidth;
         int m_cyChar = tm.tmHeight + tm.tmExternalLeading;
         dc.SelectObject(old_font);

         CRect rect (m_cxChar * 2, m_cyChar * 2, m_cxChar * 25, m_cyChar * 4);

         m_online_status.Create("connecting...", WS_CHILD | WS_VISIBLE | SS_LEFT, rect, this);

         //rect = CRect(m_cxChar * 5, m_cyChar * 5, m_cxChar * 100, m_cyChar * 5);
         m_my_status.Create("User Status: Active", WS_CHILD | WS_VISIBLE | SS_LEFT, rect, this);

         m_online_status.SetFont(&m_mainfont);
         m_my_status.SetFont(&m_mainfont);

         m_RedBrush.CreateSolidBrush( RGB( 255, 64, 64) );
         m_GreenBrush.CreateSolidBrush( RGB( 64, 255, 64) );
         m_BlackBrush.CreateSolidBrush( RGB( 0, 0, 0) );

         if (1) {
                  RECT chkrect;
                  pCWnd->GetWindowRect(&chkrect);
                  CWnd *pwnd2 = (CWnd *)(&m_my_status);
                  int x, y, cx, cy;
                  x = 0;
                  y = chkrect.bottom - chkrect.top - 43;
                  cx = 100;
                  cy = 20;
                  //ASSERT(0);
                  /*
                  pwnd2->SetWindowPos( NULL , 10 ,
                           y, 
                           100, 100 , SWP_SHOWWINDOW ); */

                  /*
                  pwnd2 = (CWnd *)(&m_my_status);
                  pwnd2->SetWindowPos( NULL, 100 ,
                           y,
                           100, 100, SWP_SHOWWINDOW ); */

         }

}

void CSecuresockDlg::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
         //if (nChar == VK_CANCEL)
                  //AfxMessageBox("cancel hit");

         CDialog::OnSysChar(nChar, nRepCnt, nFlags);
}

// signup a new user by getting various info via dialogs
bool CSecuresockDlg::SignupUser(bool bWelcomeScreen ) 
{

         int myresult;
         int choice = 1;
         char *newptr;

         if (bWelcomeScreen) {

                  WelcomeDlg mypersonal;
                  myresult = mypersonal.DoModal();
                  choice = mypersonal.m_choice;
                  if (mypersonal.m_choice == 0) 
                           return false;

         }

         if (choice == 1 || ! bWelcomeScreen ) {

                  PersonalInfoDlg pid;
                  myresult = pid.DoModal();
                  if (pSockApp->m_canceled)
                           return false;

                  CCompDlg cid;
                  myresult = cid.DoModal();
                  if (pSockApp->m_canceled)
                           return false;

                  InternetInfoDlg iid;
                  myresult = iid.DoModal();
                  if (pSockApp->m_canceled)
                           return false;

                  GetChatID pid2;
                  myresult = pid2.DoModal();
                  if (pSockApp->m_canceled)
                           return false;

                  IconChooser icd;
                  icd.bGroupIcon = false;

                  // the postncdestroy method in IconChooser will delete this memory allocated
                  // here so this isn't a real memory leak
                  newptr = new char[100];
                  strcpy(newptr, "Select Your Personal Chat Icon");

                  // set the caption for the chooser dialog, uses soft logic if not set then uses
                  // a default value (this dialog is called from other places than registration)
                  icd.title = newptr; // this isn't a memory leak the dialog itself will release the
                                             // memory via delete [] for this pointer
                  icd.m_signup = 1; // registration level call (screen can be called from different places
                                     // in the program this flag helps to differentiate
                  myresult = icd.DoModal();
                  if (pSockApp->m_canceled) {
                           return false;
                  }

                  int ICONIDD;

                  // if they didn't hit cancel but selected a real icon
                  if (icd.ICON_IDD != -1) {

                           ICONIDD = icd.ICON_IDD;

                  } else { // this is if they canceled instead of selecting an icon
                           AfxMessageBox("A generic icon will be used, you may change this later via \"change icon\" ");
                           ICONIDD = IDI_ICON31;
                  }

                  HICON hIcon;

                  // if selected a real icon
                  if (ICONIDD != -1) {
                           hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(ICONIDD));
                           m_mypersonalbutton.SetIcon( hIcon );         
                  } else {                          // otherwise use the default one
                           ICONIDD = IDI_ICON31; // ICON31 is a default, if they didn't select it we set default to that
                                                                                 // rather than show an empty icon button
                           hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(ICONIDD));
                           m_mypersonalbutton.SetIcon( hIcon );         

                  }

                  CString temp;
                  temp.Format("%i", ICONIDD);
                  if (! pSockApp->my_controls.SetStringByTokenName("user_icon", temp))
                           AfxMessageBox("trouble setting user_icon in properties");

                  // save favorite icon choice to userprop2.ids
                  //ofstream optionsFile2 ( "userprop2.ids", ios::out );
                  //optionsFile2 << setw(7) << ICONIDD <<  '\n';

                  // save this to a class variable also so we can keep track of the last personal icon
                  // add a save function to the destructor
                  m_my_personal_icon_id = ICONIDD;

                  pSockApp->SavePropsToFile();

                  //pSockApp->AddUser( strtoul( buffer, NULL, 10), cnickname, bdefault );
                  //char *temp_password = ;

                  CString nickname = pSockApp->my_controls.GetStringByTokenName("nickname");
                  pSockApp->AddUser( pSockApp->my_controls.GetChatId(), 
                           nickname.GetBuffer(0), 
                           pSockApp->my_controls.GetPassword(), true);


         }
         return true;

}

bool CSecuresockDlg::LoadUserIds(void)
{

         int n;
         ifstream users_file ( "users.ids" );

         //char buffer[257];
         //char cnickname[101];
         char is_default;
         //char discard;
         bool bdefault;
         bool hitdefault = false;
         unsigned long chat_id;
         char text[256];
         int itextlen;
         //char cchat_id[11];

         //ASSERT(0);
         if (users_file) {

                  n = 0;
                  //users_file.unsetf( ios::skipws );
                  //users_file.seekg(0);

                  while (! users_file.eof() ) {

                           //stream_stuff::read_long(users_file, &contact_id);
                           if (users_file.read(text, 10) == 0)
                                    break;
                           text[10] = (char)0;
                           chat_id = strtoul(text, NULL, 10);

                           users_file.read(text, 1);
                           is_default = text[0];

                           users_file.read(text, 4);
                           text[4] = 0;
                           itextlen = atoi(text);

                           users_file.read(text, 1);

                           //itextlen++; // add one for zero terminator
                           if (itextlen < 0 || itextlen > 254 ) {
                                    ASSERT(0);
                                    AfxMessageBox("corrupt users list file serious error, contact programmer");
                                    users_file.close();
                                    return false;
                           }

                           users_file.read(text, itextlen);
                           text[itextlen] = (char)0;

                           bdefault = ! (is_default == '0');                  
                           pSockApp->AddUser( chat_id, text, "", bdefault );
                           hitdefault = hitdefault || bdefault;

                           users_file.read(text,1);

                  }
                  users_file.close();

                  if (! hitdefault) {
                           CString msg;
                           msg.Format("No User is set to default, setting default to %s", pSockApp->users_array[0].nickname.GetBuffer(0));
                           AfxMessageBox( msg );
                           pSockApp->SetDefaultUser( 0 );
                  }

         } else {
                  return false;
         }
         return true;

}

void CSecuresockDlg::LoadGroupIconVector(void)
{

         int n;
         CImageVector temp;
         m_GroupIcons_CIV_Vector.clear();

         int n2 = 0;

         for (n=IDI_ICON24; n <= IDI_ICON60;n++) {

                  if (n==IDI_ICON31) continue;
                  if (n==IDI_ICON30) continue;
                  if (n==159 || n == 160) continue;

                  temp.nindex = n2++;
                  temp.ICONIDD = n;
                  m_GroupIcons_CIV_Vector.push_back(temp);

         } 

}

void CSecuresockDlg::LoadImageList()
{

         m_ImageList.Create(16,
                    16,
                    ILC_MASK | ILC_COLOR,   // list does not include masks
                    0,
                    1 );   // list will not grow

         HICON hIcon;
         int result;


         //
         // load the icon images and add them 
         // to the image lists
         //
         int n;
         int n2 = 0;
         for (n=129;n<159;n++) {

                  hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(n));

                  result = m_ImageList.Add(hIcon);

                  CSecuresockApp *ref_app;
                  CImageVector temp;
                  ref_app = (CSecuresockApp *)AfxGetApp();
                  temp.nindex = n2++;
                  temp.ICONIDD = n;
                  ref_app->m_imagevector.push_back(temp);

         }

         for (n=161;n<=190;n++) {

                  hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(n));

                  result = m_ImageList.Add(hIcon);

                  CSecuresockApp *ref_app;
                  CImageVector temp;
                  ref_app = (CSecuresockApp *)AfxGetApp();
                  temp.nindex = n2++;
                  temp.ICONIDD = n;
                  ref_app->m_imagevector.push_back(temp);

         }

         for (n=207;n<=214;n++) {

                  hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(n));

                  result = m_ImageList.Add(hIcon);

                  CSecuresockApp *ref_app;
                  CImageVector temp;
                  ref_app = (CSecuresockApp *)AfxGetApp();
                  temp.nindex = n2++;
                  temp.ICONIDD = n;
                  ref_app->m_imagevector.push_back(temp);

         }

         n = IDI_ICON83;
         hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                       MAKEINTRESOURCE(n));

         result = m_ImageList.Add(hIcon);

         CSecuresockApp *ref_app;
         CImageVector temp;
         ref_app = (CSecuresockApp *)AfxGetApp();
         temp.nindex = n2++;
         temp.ICONIDD = n;
         ref_app->m_imagevector.push_back(temp);

         for (n=IDI_ICON84;n<=IDI_ICON93;n++) {

                  hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(n));

                  result = m_ImageList.Add(hIcon);

                  CSecuresockApp *ref_app;
                  CImageVector temp;
                  ref_app = (CSecuresockApp *)AfxGetApp();
                  temp.nindex = n2++;
                  temp.ICONIDD = n;
                  ref_app->m_imagevector.push_back(temp);

         }

         for (n=IDI_ICON94; n <= IDI_ICON114;n++) {

                  hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(n));

                  result = m_ImageList.Add(hIcon);

                  CSecuresockApp *ref_app;
                  CImageVector temp;
                  ref_app = (CSecuresockApp *)AfxGetApp();
                  temp.nindex = n2++;
                  temp.ICONIDD = n;
                  ref_app->m_imagevector.push_back(temp);


         } 

         for (n = IDI_ICON115; n <= IDI_ICON115;n++) {
                  hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(n));

                  result = m_ImageList.Add(hIcon);

                  CSecuresockApp *ref_app;
                  CImageVector temp;
                  ref_app = (CSecuresockApp *)AfxGetApp();
                  temp.nindex = n2++;
                  temp.ICONIDD = n;
                  ref_app->m_imagevector.push_back(temp);

         }

         //

         hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                       MAKEINTRESOURCE(234));
         result = m_ImageList.Add(hIcon);
         BOOL bres = m_ImageList.SetOverlayImage( n2, 1 );
         ASSERT(bres);
         n2++;

         hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                       MAKEINTRESOURCE(235));
         result = m_ImageList.Add(hIcon);
         bres = m_ImageList.SetOverlayImage( n2, 2 );
         ASSERT(bres);
         n2++;

         hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                       MAKEINTRESOURCE(236));
         result = m_ImageList.Add(hIcon);
         bres = m_ImageList.SetOverlayImage( n2, 3 );
         ASSERT(bres);
         n2++;

         hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                       MAKEINTRESOURCE(237));
         result = m_ImageList.Add(hIcon);
         bres = m_ImageList.SetOverlayImage( n2, 4 );
         ASSERT(bres);
         n2++;

         m_TreeCtrl.SetImageList( &m_ImageList, TVSIL_NORMAL);

         //m_ImageList.DeleteImageList();

}

void CSecuresockDlg::AddTrayIcon()
{

         NOTIFYICONDATA nid;
         nid.cbSize = sizeof(nid);
         nid.hWnd = this->m_hWnd;
         nid.uID = 1;
         nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
         nid.uCallbackMessage = WM_TRAY_IDD;
         HICON hicon2;
         hicon2 = ::LoadIcon (AfxGetResourceHandle(), 
                              MAKEINTRESOURCE(IDI_ICON27));

         nid.hIcon = hicon2;
         strcpy(nid.szTip, "SecureChat");

         // use mutex to make sure there isn't another shell icon already up
         ::CreateMutex(NULL, TRUE, "SecureChatTBIcon");
         if ( GetLastError() != ERROR_ALREADY_EXISTS )
                  Shell_NotifyIcon(NIM_ADD, &nid); // it wasn't there add it now


}

void CSecuresockDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
         if ((nID & 0xFFF0) == IDM_ABOUTBOX)
         {
                  CAboutDlg dlgAbout;
                  dlgAbout.DoModal();
         }
         else
         {
                  //CString output;
                  //output.Format("%u", nID);
                  //AfxMessageBox(output);

                  if (nID == SC_MINIMIZE) {
                           //AfxMessageBox("minimizing");
                           this->ShowWindow(SW_HIDE);
                           return;
                  }

                  CDialog::OnSysCommand(nID, lParam);
         }
}

void CSecuresockDlg::OnDestroy()
{
         WinHelp(0L, HELP_QUIT);
         ::clean_up_garbage();

         if (m_ptreefont)
                  delete m_ptreefont;

         CDialog::OnDestroy();
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSecuresockDlg::OnPaint() 
{
         if (IsIconic())
         {
                  CPaintDC dc(this); // device context for painting

                  SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

                  // Center icon in client rectangle
                  int cxIcon = GetSystemMetrics(SM_CXICON);
                  int cyIcon = GetSystemMetrics(SM_CYICON);
                  CRect rect;
                  GetClientRect(&rect);
                  int x = (rect.Width() - cxIcon + 1) / 2;
                  int y = (rect.Height() - cyIcon + 1) / 2;

                  // Draw the icon
                  dc.DrawIcon(x, y, m_hIcon);
         }
         else
         {
                  CDialog::OnPaint();
         }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSecuresockDlg::OnQueryDragIcon()
{
         return (HCURSOR) m_hIcon;
}

// Automation servers should not exit when a user closes the UI
//  if a controller still holds on to one of its objects.  These
//  message handlers make sure that if the proxy is still in use,
//  then the UI is hidden but the dialog remains around if it
//  is dismissed.

void CSecuresockDlg::OnClose() 
{
         ((CSecuresockApp *)AfxGetApp())->SavePosInfo((CWnd *)this, "Main Dialog");

         SaveUsersToFile();

         if (CanExit())
                  CDialog::OnClose();
}

void CSecuresockDlg::OnOK() 
{
         //AfxMessageBox("ok");
         if (CanExit()) {
                  CDialog::OnOK();
                  //DestroyWindow();
         }

}

void CSecuresockDlg::OnCancel() 
{
         //AfxMessageBox("cancel");
         if (CanExit()) {
                  CDialog::OnCancel();
                  //DestroyWindow();
         }
}

BOOL CSecuresockDlg::CanExit()
{
         // If the proxy object is still around, then the automation
         //  controller is still holding on to this application.  Leave
         //  the dialog around, but hide its UI.
         if (m_pAutoProxy != NULL)
         {
                  ShowWindow(SW_HIDE);
                  return FALSE;
         }

         return TRUE;
}

void CSecuresockDlg::OnRclickTree1(NMHDR* pNMHDR, LRESULT* pResult) 
{

         if (0) {
                  sndPlaySound("driveby.wav", SND_ASYNC);
         }

         DWORD dp = ::GetMessagePos();

         CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) );

         m_TreeCtrl.ScreenToClient (&pt);
         UINT flags = NULL;

         //char buffer[20];
         int choice;
         int myresult;
         //DWORD this_contact_id;

         HTREEITEM thishitem = m_TreeCtrl.HitTest( pt, &flags);
         m_TreeCtrl.SelectItem( thishitem );
         bool bHitTestFailed = false;

         // NULL means they clicked in area which is not an item so ignore
         if ( thishitem == NULL) {
                  *pResult = 1;
                  bHitTestFailed = true;
                  //return;
         }

         ChatItemInfo *tempci;
         //ChatItemInfo *citemp ;

         CLookupContacts lookupdlg;

         CMenu menu;
         menu.LoadMenu(IDR_MENU1);
         CMenu *x;
         bool bGroupLevelCall;
         bool bSystemMsg = false;
         bool bIncCR = false;
         bool bPCGroup = false;
         bool bChatContact = false;

         // if we aren't on a non-item, grab the related chatiteminfo pointer from the item selected
         if (! bHitTestFailed ) {
                  tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem ));

                  bPCGroup = (tempci->ntype == PENDING_CONTACTS_GROUP);
                  bChatContact = (tempci->ntype == CHAT_CONTACT );
         }


         // if on no item then show this short menu
         if (bHitTestFailed) {
                  x = menu.GetSubMenu(7);

         // if top level item = department, use department menu, otherwise use contact menu
         } else if ( m_TreeCtrl.GetParentItem(thishitem) == NULL) { 
                  x = menu.GetSubMenu(1);
                  bGroupLevelCall = true;

         } else {

                  if (tempci->ntype == SYSTEM_MSG) {
                           x = menu.GetSubMenu(5);
                           bSystemMsg = true;

                  } else if (         tempci->ntype == INCOMING_CONTACT_REQUEST ) {
                           x = menu.GetSubMenu(6);
                           bIncCR = true;

                  } else {
                           x = menu.GetSubMenu(0);
                           x->DeleteMenu(ID_RIGHTCLICK_SPLITWINDOWCHAT, MF_GRAYED);
                  }

                  // MF_GRAYED
                  //BOOL ModifyMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
                  bGroupLevelCall = false;
         }

         CRect rect;
         GetWindowRect(rect);

         CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) );

         // i get the value back directly rather than map it as a COMMAND message, which would also
         // be fine.
         int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect );

         // defining variables within case statements is causing a weird bug with default: clause
         // something about "initialization of variable x not found for default" which makes no sense I think
         // this is a Visual C++ bug with case statements, i like to define temp variables only within the block
         // of code used but in this case some are defined at a higher level (temp here and myresult, etc above)
         CString temp;
         //ChatItemInfo *tempci = new ChatItemInfo;
         CString temp1;
         CPropDlg pd;
         MyCtrlContainer *ptempCtrlContainer;

         CMyPropSheet testprop(IDS_MYPROPS, this, 0) ;
         CPersP1 p1;
         CPersP3 p3;
         CPers_P2 p2;
         CString msg1;

         CString last_icon;

         CMoveContactDlg mcd;
         CAcceptContact acdlg;
         int nresult;
         int response;

         switch (ncmd ) {

         /*case ID_GET_CHATID:
         
                  this_contact_id = m_TreeCtrl.GetItemData( thishitem );
                  temp.Format("chat id:%u", this_contact_id);
                  MessageBox( temp );
                  break; */

         case ID_ACCEPT:
                  ProcessChatRequest(thishitem, tempci, true);
                  //AfxMessageBox("add");

                  break;
         case ID_DECLINE:
                  ProcessChatRequest(thishitem, tempci, false);
                  //AfxMessageBox("decline");
                  break;

         case ID_VIEW:

                  tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem ));
                  acdlg.m_ContactMsg = tempci->msg;
                  nresult = acdlg.DoModal();
                  if (acdlg.nstatus == 1) {
                           //AfxMessageBox("add");
                           ProcessChatRequest(thishitem, tempci, true);
                  }
                  if (acdlg.nstatus == 0) {
                           //AfxMessageBox("decline");
                           ProcessChatRequest(thishitem, tempci, false);
                  }
                  break;


         case ID_TREE_ITEM_INFO:

                  tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem ));
                  temp1.Format("related chat id:%lu\nitem type:%s\ndescrip:%s\ncreated:%s", tempci->chat_id, ChatItemInfo::TypeDescrip(tempci->ntype), tempci->msg, tempci->create_time );
                  //MB( temp1, MB_OK, "Item Properties" );
                  pd.m_ChatId.Format("%lu", tempci->chat_id);
                  pd.m_Created = tempci->create_time;
                  pd.m_Descrip = tempci->msg;
                  pd.m_ItemType = ChatItemInfo::TypeDescrip(tempci->ntype);
                  pd.m_Nickname = tempci->nickname;
                  pd.m_Time_Received = tempci->time_received;
                  pd.m_Icon_ID.Format("%i", tempci->icon_id);

                  //pd.UpdateData(FALSE);

                  pd.DoModal();
                  break;

         case ID_PROPERTIES:

                  // get related chat info item
                  tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem ));
                  // open a new control container with this chat_id as default
                  ptempCtrlContainer = new MyCtrlContainer();

                  // update the properties in the control container from the web
                  ptempCtrlContainer->BlankAllValues();
                  ptempCtrlContainer->SetChatId(tempci->chat_id);

                  msg1 = "Getting Server Settings";
                  CMiscStuff::WaitWindow( msg1, this );
                  ptempCtrlContainer->UpdateLocalFromURL();
                  //Sleep(2000);
                  CMiscStuff::ClearWaitWindow();

                  // assign this temporary control container to the app (used by dialogues saving/
                  // get window val routines).
                  pSockApp->m_pcontact_mcc = ptempCtrlContainer;

                  // make sure this flag is set back to false when done so signing a new user or viewing
                  // your own properties pulls from the right control container
                  pSockApp->m_bUsingOtherProp = true;

                  testprop.m_psh.dwSize = sizeof(testprop.m_psh);
                  testprop.m_psh.dwFlags |=  PSH_NOAPPLYNOW ;
                  testprop.m_bViewingOthers = true;
                  testprop.newtitle.Format("Viewing Properties for User %lu [Read-only]", tempci->chat_id);

                  p1.m_psp.dwFlags &= (~PSH_HASHELP);
                  p2.m_psp.dwFlags &= (~PSH_HASHELP);
                  p3.m_psp.dwFlags &= (~PSH_HASHELP);

                  testprop.AddPage(&p1);
                  testprop.AddPage(&p2);
                  testprop.AddPage(&p3);
                  
                  response = testprop.DoModal();
                  if (response == IDOK) {

                           //pSockApp->SavePropsToFile();         
                           // save properties to web
                           //pSockApp->my_controls.UpdateURLwithInfo();

                  }

                  // ALWAYS SET THIS TO FALSE WHEN DONE, lets the app know whether we are looking at someone else's
                  // properties or at those for the current user (or a new user signing on)
                  pSockApp->m_bUsingOtherProp = false;

                  // reset this pointer to zero when not in use
                  pSockApp->m_pcontact_mcc = (MyCtrlContainer *)0;

                  delete ptempCtrlContainer;


                  break;

         case ID_ADDUSER:

                  if (!SignupUser( false ) )  {
                           AfxMessageBox("Trouble adding this user, notify Programmer");
                  }

         case ID_RIGHTCLICK_SPLITWINDOWCHAT:

                  pdlg = new TwoWayDlg();
                  pdlg->m_bModeless = TRUE;

                  // retrieve this person's image from the tree control
                  int iimage;
                  if ( (iimage = m_TreeCtrl.GetImageIndex(thishitem)) != -1)
                  {
                           pdlg->m_myiconid = iimage; 
                  } else {
                           pdlg->m_myiconid = 30;
                           MessageBox("debug note: trouble getting image for this tree item");
                  }

                  pdlg->Create();
                  break;

         case ID_OPTION1_ADDNEWDEPT:

                  OnAddGroupButton();
                  break;

         case ID_RIGHTCLICK_NICKNAME:

                  //int itest = rand() % 3;
                  // give them a reminder
                  MessageBox(  "You can change this users Nickname to something more preferable, just be sure you don't "
                                    "get confused who this contact refers to.  You can always right click and select TreeItem Info to see what is "
                                    "their common Chat Nickname. This new Nickname will not be sent to them via any mechanism it is simply for your"
                                    "own tree display.",  "Reminder",  MB_OK ) ;

                  m_TreeCtrl.EditLabel(thishitem);
                  CEdit *scooby;
                  scooby = m_TreeCtrl.GetEditControl();

                  
                  // if we don't subclass it the dialog will override enter and cancel keys which is not
                  // optimal behavior.  another trick from an online example.
                  m_TreeEdit.SubclassWindow( scooby->m_hWnd );
                  m_inick = 1;
                  break;

         
         case ID_OPTION1_EDITLABEL: 

                  m_TreeCtrl.EditLabel(thishitem);
                  break;

         case ID_OPTION1_ADDCONTACT:

                  // 30 is the default contact icon for now
                  lookupdlg.DoModal();

                  //m_TreeCtrl.InsertItem( "New Contact", 30, 30, thishitem);
                  //m_TreeCtrl.Expand( thishitem, TVE_EXPAND);

                  break;

         case ID_RIGHTCLICK_DELETE:
         case ID_OPTION1_REMOVEGROUP:

                  char buffer[200];
                  //ASSERT(0);

                  if (m_TreeCtrl.GetItemData( thishitem ) == 2) {
                           AfxMessageBox("Sorry you can't delete this group as it's needed for keeping track of System Messages. =)");
                           break;
                  }

                  if (! m_TreeCtrl.GetLabelText(thishitem, buffer, 200) )
                           strcpy(buffer, "");

                  if (bSystemMsg) {
                           temp = "Do you wish to delete this system message? Note: pending contact requests and other "
                                                               "operations will not be adversely affected by deleting system messages. "
                                                               "All messages will have related entries in the message logs.";
                  } else {

                           if (ncmd == ID_OPTION1_REMOVEGROUP) {
                                    if (!bPCGroup) 
                                             temp.Format("Are you sure you wish to remove the Group %s from your contact list?\n "
                                                               "Warning: this will remove all attached contacts to this group "
                                                               "and you will have to re-add them later.  Continue?", buffer);
                                    else
                                             temp.Format("Deleting the Incoming Contact Request Group will delete all Incoming Contact Requests associated with it, continue?", buffer);

                           } else if (         bIncCR ) {

                                    temp.Format("Deleting an Incoming Contact Request will remove the Request Message without issuing an accept or decline.  Are you sure you wish to do this?", buffer);

                           } else if (bPCGroup ) {
                                                               
                                    temp.Format("Deleting the Incoming Contact Request Group will delete all Incoming Contact Request associated with it, continue?", buffer);
                           
                           } else {
                                    temp.Format("Are you sure you wish to remove %s from your contact list?", buffer);
                           }

                  }

                  if ( MB(  temp.GetBuffer(0), MB_YESNO, "Delete?" ) == IDYES   ) {

                           m_TreeCtrl.DeleteItem( thishitem );

                  }
                  break;

         case ID_RIGHTCLICK_SENDMESSAGE :

                  //m_TreeCtrl.SelectItem( thishitem );
                  CSendDlg *senddlg;

                  //MessageBox("send message");
                  senddlg = new CSendDlg();
                  senddlg->iUserIconID = tempci->icon_id;
                  TRACE("calling send dlg, chat id : %lu", tempci->chat_id);
                  //tempci->chat_id
                  //AfxMessageBox( tempci->nickname );

                  TRACE("nickname: %s", tempci->nickname.GetBuffer(0));

                  senddlg->m_myiconid = m_TreeCtrl.GetImageIndex(thishitem);
                  senddlg->m_nickname = tempci->nickname;
                  senddlg->chat_id = tempci->chat_id;

                  senddlg->Create();
                  senddlg->SetActiveWindow();

                  break;

         case ID_HISTORY:

                  AfxMessageBox("not yet supported");
                  break;

         case ID_MOVE_GROUP:
                  AfxMessageBox("not yet supported");
                  break;

         case ID_CHANGE_ICON1: 

                  if (! bGroupLevelCall) {

                           int response = MB("You may change a user's display icon in your treeview to something you like more but be "
                                    "careful not to get confused as to who they are.\nRemember you can always right click and select Quick Info if you get confused.\nContinue with changing their Icon?", MB_YESNO);
                           if (response != IDYES) 
                                    break;
                  }

                  IconChooser myChooserDlg;

                  myChooserDlg.bGroupIcon = bGroupLevelCall;

                  myChooserDlg.m_signup = 0;

                  myresult = myChooserDlg.DoModal();

                  choice = this->GetIndexFromIconID(myChooserDlg.ICON_IDD);


                  if ((myresult == IDOK) && (choice != -1)) {

                           m_TreeCtrl.SetImagesByIndex(thishitem, choice);

                           tempci->icon_id = myChooserDlg.ICON_IDD;
                           
                           // save new icon to the properties file
                           //SaveMyIcon(GetIconIDFromIndex(choice));

                  }

                  break;

         //default:
         //         itoa(ncmd, buffer, 10);
         //         MessageBox(buffer, "Unhandled command value");
         }

         //_itoa( ncmd, buffer, 10);
         //AfxMessageBox(buffer);

         menu.DestroyMenu();

         //SendMessage( WM_LBUTTONUP, 0, MAKELPARAM(1,1));
         //::SendMessage( GetDlgItem(IDC_TREE1)->m_hWnd, WM_RBUTTONUP, 0, MAKELPARAM((unsigned)y.x, (unsigned)y.y));
         *pResult = 1;
         return;

}

void CSecuresockDlg::OnButton1() 
{

         if (rclickmenu) {
         CRect rect;
         GetWindowRect(rect);
         char buffer[20];
         sprintf(buffer, "%i, %i, %i, %i", rect.left, rect.right, rect.top, rect.bottom);
    //AfxMessageBox(buffer);

         rclickmenu->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON, rect.left, rect.bottom -1, AfxGetMainWnd(), rect);

         }


}

void CSecuresockDlg::OnSize(UINT nType, int cx, int cy) 
{

         CDialog::OnSize(nType, cx, cy);
         CWnd *pwnd = (CWnd *)(&m_TreeCtrl);
         if (::IsWindow(pwnd->m_hWnd)) {
                  pwnd->SetWindowPos( NULL , 0, 38, cx, cy - 60, 0 );
         }


         //CWnd *pwnd2 = (CWnd *)(&m_online_status);
         RECT rect;
         /*
         if (::IsWindow(pwnd2->m_hWnd)) {
                  pwnd2->GetWindowRect(&rect);
                  pwnd2->SetWindowPos( NULL , 10, cy - 17, cx, cy , 0 );
                  //pwnd2->Invalidate(); // cause color repaint, not sure if strictly necessary

         } else {
                  //AfxMessageBox("failure with window 1");
         } */

         CWnd *pwnd3 = (CWnd *)(&m_my_status);
         if (::IsWindow(pwnd3->m_hWnd)) {
                  pwnd3->SetWindowPos( NULL , 101, cy - 19, 600, cy , 0 );
                  //pwnd3->GetWindowRect(&rect);
                  //CString out;
                  //out.Format("%i, %i, %i, %i", rect.top, rect.left, rect.bottom, rect.right );
                  //AfxMessageBox(out);
                  //::InvalidateRect(this->m_hWnd, &rect, TRUE);

                  pwnd3->Invalidate(); // cause color repaint, not sure if strictly necessary
         } else {
                  //AfxMessageBox("failure with window 2");
         }
         CWnd *pwnd2 = (CWnd *)(&m_online_status);
         //RECT rect;
         if (::IsWindow(pwnd2->m_hWnd)) {
                  pwnd2->GetWindowRect(&rect);
                  pwnd2->SetWindowPos( NULL , 0, cy - 19, 79, cy , 0 );
                  //pwnd2->Invalidate(); // cause color repaint, not sure if strictly necessary

         } else {
                  //AfxMessageBox("failure with window 1");
         } 

         CWnd *mstatusb = (CWnd *)(&m_setstatusbutton);
         if (::IsWindow(mstatusb->m_hWnd) ) {
                  mstatusb->SetWindowPos(NULL, 80, cy - 20, 20, 20, 0);
         }

         this->GetWindowRect(&rect);
         //::InvalidateRect(this->m_hWnd, &rect, TRUE);
         
         firstcall++;
         
}

void gettreeiconindexes( const CTreeCtrl &piTree, HTREEITEM pitem, int &image, int &sel_image, bool &is_expanded ) {

         TVITEM tv;
         BOOL result;
         tv.mask =  TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE ;
         tv.hItem = pitem;
         tv.stateMask = TVIS_EXPANDED;

         is_expanded = false;

         result = piTree.GetItem( &tv );
         if (result) {
                  image = tv.iImage;
                  sel_image = tv.iSelectedImage;
                  is_expanded = ! ((tv.state & TVIS_EXPANDED)==0);
                  if (is_expanded) {
                           //ASSERT(0);
                  }

         } else {
                  image = sel_image = -1;
         }

}

void settreeexpanded( CTreeCtrl &piTree, HTREEITEM pitem, bool is_expanded ) {

         TVITEM tv;
         BOOL result;
         tv.mask =  TVIF_STATE ;
         tv.hItem = pitem;
         tv.stateMask = TVIS_EXPANDED;
         if (is_expanded ) 
            tv.state = TVIS_EXPANDED;
         else
                  tv.state = 0;

         result = piTree.SetItem( &tv );
         if (!result) {
                  ASSERT(0);
         }

}

CString gettreetext( const CTreeCtrl &piTree, HTREEITEM pitem ) {

         TVITEM tv;
         BOOL result;
         CString x1;
         tv.mask =  TVIF_TEXT ;
         tv.hItem = pitem;
         tv.stateMask = 0;
         char buffer3[200];
         tv.pszText = buffer3;
         tv.cchTextMax = 200;

         result = piTree.GetItem( &tv );
         if (result) {
                  x1 = tv.pszText;
         } else {
                  x1 = "";
         }
         return x1;
}

void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent,
                           int contact_id, int iimage, int isel_image, bool is_expanded) {

         TreeSaver thisone;
         thisone.id = param_id;
         thisone.parent_id = param_parent;
         if (strlen( param_text) > 99) {
                  strncpy(thisone.text, param_text, 99);
                  thisone.text[99] = (char)0;
         } else {
                  strcpy(thisone.text, param_text );
         }
         thisone.contact_id = contact_id;
         thisone.hitem = hitem;
         thisone.iimage = iimage;
         thisone.isel_image = isel_image;
         thisone.is_expanded = is_expanded;
         tscopy.push_back( thisone );

}


// new saveone now uses ChatItemInfo pointer for 32 bit value
void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent,
                           ChatItemInfo *pchatinfo, int iimage, int isel_image, bool is_expanded) {

         TreeSaver thisone;
         thisone.id = param_id;
         thisone.parent_id = param_parent;
         if (strlen( param_text) > 99) {
                  strncpy(thisone.text, param_text, 99);
                  thisone.text[99] = (char)0;
         } else {
                  strcpy(thisone.text, param_text );
         }
         thisone.contact_id = pchatinfo->chat_id;
         thisone.hitem = hitem;
         thisone.iimage = iimage;
         thisone.isel_image = isel_image;
         thisone.is_expanded = is_expanded;
         thisone.ntype = pchatinfo->ntype; 
         thisone.msg = pchatinfo->msg; 
         //thisone.
         thisone.create_time = pchatinfo->create_time; 
         thisone.time_received = pchatinfo->time_received;
         thisone.nickname = pchatinfo->nickname;
         thisone.icon_id = pchatinfo->icon_id;

         tscopy.push_back( thisone );

}

void CSecuresockDlg::OnEndlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult) 
{
         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;

         char buffer3[200];
         if (pTVDispInfo->item.pszText == NULL) {
                  *pResult = 0;
                  return;
         }

         if (strlen(pTVDispInfo->item.pszText) > 199) {
                  AfxMessageBox("Max item text length is 200, retry");         
                  *pResult = 0;
                  return;

         }

         strcpy(buffer3, pTVDispInfo->item.pszText );

         TVITEM tv;
         BOOL result;
         tv.mask =  TVIF_TEXT ;
         tv.hItem = pTVDispInfo->item.hItem;
         tv.stateMask = 0;
         tv.pszText = buffer3;
         tv.cchTextMax = 200;

         result = m_TreeCtrl.SetItem( &tv );
         // TODO: Add your control notification handler code here
         
         *pResult = 0;
}

void CSecuresockDlg::OnKeydownTree1(NMHDR* pNMHDR, LRESULT* pResult) 
{
         TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR;

         HTREEITEM s = m_TreeCtrl.GetSelectedItem( );

         if (s == NULL) {

                  *pResult = 0;
                  return;
         }

         CString temp;
         temp.Format("pushed key:%i", pTVKeyDown->wVKey);
         //AfxMessageBox(temp);

    if (pTVKeyDown->wVKey == 46) {

                  CString x1;
                  CString x2 = gettreetext( m_TreeCtrl, s );
                  ChatItemInfo *tempci;

                  bool bIncCR = false;
                  tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( s ));

                  if (tempci->ntype == INCOMING_CONTACT_REQUEST ) 
                           bIncCR = true;


                  if (m_TreeCtrl.GetParentItem(s) == NULL) {
                           x1.Format("Are you sure you wish to remove Group %s from your contact list?\n Warning: this will remove all attached contacts to this department and you will have to re-add them later.  Continue?", x2.GetBuffer(10));
                  } else if (bIncCR) {
                           x1.Format("Deleting an Incoming Contact Request will remove the Request Message without issuing an accept or decline.  Are you sure you wish to do this?", x2.GetBuffer(0));
                           
                  } else {
                           x1.Format("Are you sure you wish to remove %s from your contact list?", x2.GetBuffer(10));
                  }

                  if ( IDYES == ::MessageBox(  this->m_hWnd,          // handle of owner window
                                                                 x1.GetBuffer(10),     // address of text in message box
                                                                 "Delete?",  // address of title of message box
                                                                 MB_YESNO          // style of message box
                                                                 ) ) {

                                    m_TreeCtrl.DeleteItem( s );

                           }

         }
         
         *pResult = 1;
}

void CSecuresockDlg::OnReturnTree1(NMHDR* pNMHDR, LRESULT* pResult) 
{
         // TODO: Add your control notification handler code here

         //CString temp;
         //temp.Format("pushed key:%i", pTVKeyDown->wVKey);
         //AfxMessageBox("hit return");
         
         *pResult = 0;
}

void CSecuresockDlg::SaveImageList()
{

         // test code for image archive
         CFile *newone = new CFile( "image_list.ids", CFile::modeWrite | CFile::modeCreate   );
         if (newone) {
                  CArchive *test = new CArchive( newone, CArchive::store  );

                  m_ImageList.Write( test );
                  delete test;
         } else {
                  AfxMessageBox("Trouble creating image archive");
         }
         delete newone;

}

void CSecuresockDlg::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{

         CString temp;
         temp.Format("pushed key:%i", nChar);
         AfxMessageBox(temp);
         
         CDialog::OnChar(nChar, nRepCnt, nFlags);
}


void CSecuresockDlg::SaveMyIcon(int ICONID) {

         // save favorite icon choice to userprop2.ids
         ofstream optionsFile2 ( "userprop2.ids", ios::out );
         if (ofstream) {
                  optionsFile2 << setw(7) << ICONID <<  '\n';
         }

}

int CSecuresockDlg::GetIconIDFromIndex(int nindex) {

         // this is my default icon, a "normal user" icon
         int iret = IDI_ICON31;

         // get reference to app (for convenience in expression below in loop)
         CSecuresockApp *ref_app;
         ref_app = (CSecuresockApp *)AfxGetApp();

         // loop thru the applications "imagevector" class, this is one of my own classes (in securesockDlg.h)
         // I use it to track the index in the cimagelist to the actual dialog ID
         // note that altho the imagelist (used by the treecontrol and elsewhere) tracks much other
         // info once you've added an image it doesn't really track the image's DIALOG_ID (e.g. the constants
         // from resource.h) -- 
         // which is at times useful to get.  hence my self-created imagevector class which relates these
         // two together (the index in the m_ImageList to the actual dialogs control ID from resource.h).

         // iterate thru the imagevector list
         for (int n=0; n < ref_app->m_imagevector.size(); n++) {

                  // when we find the index item, get it's DIALOG_ID
                  if (ref_app->m_imagevector[n].nindex == nindex) {
                           iret = ref_app->m_imagevector[n].ICONIDD;
                           break;
                  }
         }

         return (iret);

}

int CSecuresockDlg::GetIndexFromIconID(int nicon) {

         // this is my default icon, a "normal user" icon
         int iret = -1;

         // get reference to app (for convenience in expression below in loop)
         CSecuresockApp *ref_app;
         ref_app = (CSecuresockApp *)AfxGetApp();

         // loop thru the applications "imagevector" class, this is one of my own classes (in securesockDlg.h)
         // I use it to track the index in the cimagelist to the actual dialog ID
         // note that altho the imagelist (used by the treecontrol and elsewhere) tracks much other
         // info once you've added an image it doesn't really track the image's DIALOG_ID (e.g. the constants
         // from resource.h) -- 
         // which is at times useful to get.  hence my self-created imagevector class which relates these
         // two together (the index in the m_ImageList to the actual dialogs control ID from resource.h).

         // iterate thru the imagevector list
         for (int n=0; n < ref_app->m_imagevector.size(); n++) {

                  // when we find the index item, get it's DIALOG_ID
                  if (ref_app->m_imagevector[n].ICONIDD == nicon) {
                           iret = ref_app->m_imagevector[n].nindex;
                           break;
                  }
         }

         return (iret);

}

void CSecuresockDlg::PostNcDestroy() 
{
         // this is the last destruction point but class vars may not be there at this point so
         // don't save tree structure here, but save it on destroy window method below
         stop_threads();
         Sleep(120);

         CDialog::PostNcDestroy();
         //delete this;
         //PostQuitMessage(0);

}

// TraverseTree does various things, by traversing thru the whole tree control for all items
// in one case, to set flashing on or off - used with timer
// this is like GetTreeItemByCriteria somewhat but it doesn't just return the first match but
// rather traverses the whole tree and processes each tree item with the conditions in check_type
// and val (based on a call to CheckTreeItem).
void CSecuresockDlg::TraverseTree( int check_type, int val, bool bIgnoreGroups )
{

         HTREEITEM lastroot;
         HTREEITEM mynext, prevchild;
         CString mystring;

         //vector <TreeSaver> ts;                           

         //HTREEITEM firstchild;
         int last_id = 1;
         int last_contact = 101;
         int cur_root_id;
         bool firstone;
         int image, sel_image;
         bool expanded;

         HTREEITEM myroot = m_TreeCtrl.GetRootItem( );
         lastroot = myroot;

         if (myroot == NULL) {

         } else {

                  mystring = gettreetext(m_TreeCtrl, myroot);

                  //AfxMessageBox( mystring.GetBuffer(10) );
                  lastroot = myroot;
                  cur_root_id = last_id;

                  gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded );
                  if (! bIgnoreGroups )
                           CheckTreeItem( m_TreeCtrl, myroot, check_type, val);

                  bool veryfirst = true;

                  //ASSERT(0);
                  while (1) {

                           firstone = 1;
                           while (1) {

                                    if (firstone) {
                                             mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD );
                                             if (mynext == NULL) break;
                                             mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             CheckTreeItem( m_TreeCtrl, mynext, check_type, val);

                                             prevchild = mynext;

                                    } else {
                                             mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT );
                                             if (mynext == NULL) break;
                                             mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             CheckTreeItem( m_TreeCtrl, mynext, check_type, val);

                                             prevchild = mynext;

                                    }
                                    firstone = 0;

                           }
                           lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT );
                           if (lastroot == NULL) break;
                           mystring = gettreetext(m_TreeCtrl, lastroot);
                           cur_root_id = last_id;

                           //AfxMessageBox( mystring.GetBuffer(10) );
                           gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded );
                           //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, 0, image, sel_image, expanded);
                           if (! bIgnoreGroups )
                                    CheckTreeItem( m_TreeCtrl, lastroot, check_type, val);


                  }

         }
         //ASSERT(0);


}


// traverse a tree to find something, according to a type of checking and a value, return
// the related HTREEITEM if one is found
HTREEITEM CSecuresockDlg::GetTreeItemByCriteria(int check_type, int val)
{

         HTREEITEM lastroot;
         HTREEITEM mynext, prevchild;
         CString mystring;

         //vector <TreeSaver> ts;                           

         //HTREEITEM firstchild;
         int last_id = 1;
         int last_contact = 101;
         int cur_root_id;
         bool firstone;
         //int image, sel_image;
         //bool expanded;

         HTREEITEM myroot = m_TreeCtrl.GetRootItem( );
         lastroot = myroot;

         if (myroot == NULL) {

         } else {

                  //mystring = gettreetext(m_TreeCtrl, myroot);

                  if ( CheckTreeItem( m_TreeCtrl, myroot, check_type, val) )
                           return myroot;

                  //AfxMessageBox( mystring.GetBuffer(10) );
                  lastroot = myroot;
                  cur_root_id = last_id;

                  //gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded );
                  bool veryfirst = true;

                  //ASSERT(0);
                  while (1) {

                           firstone = 1;
                           while (1) {

                                    if (firstone) {
                                             mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD );
                                             if (mynext == NULL) break;
                                             if ( CheckTreeItem( m_TreeCtrl, mynext, check_type, val) )
                                                      return mynext;

                                             //mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             prevchild = mynext;

                                    } else {
                                             mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT );
                                             if (mynext == NULL) break;
                                             if ( CheckTreeItem( m_TreeCtrl, mynext, check_type, val) )
                                                      return mynext;
                                             //mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             prevchild = mynext;

                                    }
                                    firstone = 0;

                           }
                           lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT );
                           if (lastroot == NULL) break;
                           if ( CheckTreeItem( m_TreeCtrl, lastroot, check_type, val) )
                                    return lastroot;
                           //mystring = gettreetext(m_TreeCtrl, lastroot);
                           cur_root_id = last_id;

                           //AfxMessageBox( mystring.GetBuffer(10) );
                           //gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded );
                           //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, 0, image, sel_image, expanded);


                  }

         }
         //ASSERT(0);
         return (HTREEITEM)0;

}

// traverse a tree to find something, according to a type of checking and a value, return
// the related HTREEITEM if one is found
HTREEITEM CSecuresockDlg::GetGroupLabels(bool bGroup)
{

         HTREEITEM lastroot;
         HTREEITEM mynext, prevchild;
         CString mystring;

         //vector <TreeSaver> ts;                           

         //vector<TreeGroupInfo> tgiVector;
         tgiVector.clear();

         //tgiVector

         //HTREEITEM firstchild;
         int last_id = 1;
         int last_contact = 101;
         int cur_root_id;
         bool firstone;
         //int image, sel_image;
         //bool expanded;

         char buffer[256];

         HTREEITEM myroot = m_TreeCtrl.GetRootItem( );
         lastroot = myroot;

         if (myroot == NULL) {

         } else {


                  if (! m_TreeCtrl.GetLabelText(myroot, buffer, 255) ) {
                           AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl");
                  } else {
                           if ( NotSystemGroup(myroot) )
                                    tgiVector.push_back( TreeGroupInfo( buffer, myroot ) );
                  }

                  //AfxMessageBox( mystring.GetBuffer(10) );
                  lastroot = myroot;
                  cur_root_id = last_id;

                  //gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded );
                  bool veryfirst = true;

                  while (1) {

                           firstone = 1;
                           while (1) {

                                    if (firstone) {
                                             mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD );
                                             if (mynext == NULL) break;
                                             if (! bGroup) {
                                                      if (! m_TreeCtrl.GetLabelText(mynext, buffer, 255) ) {
                                                               AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl");
                                                      } else {
                                                               tgiVector.push_back( TreeGroupInfo( buffer, mynext ) );
                                                      }
                                             }

                                             //mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             prevchild = mynext;

                                    } else {
                                             mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT );
                                             if (mynext == NULL) break;
                                             if (! bGroup ) {
                                                      if (! m_TreeCtrl.GetLabelText(mynext, buffer, 255) ) {
                                                               AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl");
                                                      } else {
                                                               tgiVector.push_back( TreeGroupInfo( buffer, mynext ) );
                                                      }
                                             }
                                             //mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             prevchild = mynext;

                                    }
                                    firstone = 0;

                           }
                           lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT );
                           if (lastroot == NULL) break;

                           if (! m_TreeCtrl.GetLabelText(lastroot, buffer, 255) ) {
                                    AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl");
                           } else {
                                    if ( NotSystemGroup(lastroot) )
                                             tgiVector.push_back( TreeGroupInfo( buffer, lastroot ) );
                           }

                           //mystring = gettreetext(m_TreeCtrl, lastroot);
                           cur_root_id = last_id;

                           //AfxMessageBox( mystring.GetBuffer(10) );
                           //gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded );
                           //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, 0, image, sel_image, expanded);


                  }

         }
         //ASSERT(0);
         return (HTREEITEM)0;

}

bool CSecuresockDlg::NotSystemGroup(HTREEITEM thishitem)
{
         ChatItemInfo *citemp;
         bool bRet;
         citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem ));
         bRet = (citemp->ntype != SYSTEM_GROUP && citemp->ntype != PENDING_CONTACTS_GROUP );
         return bRet;

}

// see if this tree item or it's related info match a certain type of lookup and value
bool CSecuresockDlg::CheckTreeItem(CTreeCtrl &reftree, HTREEITEM &hitem, int check_type, int val)
{
         bool bRet = false;
         ChatItemInfo *citemp;
         int x;
         // check for a specific chat_id
         if (check_type == CSecuresockDlg::CHAT_ID_LOOKUP) {
                  citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem ));
                  if ( val == citemp->chat_id   ) {
                           bRet = true;
                  }
         }

         // check for a specific type, like system lookup
         else if (check_type == CSecuresockDlg::TYPE_LOOKUP) {
                  citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem ));
                  if ( val == citemp->ntype   ) {
                           bRet = true;
                  }
         }

         else if (check_type == CSecuresockDlg::ONLINE_STATUS_MSG_LOOKUP) {

                  citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem ));
                  if ( citemp->ntype == CHAT_CONTACT ) {
                           online_chk_vector.push_back( TreeStatusHelper( hitem, citemp->chat_id) );
                           TRACE("hit again\n");
                           TRACE("%s", citemp->msg.GetBuffer(0) );
                           bRet = true;
                  }

         }

         // check for any pending messages for this chat_id, note this is somewhat of an odd
         // call since it actually causes the flashing also, so this is more CheckTreeItemandFlash
         // when called in this case (val is also ignored, since the chat_id is checked against a 
         // message list vector of unprocessed messages which is a part of pSockApp).

         // split this into two cases, one gets whether or not there are pending messages and if so
         // sets a citemp value (bPendingMsgs) to true. 

         // BLINK_UPDATE_CALL handles the actual update and executes every half second
         else if (check_type == CSecuresockDlg::PENDING_MSG_LOOKUP) {

                  citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem ));
                  if ( citemp->ntype != CHAT_CONTACT )
                           return false;

                  int new_icon;
                  bRet = pSockApp->bPendingMsgsByChatID( citemp->chat_id, &new_icon );

                  if (bRet) {
                           if (new_icon != citemp->icon_id && new_icon != 0) {
                                    citemp->icon_id = new_icon;
                           }
                  }

                  TRACE("checking msg for %lu\n", citemp->chat_id );

                  citemp->bPendingMsgs = bRet;

         }

         else if (check_type == BLINK_UPDATE_CALL) {

                  citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem ));
                  bRet = citemp->bPendingMsgs;
                  if ( citemp->ntype != CHAT_CONTACT )
                           return false;

                  if (!bRet) {

                           TRACE("no match found\n");

                           // if message was handled when showing invisible icon, need to set back to real icon
                           if (m_TreeCtrl.GetImageIndex( hitem ) == GetIndexFromIconID(IDI_ICON115) ) {

                                    TRACE("fixing lost in down state bug\n");
                                    x = GetIndexFromIconID( citemp->icon_id );
                                    m_TreeCtrl.SetImagesByIndex( hitem, x); // citemp->icon_id

                           }

                  } else  {

                           if (bUpTimer) {
                                    // icon115 aka "the empty icon"
                                    x = GetIndexFromIconID(IDI_ICON115);
                                    m_TreeCtrl.SetImagesByIndex( hitem, x);
                                    //m_TreeCtrl.SetItemOverlayIndex( hitem, 0);

                           } else {
                                    x = GetIndexFromIconID( citemp->icon_id );

                                    // we can't really put up a messagebox on this bug so set everything to kyle and they will
                                    // know there is a bug
                                    if (x == - 1) {
                                             TRACE("BUG: this icon_id not found in index list\n");
                                             x = 2;
                                    }

                                    m_TreeCtrl.SetImagesByIndex( hitem, x); // citemp->icon_id
                           }
                  }

         }

         return bRet;

}

// saves tree structure to treefile.ids via standard iostream stuff
void CSecuresockDlg::SaveTreeFont(void)
{

         CString temp;
         temp.Format("tf_u%lu_font.dra", pSockApp->my_controls.chat_id);

         ofstream myOutFile2( temp.GetBuffer(0), ios::out );
         //myOutFile2 << this->tree_lf;

         if (myOutFile2) {
                  stream_stuff::write_long2( myOutFile2, (DWORD)(m_TreeCtrl.crForeColor));
                  CString temp;
                  temp.Format("%lu", (DWORD)(m_TreeCtrl.crForeColor) );
                  //AfxMessageBox( temp );

                  stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfHeight);
                  stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfWidth);
                  stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfEscapement);
                  stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfOrientation);
                  stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfWeight);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfItalic);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfUnderline);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfStrikeOut);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfCharSet);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfOutPrecision);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfClipPrecision);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfQuality);
                  stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfPitchAndFamily);
         } else {
                  AfxMessageBox("Trouble opening tree font save file");
         }

         // one longer for paranoia and to avoid bad assignment to CString
         // put the lfFaceName into a CString and use the normal writeCString helper function
         char buffer[LF_FACESIZE+1];
         buffer[LF_FACESIZE] = (char)0;
         ::lstrcpyn(buffer, this->tree_lf.lfFaceName, LF_FACESIZE);
         temp = buffer;
         stream_stuff::writeCString( myOutFile2, temp );

         myOutFile2.close();


}

// load in tree font (if they've set it to other than default) -  for current user
bool CSecuresockDlg::GetTreeFontFromFile(void)
{

         CString temp;
         temp.Format("tf_u%lu_font.dra", pSockApp->my_controls.chat_id);
         CFile *myfile = new CFile();
         COLORREF crValue;
         crValue = RGB(0,0,0);

         try {
                  myfile->Open( temp.GetBuffer(0), CFile::modeRead );

         } catch (...) { } // avoid runtime errors most likely one is just file doesn't exist which will cause
                                             // a runtime if we don't catch it here

         if (myfile->m_hFile != (UINT)CFile::hFileNull) {

                  //long ltemp;
                  bool bokay = false;
                  while (1) {

                           unsigned long ultemp;
                           stream_stuff::read_long2(myfile, &ultemp);
                           crValue = (COLORREF)ultemp;

                           if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfHeight) ) ) { break; }
                           if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfWidth) ) ) { break; }
                           if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfEscapement) )  ) { break; }
                           if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfOrientation) ) ) { break; }
                           if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfWeight) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfItalic) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfUnderline) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfStrikeOut) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfCharSet) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfOutPrecision) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfClipPrecision) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfQuality) ) ) { break; }
                           if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfPitchAndFamily) ) ) { break; }
                           bokay = true;

                           break;
                  }

                  if (bokay) {

                           char buffer[LF_FACESIZE+1];
                           char size_buffer[6];
                           int num_read = myfile->Read(size_buffer, 4);
                           size_buffer[num_read] = 0;

                           int itextlen = atoi(size_buffer);
                           if (itextlen > LF_FACESIZE) {
                                    itextlen = LF_FACESIZE;
                           }
                           // skip comma
                           myfile->Read(size_buffer, 1);

                           num_read = myfile->Read(buffer, itextlen);
                           buffer[num_read] = (char)0;
                           ::lstrcpy(this->tree_lf.lfFaceName, buffer);

                  }
                  myfile->Close();

         } else {
                  ::ZeroMemory( &tree_lf, sizeof(tree_lf) );
                  tree_lf.lfHeight = -11;
                  tree_lf.lfWeight = 700;
                  tree_lf.lfOutPrecision = 3;
                  tree_lf.lfClipPrecision = 2;
                  tree_lf.lfQuality = 1;
                  tree_lf.lfPitchAndFamily = 34;
                  ::lstrcpy(tree_lf.lfFaceName, "Arial");
                  crValue = RGB(0,0,0);
         }

         delete myfile;

         CHOOSEFONT chf;

         HDC hDC;

         hDC = ::GetDC (this->m_hWnd);
         chf.hDC = CreateCompatibleDC (hDC);
         ::ReleaseDC (this->m_hWnd, hDC);
         chf.lStructSize = sizeof (CHOOSEFONT);
         chf.hwndOwner = this->m_hWnd;
         chf.lpLogFont = &tree_lf;
         chf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ; 
         chf.rgbColors = RGB (0, 0, 0);
         chf.lCustData = 0;
         chf.hInstance = AfxGetInstanceHandle();
         chf.lpszStyle = (LPTSTR)NULL;
         chf.nFontType = SCREEN_FONTTYPE;
         chf.nSizeMin = 0;
         chf.nSizeMax = 0;

         if (m_ptreefont)
                  delete m_ptreefont;

         m_ptreefont = new CFont();
         m_ptreefont->CreateFontIndirect(&tree_lf);
         bTreeFontChanged = true;
         m_TreeCtrl.SetFont(m_ptreefont);

         m_TreeCtrl.crForeColor = crValue;

         return true;

         /* LONG lfHeight; 
   LONG lfWidth; 
   LONG lfEscapement; 
   LONG lfOrientation; 
   LONG lfWeight; 
   BYTE lfItalic; 
   BYTE lfUnderline; 
   BYTE lfStrikeOut; 
   BYTE lfCharSet; 
   BYTE lfOutPrecision; 
   BYTE lfClipPrecision; 
   BYTE lfQuality; 
   BYTE lfPitchAndFamily; 
   TCHAR lfFaceName[LF_FACESIZE]; 

         /*
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfItalic);
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfUnderline);
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfStrikeOut);
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfCharSet);
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfOutPrecision);
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfClipPrecision);
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfQuality);
         stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfPitchAndFamily);

         // one longer for paranoia and to avoid bad assignment to CString
         // put the lfFaceName into a CString and use the normal writeCString helper function
         char buffer[LF_FACESIZE+1];
         buffer[LF_FACESIZE] = (char)0;
         ::lstrcpyn(buffer, this->tree_lf.lfFaceName, LF_FACESIZE);
         temp = buffer;
         stream_stuff::writeCString( myOutFile2, temp );
         */

}

// saves tree structure to treefile.ids via standard iostream stuff
void CSecuresockDlg::SaveTree()
{

         HTREEITEM lastroot;
         HTREEITEM mynext, prevchild;
         CString mystring;

         vector <TreeSaver> ts;                           

         //HTREEITEM firstchild;
         int last_id = 1;
         int last_contact = 101;
         int cur_root_id;
         bool firstone;
         int image, sel_image;
         bool expanded;
         //unsigned long chat_id;
         ChatItemInfo *tempci;
         //tempci->msg = "";
         //tempci->ntype = UNKNOWN;
         //tempci->create_time = "";

         HTREEITEM myroot = m_TreeCtrl.GetRootItem( );
         lastroot = myroot;

         if (myroot == NULL) {

         } else {

                  mystring = gettreetext(m_TreeCtrl, myroot);

                  //AfxMessageBox( mystring.GetBuffer(10) );
                  lastroot = myroot;
                  cur_root_id = last_id;

                  gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded );
                  //tempci->chat_id = m_TreeCtrl.GetItemData( myroot);
                  tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( myroot));
                  if (! tempci )
                           ASSERT(0);

                  //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, chat_id, image, sel_image, expanded);

                  // save info to a vector via SaveOne, then later use this vector to write to the file
                  SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, tempci, image, sel_image, expanded);

                  //ASSERT(0);
                  while (1) {

                           firstone = 1;
                           while (1) {

                                    if (firstone) {
                                             mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD );
                                             if (mynext == NULL) break;
                                             mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             //tempci->chat_id = m_TreeCtrl.GetItemData( mynext);
                                             tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( mynext));
                                             //SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, chat_id, image, sel_image);
                                             SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, tempci, image, sel_image);
                                             prevchild = mynext;

                                    } else {
                                             mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT );
                                             if (mynext == NULL) break;
                                             mystring = gettreetext(m_TreeCtrl, mynext);
                                             //AfxMessageBox( mystring.GetBuffer(10) );
                                             gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded );
                                             //tempci->chat_id = m_TreeCtrl.GetItemData( mynext);
                                             tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( mynext));
                                             //SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, chat_id, image, sel_image);
                                             SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, tempci, image, sel_image);
                                             prevchild = mynext;

                                    }
                                    firstone = 0;

                           }
                           lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT );
                           if (lastroot == NULL) break;
                           mystring = gettreetext(m_TreeCtrl, lastroot);
                           cur_root_id = last_id;

                           //AfxMessageBox( mystring.GetBuffer(10) );
                           gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded );
                           //tempci->chat_id = m_TreeCtrl.GetItemData( lastroot);
                           tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( lastroot));
                           //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, chat_id, image, sel_image, expanded);
                           SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, tempci, image, sel_image, expanded);


                  }

         }
         //ASSERT(0);

         //CString curdir;
         //::GetCurrentDirectory(MAX_PATH, curdir.GetBuffer(MAX_PATH));
         //curdir.ReleaseBuffer();
         //AfxMessageBox( curdir.GetBuffer(MAX_PATH));

         CString temp;
         temp.Format("tf_u%lu.dra", pSockApp->my_controls.chat_id);

         ofstream myOutFile2( temp.GetBuffer(0), ios::out );

         myOutFile2 << "y";

         char buffer[256];
         DWORD id, parent_id, contact_id, iimage, isel_image, is_expanded;
         int textlen;
         int i;

         for (i=0; i<ts.size(); i++) {

                  id = ts[i].id;
                  parent_id = ts[i].parent_id;
                  contact_id = ts[i].contact_id;
                  iimage = ts[i].iimage;
                  isel_image = ts[i].isel_image;
                  is_expanded = ts[i].is_expanded;

                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].id));
                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].parent_id));
                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].contact_id));
                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].iimage));
                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].isel_image));
                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].is_expanded));

                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].ntype) ) ;
                  stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].icon_id) );

                  textlen = strlen(ts[i].text);
                  myOutFile2 << setw(4) << strlen(ts[i].text) ;
                  myOutFile2 << ",";
                  myOutFile2 << ts[i].text ;
                  strcpy( buffer, ts[i].text); 

                  stream_stuff::writeCString( myOutFile2, ts[i].msg );
                  /*
                  char *ctemp;
                  textlen = strlen(ts[i].msg.GetBuffer(0) );
                  myOutFile2 << setw(4) << textlen ;
                  myOutFile2 << ",";
                  ctemp = ts[i].msg.GetBuffer(0);
                  myOutFile2 << ctemp;
                  strcpy( buffer, ts[i].msg.GetBuffer(0)); */

                  stream_stuff::writeCString( myOutFile2, ts[i].create_time);

                  /*
                  textlen = strlen(ts[i].create_time.GetBuffer(0) );
                  myOutFile2 << setw(4) << textlen ;
                  myOutFile2 << ",";
                  ctemp = ts[i].create_time.GetBuffer(0);
                  myOutFile2 << ctemp ;
                  strcpy( buffer, ts[i].create_time.GetBuffer(0) ); */

                  stream_stuff::writeCString( myOutFile2, ts[i].time_received);
                  stream_stuff::writeCString( myOutFile2, ts[i].nickname);

                  /*
                  enum TypeInfo { UNKNOWN = 0, CHAT_CONTACT, GROUP, SYSTEM_MSG };
                  TypeInfo ntype;
                  CString msg;
                  CString create_time; */

                  myOutFile2 << '\n';

         }

         //m_TreeCtrl.Detach();

         //if (ts.size() == 0) AfxMessageBox("No elements");

}

// reads in tree structure from file treefile.ids via standard iostream stuff
void CSecuresockDlg::BuildTreeFromFile(CTreeCtrl &piTree, CFile *myfile, bool newformat) {

         CString outstring; 
         char buffer[256];
         char msg[256];
         char create_time[256];
         char time_received[256];
         char nickname[256];

         //ASSERT(0);
         /*
         ifs.seekg(0, ios::end);
         long pos = ifs.tellg();
         ifs.seekg(0); */
         unsigned long length = 0;
         int num_read;
         bool bNewFormat;
         ChatItemInfo *tempci;
         ChatItemInfo *newci;

         if (myfile) {
                  length = myfile->GetLength();
                  myfile->Read(buffer, 1);
                  bNewFormat = ! (buffer[0] == 'x');

         }

         if (! myfile || length < 10) {

                  HTREEITEM system = piTree.InsertItem( "System Notifications", 29, 29, TVI_ROOT, TVI_LAST);

                  CString string_time = GetTimeString();

                  newci = new ChatItemInfo(0L, SYSTEM_GROUP, 
                                             CString("Basic System Notifications Group"), string_time );

                  piTree.SetItemData( system, (DWORD)newci );

                  add_ptr_to_garbage(newci, "ChatItemInfo");

                  newci = NULL;
                  newci = new ChatItemInfo(0L, GROUP, 
                                             CString("Contacts Group"), string_time );

                  HTREEITEM work = piTree.InsertItem( "Work Contacts", 27, 27, TVI_ROOT, TVI_LAST);
                  piTree.SetItemData( work, (DWORD)newci );

                  add_ptr_to_garbage(newci, "ChatItemInfo");

                  newci = NULL;
                  newci = new ChatItemInfo(0L, GROUP, 
                                             CString("Contacts Group"), string_time );

                  HTREEITEM personal = piTree.InsertItem( "Personal Contacts", 28, 28, TVI_ROOT, TVI_LAST);
                  piTree.SetItemData( personal, (DWORD)newci );

                  add_ptr_to_garbage(newci, "ChatItemInfo");

         } else {

                  unsigned long id, contact_id, parent_id, iimage, isel_image;
                  unsigned long ntype;
                  int itextlen;
                  char text[256];
                  unsigned long long_bool;
                  bool is_expanded;
                  char buffer[200];
                  unsigned long icon_id;

                  HTREEITEM last_root;
                  stream_stuff::eof = false;

                  while ( ! stream_stuff::eof ) {

                           id = 0;

                           stream_stuff::warning = false;
                           stream_stuff::read_long2(myfile, &id);
                           stream_stuff::warning = true;

                           // eof is failing on last record (at least at that point) so this is a kludge but effective for now
                           if (stream_stuff::eof ) {
                                    break;
                           }

                           stream_stuff::read_long2(myfile, &parent_id);
                           if (stream_stuff::eof ) {
                                    break;
                           }
                           stream_stuff::read_long2(myfile, &contact_id);
                           if (stream_stuff::eof ) {
                                    break;
                           }
                           stream_stuff::read_long2(myfile, &iimage);
                           if (stream_stuff::eof ) {
                                    break;
                           }
                           stream_stuff::read_long2(myfile, &isel_image);
                           if (stream_stuff::eof ) {
                                    break;
                           }
                           stream_stuff::read_long2(myfile, &long_bool);
                           if (stream_stuff::eof ) {
                                    break;
                           }

                           is_expanded = !(long_bool == 0);

                           stream_stuff::read_long2(myfile, &ntype);
                           if (stream_stuff::eof ) {
                                    break;
                           }

                           stream_stuff::read_long2(myfile, &icon_id);
                           if (stream_stuff::eof ) {
                                    break;
                           }

                           num_read = myfile->Read(buffer, 4);
                           buffer[num_read] = 0;

                           itextlen = atoi(buffer);
                           myfile->Read(buffer, 1);

                           num_read = myfile->Read(text, itextlen);
                           text[num_read] = (char)0;


                           num_read = myfile->Read(buffer, 4);
                           buffer[num_read] = 0;

                           itextlen = atoi(buffer);
                           myfile->Read(buffer, 1);

                           num_read = myfile->Read(msg, itextlen);
                           msg[num_read] = (char)0;

                           num_read = myfile->Read(buffer, 4);
                           buffer[num_read] = 0;

                           itextlen = atoi(buffer);
                           myfile->Read(buffer, 1);

                           num_read = myfile->Read(create_time, itextlen);
                           create_time[num_read] = (char)0;

                           //stream_stuff::
                           num_read = myfile->Read(buffer, 4);
                           buffer[num_read] = 0;

                           itextlen = atoi(buffer);
                           myfile->Read(buffer, 1);

                           num_read = myfile->Read(time_received, itextlen);
                           time_received[num_read] = (char)0;

                           num_read = myfile->Read(buffer, 4);
                           buffer[num_read] = 0;

                           itextlen = atoi(buffer);
                           myfile->Read(buffer, 1);

                           num_read = myfile->Read(nickname, itextlen);
                           nickname[num_read] = (char)0;

                           // read CRLF now
                           myfile->Read(buffer, 2);

                           // if parent item
                           if (parent_id == 0) {

                                    last_root = piTree.InsertItem( text, iimage, isel_image, TVI_ROOT, TVI_LAST);

                                    if (bNewFormat ) {

                                             tempci = NULL;
                                             ChatItemInfo *tempci = new ChatItemInfo;
                                             add_ptr_to_garbage(tempci, "ChatItemInfo");

                                             tempci->chat_id = contact_id;
                                             tempci->msg = msg;
                                             tempci->create_time = create_time;
                                             tempci->time_received = time_received;
                                             tempci->nickname = nickname;
                                             tempci->ntype = ChatItemInfo::translate(ntype);
                                             tempci->icon_id = (int)icon_id;
                                             piTree.SetItemData( last_root, (DWORD)tempci );


                                    } else {
                                             piTree.SetItemData( last_root, contact_id );
                                    }
                                    if (last_root && is_expanded) {
                                             //ASSERT(0);
                                             settreeexpanded( piTree, last_root, is_expanded );
                                    }

                           } else {

                                    int iconindex;
                                    if (icon_id != 0) {
                                             iconindex = GetIndexFromIconID( (int)icon_id );
                                             if (iconindex != -1 ) {
                                                      iimage = iconindex;
                                                      isel_image = iconindex;
                                             }
                                    } 

                                    HTREEITEM newone = piTree.InsertItem( text, iimage, isel_image, last_root);
                                    if (! bNewFormat) {
                                             piTree.SetItemData( newone, contact_id );
                                    } else {
                                             tempci = NULL;
                                             ChatItemInfo *tempci = new ChatItemInfo;
                                             add_ptr_to_garbage(tempci, "ChatItemInfo");

                                             tempci->chat_id = contact_id;
                                             tempci->msg = msg;
                                             tempci->create_time = create_time;
                                             tempci->ntype = ChatItemInfo::translate(ntype);
                                             tempci->time_received = time_received;
                                             tempci->nickname = nickname;
                                             tempci->icon_id = (int)icon_id;
                                             piTree.SetItemData( newone, (DWORD)tempci );
                                    }

                           }

                  }

         }
}

BOOL CSecuresockDlg::DestroyWindow() 
{
         //MessageBox("called");

         if (fully_loaded)
                  SaveTree();

         if (bTreeFontChanged) {
                  SaveTreeFont();
         }

         // close the taskbar icon on main dialog shutdown
         NOTIFYICONDATA nid;
         nid.cbSize = sizeof(nid);
         nid.hWnd = this->m_hWnd;
         nid.uID = 1;
         nid.uFlags = 0;
         Shell_NotifyIcon(NIM_DELETE, &nid);

         KillTimer(1);
         KillTimer(2);
         KillTimer(3);
         //KillTimer(4);

         // turn off multimedia timer also used to make sure blinking isn't weird (normal timers aren't reliable
         // and act weird) note this causes a performance hit but I think if we assume systems with modern processors
         // and ram this shouldn't be a big issue.
         if (m_n_mmtimer_id != 0) {
                  timeKillEvent(m_n_mmtimer_id);
                  timeEndPeriod(500);
         }

         return CDialog::DestroyWindow();
}

void CSecuresockDlg::OnMypersonalbutton() 
{

         DWORD dp = ::GetMessagePos();
         CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) );
         //CTreeCtrl piTree;
         //piTree.Attach( GetDlgItem(IDC_TREE1)->m_hWnd);

         //m_TreeCtrl.ScreenToClient (&pt);
         UINT flags = NULL;

         //char buffer[20];

         CMenu menu;
         menu.LoadMenu(IDR_MENU1);
         CMenu *x;
         x = menu.GetSubMenu(2);
         //x->AppendMenu(MF_STRING, WM_USER + 301, "appended item");
         CMenu users_menu;
         users_menu.CreatePopupMenu();

         int i;
         int ncnt = 0;
         for (i=0;i<         pSockApp->users_array.size(); i++) {
                  users_menu.AppendMenu(MF_STRING, WM_USER + 300 + ncnt++, pSockApp->users_array[i].nickname.GetBuffer(0) );
                  if (pSockApp->users_array[i].chat_id == pSockApp->my_controls.chat_id) {

                           users_menu.CheckMenuItem(WM_USER + 300 + ncnt - 1, MF_CHECKED);

                  }

         }

         x->InsertMenu(3, MF_BYPOSITION | MF_POPUP, (unsigned int)(users_menu.m_hMenu), "Change User");

         CRect rect;
         GetWindowRect(rect);

         //CPoint y;
         //::GetCursorPos(&y);
         //ScreenToClient (&y);
         CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) );
         int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect );

         if (ncmd >= WM_USER + 300 && ncmd <= WM_USER + 399 ) {

                  SwitchUsers(ncmd - (WM_USER + 300) );
                  return;

         }

         if (ncmd == ID_MYPROPERTIES ) {


                  //pSockApp->ShowMessageList();

                  CMyPropSheet testprop(IDS_MYPROPS, this, 0) ;

                  testprop.m_psh.dwFlags |=  PSH_NOAPPLYNOW ;

                  CPersP1 p1;
                  CPersP3 p3;
                  CPers_P2 p2;
                  CPersP4 p4;


                  p1.m_psp.dwFlags &= (~PSH_HASHELP);
                  p2.m_psp.dwFlags &= (~PSH_HASHELP);
                  p3.m_psp.dwFlags &= (~PSH_HASHELP);
                  p4.m_psp.dwFlags &= (~PSH_HASHELP);

                  testprop.AddPage(&p1);
                  testprop.AddPage(&p2);
                  testprop.AddPage(&p3);
                  testprop.AddPage(&p4);
                  testprop.newtitle.Format("Change My Properties [Chat ID %lu]", pSockApp->my_controls.chat_id);

                  int response = testprop.DoModal();
                  if (response == IDOK) {

                           //MessageBox("saving");
                           CSecuresockApp *pSockApp;
                           pSockApp = (CSecuresockApp *)AfxGetApp();
                           CString msg1;
                           msg1 = "Saving Settings to Server";
                           CMiscStuff::WaitWindow( msg1, this );
                           pSockApp->SavePropsToFile();         

                           // save properties to web
                           pSockApp->my_controls.UpdateURLwithInfo();
                           //Sleep(1000);

                           CMiscStuff::ClearWaitWindow();


                  }


         }

         if (ncmd == ID_CHECKLATENCY) {

                  GetLatency() ;

         }

         if (ncmd == ID_CHANGE_ICON1) {

                  IconChooser icd;
                  icd.bGroupIcon = false;

                  // the postncdestroy method in IconChooser will delete this memory allocated
                  // here so this isn't a real memory leak
                  char *newptr = new char[100];
                  strcpy(newptr, "Select Your Personal Chat Icon");

                  // set the caption for the chooser dialog, uses soft logic if not set then uses
                  // a default value (this dialog is called from other places than registration)
                  icd.title = newptr; // this isn't a memory leak the dialog itself will release the
                                             // memory via delete [] for this pointer
                  icd.m_signup = 0; // registration level call (screen can be called from different places
                                     // in the program this flag helps to differentiate
                  icd.m_me = 1;

                  int myresult = icd.DoModal();

                  int ICONIDD;

                  if (! pSockApp->m_canceled && icd.ICON_IDD != -1 && myresult == IDOK) {

                           ICONIDD = icd.ICON_IDD;
                           HICON hIcon;

                           hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                                                MAKEINTRESOURCE(ICONIDD));
                           m_mypersonalbutton.SetIcon( hIcon );         

                           CString temp;
                           temp.Format("%i", ICONIDD);
                           if (! pSockApp->my_controls.SetStringByTokenName("user_icon", temp))
                                    AfxMessageBox("trouble setting user_icon in properties");

                           m_my_personal_icon_id = ICONIDD;

                           pSockApp->SavePropsToFile();

                  }
                  // save favorite icon choice to userprop2.ids
                  //ofstream optionsFile2 ( "userprop2.ids", ios::out );
                  //optionsFile2 << setw(7) << ICONIDD <<  '\n';

                  // save this to a class variable also so we can keep track of the last personal icon
                  // add a save function to the destructor

         }

         if (ncmd == ID_OPTION1_ADDNEWDEPT) {

                  HTREEITEM newone;
                  m_ilast_dept_insert_icon++;
                  // alternate between three types of insert icons for departments (for now)
                  if (m_ilast_dept_insert_icon > 28)
                           m_ilast_dept_insert_icon = 26;

                  newone = m_TreeCtrl.InsertItem( "New Group", m_ilast_dept_insert_icon, 
                                                               m_ilast_dept_insert_icon, TVI_ROOT, TVI_LAST);

                  ChatItemInfo *citemp;
                  citemp = new ChatItemInfo;
                  citemp->chat_id = 0;
                  citemp->ntype = GROUP;
                  citemp->create_time = GetTimeString() ;
                  citemp->msg = "Contact Group";
                  add_ptr_to_garbage(citemp, "ChatItemInfo");

                  m_TreeCtrl.SetItemData( newone, (DWORD)citemp );

                  //m_TreeCtrl.SetItemData( newone, 0 );

                  m_TreeCtrl.EditLabel(newone);

         }

         if (ncmd == ID_ADDUSER) {

                  if (!SignupUser( false ) )  {
                           AfxMessageBox("Adding New User Canceled");
                  } else {
                           m_TreeCtrl.DeleteAllItems();
                           // if treeFile is NULL this is okay it recreates a generic tree
                           //ifstream failure("impossible_name_234asdfaw34rfs");
                           BuildTreeFromFile(m_TreeCtrl, NULL, true);
                           COLORREF cref = RGB( 255, 255, 255);

                           CString temp;
                           temp.Format("%lu", (unsigned long)cref);

                           m_TreeCtrl.SetBkColor(cref) ;
                           if (! pSockApp->my_controls.SetStringByTokenName("tree_back_color", temp)) {
                                    AfxMessageBox("trouble saving tree backcolor in properties");
                           } else {
                                    pSockApp->SavePropsToFile();
                           }

                  }


         }

         if (ncmd == ID_TREEBKCOLOR) {

                  /*
                  CMySocket newconn("www.drakis.com");
                  CString response = newconn.GetFileAsString("/cgi-bin/check_in.pl?my_scno=101",
                           "www.drakis.com");

                  MB( response );
                  return; */

                  //this is retarded but there is no getbackground color function calling set
                  // gets it's value, here we set it to white then quickly set it back
                  COLORREF old = m_TreeCtrl.GetBkColor(); 

                  CMyColorDialog x1(old, CC_RGBINIT );
                  x1.m_cc.lStructSize = sizeof( CHOOSECOLOR );
                  x1.m_cc.Flags = x1.m_cc.Flags | CC_FULLOPEN ;
                  x1.SetWindowCaption("Select Tree Background Color");

                  if (x1.DoModal() == IDOK ) {

                           COLORREF x2 = x1.GetColor();
                            m_TreeCtrl.SetBkColor(x2) ;

                           CString temp;
                           temp.Format("%lu", (unsigned long)x2);

                           if (! pSockApp->my_controls.SetStringByTokenName("tree_back_color", temp)) {
                                    AfxMessageBox("trouble saving tree backcolor in properties");
                           } else {
                                    pSockApp->SavePropsToFile();
                           }

                  }

         }

         
}

void CSecuresockDlg::OnShowWindow(BOOL bShow, UINT nStatus) 
{
         //char buffer[20];
         //_itoa(nStatus, buffer, 10);
         //AfxMessageBox(buffer);
         CDialog::OnShowWindow(bShow, nStatus);

         // TODO: Add your message handler code here
         
}

BOOL CSecuresockDlg::OnHelpInfo(HELPINFO* pHelpInfo) 
{
         // TODO: Add your message handler code here and/or call default
         //AfxMessageBox("they hit f1");
         return CDialog::OnHelpInfo(pHelpInfo);
}

BOOL CSecuresockDlg::OnCommand(WPARAM wParam, LPARAM lParam) 
{
         // TODO: Add your specialized code here and/or call the base class
         /*AfxMessageBox("on command called");
         CString out;
         out.Format("%li:%li", wParam, lParam);
         AfxMessageBox(out); */
         if (lParam == WM_TRAY_IDD)
                  AfxMessageBox("c");

         if (wParam == WM_TRAY_IDD)
                  AfxMessageBox("d");

         return CDialog::OnCommand(wParam, lParam);
}

BOOL CSecuresockDlg::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
{
         // TODO: Add your specialized code here and/or call the base class

         if (nID == WM_TRAY_IDD) 
                  AfxMessageBox("nID");

         if (nCode == WM_TRAY_IDD)
                  AfxMessageBox("nCode");
         
         return CDialog::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}



BOOL CSecuresockDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
         // TODO: Add your specialized code here and/or call the base class
         //AfxMessageBox("notify");
         
         return CDialog::OnNotify(wParam, lParam, pResult);
}

BOOL CSecuresockDlg::PreCreateWindow(CREATESTRUCT& cs) 
{
         // TODO: Add your specialized code here and/or call the base class
         AfxMessageBox("precreate window");

         cs.style |= WS_VISIBLE;
         //cs.style |= WS_EX_TOOLWINDOW;
         cs.dwExStyle &= (~WS_EX_APPWINDOW);
         cs.dwExStyle |= WS_EX_TOOLWINDOW;
         cs.dwExStyle |= WS_EX_PALETTEWINDOW ;
         
         
         return CDialog::PreCreateWindow(cs);
}
/*
The rules the taskbar uses to decide whether a button should be shown for a window are 
really quite simple, but are not well documented. When you create a window, the taskbar 
examines the window’s extended style to see if either the WS_EX_APPWINDOW (defined as 
0x00040000) or WS_EX_TOOLWINDOW (defined as 0x00000080) style is turned on. If 
WS_EX_APPWINDOW is turned on, the taskbar shows a button for the window, and if 
WS_EX_ TOOLWINDOW is turned on, the taskbar does not show a button for the window. 
You should never create a window that has both of these extended styles.

  LRESULT CMWDlg::OnTrayNotification(WPARAM uID, LPARAM lEvent)
{
    if ( lEvent == WM_LBUTTONDBLCLK )
    {
        m_okToShow = TRUE;    // Allow the dialog to be shown

        if ( !IsWindowVisible() )
            ShowWindow( SW_SHOW );

        if ( IsIconic() )
            ShowWindow( SW_RESTORE );
    }

    #if 1
    else if ( lEvent == WM_RBUTTONUP )
    {
        CMenu * pSysMenu = GetSystemMenu( FALSE );
        if ( pSysMenu )
        {
            CPoint mouse;
            GetCursorPos(&mouse);
            pSysMenu->TrackPopupMenu( TPM_CENTERALIGN, mouse.x, mouse.y, this );
            // delete pSysMenu;
        }
    }
    #endif

    return 0;
}


*/


LRESULT CSecuresockDlg::OnTrayNotification(WPARAM uID, LPARAM lEvent){   

         if (lEvent == WM_LBUTTONDOWN) {

                  CWnd *pwnd = CWnd::GetDesktopWindow()->GetWindow(GW_CHILD);
                  CString test;
                  while (pwnd) {
                           pwnd->GetWindowText(test);
                           //AfxMessageBox(test);
                           if (test == "Drakis SecureChat 1.0") {
                                    //if (pwnd->IsIconic() ) // isiconic isn't reliable when i'm minimizing/hiding -
                                                             // in those cases isiconic returns false (since it's invis).
                                                             // the sneaky way to not have it show up in desktop bar
                                                             // that lists apps (or alt-tab list).  this is how winamp
                                                             // handles minimization also.  call sw_restore always shouldn't
                                                             // hurt anything for now.
                                             pwnd->ShowWindow(SW_RESTORE);

                                    pwnd->SetForegroundWindow();
                                    pwnd->GetLastActivePopup()->SetForegroundWindow();

                                    return TRUE;
                           }
                           pwnd = pwnd->GetWindow( GW_HWNDNEXT);
                  }
         }

         if (lEvent == WM_RBUTTONDOWN) {


                  DWORD dp = ::GetMessagePos();
        CPoint mouse;
             GetCursorPos(&mouse);
                  CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) );
                  CMenu menu;
                  menu.LoadMenu(IDR_MENU1);
                  CMenu *x;

                  x = menu.GetSubMenu(4);
                  CRect rect;
                  GetWindowRect(rect);

                  int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_RIGHTALIGN , mouse.x, 
                                   mouse.y, AfxGetMainWnd(), NULL );

                  if (ncmd == ID_CLOSE_NOW)
                           AfxGetMainWnd()->PostMessage(WM_QUIT);

         }

         if (false) {      
                  static LPCSTR MouseMessages[] = { "WM_MOUSEMOVE",         
                           "WM_LBUTTONDOWN", "WM_LBUTTONUP", "WM_LBUTTONDBLCLK",         
                           "WM_RBUTTONDOWN", "WM_RBUTTONUP", "WM_RBUTTONDBLCLK",         
                           "WM_MBUTTONDOWN", "WM_MBUTTONUP", "WM_MBUTTONDBLCLK" };      
                  CString s;      
                  s.Format("Tray notification: ID=%d, lEvent=0x%04x %s\r\n",          
                           uID, lEvent, WM_MOUSEFIRST<=lEvent && lEvent<=WM_MOUSELAST ?          
                           MouseMessages[lEvent-WM_MOUSEFIRST] : "(Unknown)");      
                  //AfxMessageBox(s);
                  
         }   // let tray icon do default stuff   

         return true;

}

void CSecuresockDlg::OnTrayIcon() 
{
         //AfxMessageBox("on tray icon call");
         // TODO: Add your command handler code here
         
}

BOOL CSecuresockDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
                           // TODO: Add your specialized code here and/or call the base class
         ASSERT(0);
         
         return CDialog::Create(IDD, pParentWnd);
}

void CSecuresockDlg::OnCancelMode() 
{
         CDialog::OnCancelMode();
         m_hitcancel = 1;         
         //AfxMessageBox("here");
         
}

BOOL CSecuresockDlg::PreTranslateMessage(MSG* pMsg) 
{

           // this is a known bug with the edit control for a tree control not being
           // able to receive return or escape messages when the dialog "steals" them so to speak

           // if GetEditControl returns a valid pointer than we are in editting mode, in which case
           // go ahead and manually route the message to the edit control 
           // reference knowledge base Article ID: Q167960 
           if (pMsg->message == WM_KEYDOWN &&
                   pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
           {
                   CEdit* edit = m_TreeCtrl.GetEditControl();
                   if (edit)
                   {
                           edit->SendMessage(WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
                           return TRUE;
                   }
         // for now since i don't want esc or return to do anything, just return here
                   // note that both hitting cancel key and the cancel button on the dialog both call
                   // OnCancel directly.  So removing OnCancel or making it inoperable means you can't close
                   // the app from the normal close dialog button (X button).  It is hard to separate this from
                   // the actions of them hitting cancel key also, as cancel key doesn't appear to travel thru
                   // the normal WM_CHAR or WM_SYS_CHAR functions at all but also goes directly to OnCancel if it
                   // exists.  this is highly annoying behavior and another reason for manually overriding this stuff
                   // in pretranslatemessage, so we can kill the escape key hits without disallowing them to close
                   // via the normal dialog close button.
                   return TRUE;
           }
         
         return CDialog::PreTranslateMessage(pMsg);
}

void CSecuresockDlg::OnUpdateChangeIcon1(CCmdUI* pCmdUI) 
{
         // TODO: Add your command update UI handler code here
         
}

void CSecuresockDlg::OnMyButtonUI(CCmdUI* pCmdUI) 
{
         if (1) {
                  AfxMessageBox("b");
                  ASSERT(0);

         }
         // TODO: Add your command update UI handler code here
         
}

void CSecuresockDlg::OnDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult) 
{
         DWORD dp = ::GetMessagePos();
         CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) );

         m_TreeCtrl.ScreenToClient (&pt);
         UINT flags = NULL;

         //char buffer[20];

         HTREEITEM thishitem = m_TreeCtrl.HitTest( pt, &flags);

         // if top level item = department, use department menu, otherwise use contact menu
         if ( m_TreeCtrl.GetParentItem(thishitem) == NULL || thishitem == NULL) { 
                  return;
         } 

         ChatItemInfo *tempci;
         tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem ));

         // dont open send message dialog for a system message
         if (tempci->ntype == SYSTEM_MSG) {
                  return;
         }

         else if (tempci->ntype ==  INCOMING_CONTACT_REQUEST   ) {

                  CAcceptContact acdlg;
                  //tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem ));
                  acdlg.m_ContactMsg = tempci->msg;
                  int nresult = acdlg.DoModal();
                  if (acdlg.nstatus == 1) {
                           ProcessChatRequest(thishitem, tempci, true);
                  }
                  if (acdlg.nstatus == 0) {
                           ProcessChatRequest(thishitem, tempci, false);
                  }
                  return;

         } else {

                  if ( (tempci->ntype == CHAT_CONTACT) && 
                                             pSockApp->bPendingMsgsByChatID( tempci->chat_id ) ) {

                           CReadDlg *readdlg;

                           CString temp;
                           int noffset = pSockApp->GetPendingMsgByChatID( tempci->chat_id, &temp);
                           if (noffset == -1 ) {

                                    AfxMessageBox("trouble finding related message to this chat id, bug");

                           } else {

                                    // modeless dialog creation
                                    readdlg = new CReadDlg();
                                    readdlg->iUserIconID = tempci->icon_id;
                                    readdlg->msg_text = temp.GetBuffer(0);
                                    readdlg->m_myiconid = m_TreeCtrl.GetImageIndex(thishitem);
                                    readdlg->chat_id = tempci->chat_id;
                                    readdlg->m_nickname = tempci->nickname;
                                    readdlg->s_backcolor = pSockApp->main_msg_list.msg_vector[noffset].backcolor.GetBuffer(0);
                                    readdlg->Create();
                                    pSockApp->UpdateMsgListFlag(noffset, true) ;

                           }

                  } else {

                           m_TreeCtrl.SelectItem( thishitem );
                           CSendDlg *senddlg;

                           //MessageBox("send message");
                           senddlg = new CSendDlg();
                           senddlg->iUserIconID = tempci->icon_id;
                           CString temp;
                           TRACE("calling send dlg, chat id : %lu", tempci->chat_id);
                           //tempci->chat_id
                           //AfxMessageBox( tempci->nickname );

                           TRACE("nickname: %s", tempci->nickname.GetBuffer(0));

                           senddlg->m_myiconid = m_TreeCtrl.GetImageIndex(thishitem);
                           senddlg->m_nickname = tempci->nickname;
                           senddlg->chat_id = tempci->chat_id;

                           senddlg->Create();
                           senddlg->SetActiveWindow();

                  }
                  
                  *pResult = 0;

         }
         return;


}

// save the current users array to users.ids file
// note they can switch between users so this is an array 
bool CSecuresockDlg::SaveUsersToFile(void)
{

         //ASSERT(0);

         CString ifname;
         int n;
         ifname = "users.ids";

         ofstream users_file ( ifname.GetBuffer(0), ios::out );

         if (users_file) {

                  for (n=0;n<pSockApp->users_array.size();n++) {

                           users_file << setw(10) << pSockApp->users_array[n].chat_id;
                           users_file << setw(1) << pSockApp->users_array[n].is_default ;
                           users_file << setw(4) << pSockApp->users_array[n].nickname.GetLength() ;
                           users_file << ",";
                           users_file << pSockApp->users_array[n].nickname.GetBuffer(0) ;
                           users_file << '\n';

                           //users_file << pSockApp->users_array[n].nickname.GetBuffer(0) << endl;

                  }
                  users_file.close();

         } else {
                  return false;
         }
         return true;

}

HBRUSH CSecuresockDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
         HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
         
         if (m_my_status.m_hWnd == pWnd->m_hWnd) {

                  pDC->SetBkColor( RGB( 0, 0, 0) );
                  if (m_imy_status == ACTIVE) 
                           pDC->SetTextColor( RGB( 0, 255, 0) );
                  else if (m_imy_status == BUSY)
                           pDC->SetTextColor( RGB( 0, 255, 255) );
                  else if (m_imy_status == SHORT_AFK)
                           pDC->SetTextColor( RGB( 255, 255, 0) );
                  else if (m_imy_status == LONG_AFK)
                           pDC->SetTextColor( RGB( 255, 128, 0) );
                  else if (m_imy_status == INVISIBLE)
                           pDC->SetTextColor( RGB( 192, 192, 192) );
                  else
                           pDC->SetTextColor( RGB( 255, 0, 255) );

                  return (HBRUSH)m_BlackBrush;
                  //pWnd->Invalidate(TRUE);
         }
         else if (m_online_status.m_hWnd == pWnd->m_hWnd ) {

                  if (pSockApp->bTroubleConnecting ) {
                           pDC->SetTextColor( RGB( 255, 0, 0) );
                           pDC->SetBkColor( RGB( 0, 0, 0) );
                           //return (HBRUSH)m_BlackBrush;
                  } else {
                           pDC->SetTextColor( RGB( 0, 192, 64) );
                           pDC->SetBkColor( RGB( 0, 0, 0) );
                           //return (HBRUSH)m_BlackBrush;
                           //return (HBRUSH)m_GreenBrush;
                  }
                  return (HBRUSH)m_BlackBrush;
         }

         return hbr;
}

// process an incoming message, param w is a CSingleMessage pointer of the received message's info
LONG CSecuresockDlg::OnNewMessage(WPARAM w, LPARAM l)
{

         CSingleMessage *temp = (CSingleMessage *)w;

         // if you call methods on the csm object created in the other thread (via slot.cpp) it appears to cause an error
         // on delete.  this is not consistent and relates to possibly the fact that a csm has cstrings in it and 
         // calling methods on an object across thread boundaries is a bit dangerous in MFC.  so we create a copy of
         // of the csinglemessage and then delete the CSingleMessage pointer passed in from slot.cpp (which runs in a
         // separate thread and processes incoming chat messages from there, and then posts a message to the window
         // which then gets directed to this function, which runs in the main thread).  See Prosise on threading for
         // more details on how to pass info back and forth from threads.  it is generally okay to access variables
         // from an object created in another thread but assigning these variables values or calling the methods on
         // the object seems to sometimes cause problems with delete, it gives an error "damage in header block on
         // delete" which is often a critical error.  

         // further note: when this happens after fixing error or while rebuilding the app completely can help it to
         // return to state, sometimes it can get in a dangerously unstable situation where it shows phantom bugs all
         // over (in other deletes for example that should not be buggy).  rebuild all seems to clear the heap pointer
         // mechanism somehow and stop this phantom bug problem (whereas incremental rebuild, or even quitting and coming
         // back into Visual Studio, doesn't appear to make the unstable state go away).
         CSingleMessage copy_of_csm;

         // this statement is possible because i've explicitly defined operator= for CSingleMessage class, see class details for
         // more info
         copy_of_csm = *temp;

         // make sure we delete the object passed in via the message parameters, after we've copied it to a usable object
         // again, don't use an object created in another thread by reassignign values to object variables, or
         // by calling methods on it, or you will get likely
         // crashes/memory leaks/very bad things.  this is a thread issue with MFC
         delete temp;

         // adds a message to the messages to be processed list (a vector of messages in a container class)
         int nmsgoffset = pSockApp->AddMessage(&copy_of_csm);
         if (nmsgoffset < 0) {
                  AfxMessageBox("trouble adding a message to the internal message vector make note for Scott");
         }

         CString temp2;

         // this is a serious bug just quit function if true
         if (copy_of_csm.chat_id_to == 0) {
                  AfxMessageBox("bug, new msg received with incoming chat id of zero");
                  return 0L;
         }

         // this is if the message was sent to another user on this same machine, this shouldn't happen often
         // but is possible, if so we queue it up in the messages but don't mark it as processed yet
         // note: currently used chat_id = psockapp->my_controls.chat_id
         if ( copy_of_csm.chat_id_to != pSockApp->my_controls.chat_id ) {

                  // mark message as not being processed (this is not strictly necessary as it's created with a false
                  // value but good to do for clarity here I think).
                  if (nmsgoffset >= 0) 
                           pSockApp->UpdateMsgListFlag(nmsgoffset, false);

                  copy_of_csm.SaveMsgToLog(false, false);
                  long li = 1;
                  return li;

         } 

         // received, i.e. incoming, contact request
         if (copy_of_csm.msg_type == CSingleMessage::CONTACT_REQUEST) {


                  HTREEITEM hi = GetPendingContactGroup();
                  int icon_id = copy_of_csm.icon_id;
                  int nindex = GetGoodIndex( &icon_id );
                  //copy_of_csm.icon_id = icon_id;

                  //if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) {

                           temp2.Format("Incoming contact request from:%s", copy_of_csm.nickname.GetBuffer(0) );

                           HTREEITEM newitem = m_TreeCtrl.InsertItem( temp2.GetBuffer(0), nindex, nindex, hi);
                           m_TreeCtrl.Expand( hi, TVE_EXPAND);

                           ChatItemInfo *citemp = new ChatItemInfo (copy_of_csm.chat_id_from, INCOMING_CONTACT_REQUEST, 
                                             copy_of_csm.msg, copy_of_csm.time_sent, copy_of_csm.time_received, copy_of_csm.nickname, icon_id );

                           // since the user may delete objects and they are added constantly i'm using a version of garbage
                           // collection for now to delete all this on application shutdown.  the second param shows what time to cast
                           // the pointer to before you delete it, source to function is in securesock.cpp
                           add_ptr_to_garbage(citemp, "ChatItemInfo");

                           m_TreeCtrl.SetItemData( newitem, (DWORD)citemp );

                  //}

                  if (nmsgoffset >= 0) 
                           pSockApp->UpdateMsgListFlag(nmsgoffset, true);

                  copy_of_csm.SaveMsgToLog(false, false);


         }

         // contact acceptance (reply from contact request in affirmative)
         else if (copy_of_csm.msg_type == CSingleMessage::CR_ACCEPTED) {

                  CString temp_string;
                  temp_string.Format("%s - contact acceptance msg received", copy_of_csm.nickname.GetBuffer(0) );

                  CString descrip;
                  descrip = "contact request acceptance received";
                  //AddSystemMsg( &copy_of_csm, copy_of_csm.msg_type, temp_string, descrip );
                  NewInsertSystemMessage(temp_string, copy_of_csm.chat_id_from,
                                                               copy_of_csm.msg, copy_of_csm.nickname, copy_of_csm.time_sent);

                  CString temp3;
                  temp3.Format("Your chat request to %s has been approved -- please specify what Group you would like "
                                    "to put them into.", copy_of_csm.nickname.GetBuffer(0) );

                  AfxMessageBox( temp3 );

                  this->GetGroupLabels( );

                  CMoveContactDlg mcd;
                  mcd.nocopy = true;

                  mcd.ptgiVector = tgiVector;
                  mcd.DoModal();
                  int nindex = GetIndexFromIconID(copy_of_csm.icon_id);

                  HTREEITEM higroup;
                  if (mcd.nchoice == -1) {
                           higroup = m_TreeCtrl.GetRootItem();
                           if (higroup == 0) {
                                    higroup = m_TreeCtrl.InsertItem( "New Group", nindex, 
                                                                                 nindex, TVI_ROOT, TVI_LAST);
                           }
                  } else {
                           higroup = tgiVector[mcd.nchoice].htItem;
                  }

                  HTREEITEM newitem = m_TreeCtrl.InsertItem( copy_of_csm.nickname.GetBuffer(0), nindex, nindex, higroup);
                  m_TreeCtrl.Expand( higroup, TVE_EXPAND);

                  ChatItemInfo *citemp = new ChatItemInfo;
                  citemp->chat_id = copy_of_csm.chat_id_from;
                  citemp->ntype = CHAT_CONTACT;
                  citemp->create_time = GetTimeString() ;
                  citemp->msg = "";
                  citemp->icon_id = copy_of_csm.icon_id ;
                  citemp->nickname = copy_of_csm.nickname.GetBuffer(0);

                  // since the user may delete objects and they are added constantly i'm using a version of garbage
                  // collection for now to delete all this on application shutdown.  the second param shows what time to cast
                  // the pointer to before you delete it, source to function is in securesock.cpp
                  add_ptr_to_garbage(citemp, "ChatItemInfo");

                  m_TreeCtrl.SetItemData( newitem, (DWORD)citemp );

                  if (nmsgoffset >= 0) 
                           pSockApp->UpdateMsgListFlag(nmsgoffset, true);

                  copy_of_csm.SaveMsgToLog(false, false);

         }
         // contact decline message (reply from contact request in negative)
         else if (copy_of_csm.msg_type == CSingleMessage::CR_DECLINED) {

                  CString temp_string;
                  temp_string.Format("%s - contact declined msg received", copy_of_csm.nickname.GetBuffer(0) );
                  CString descrip;
                  descrip = "contact request decline received";

                  //AddSystemMsg( &copy_of_csm, copy_of_csm.msg_type, temp_string, descrip );
                  NewInsertSystemMessage(temp_string, copy_of_csm.chat_id_from,
                                                               copy_of_csm.msg, copy_of_csm.nickname, copy_of_csm.time_sent);

                  TRACE("in declined handler\n");

                  // the current messages list/ messages vector has a flag whether it has been processed yet, it has so set this flag
                  // to a true value.  upon creation (in addmessages) it will be set to false.  if i receive a message for,
                  // say another user on this computer by accident (there is a short window of somewhere under 30 seconds
                  // when you switch accounts when you might get a message for the old user), 
                  // i can tell by this flag on the message whether the message still
                  // needs to be processed, eventually this message list will be serialized so that on shutdown or whatever
                  // the messagelist will be recreated for these unprocessed messages (note this is separate from the log
                  // which is more just a history of what happens).  the serialization will have to be a constant thing to avoid
                  // power lossage/loss of info problems.
                  if (nmsgoffset >= 0) 
                           pSockApp->UpdateMsgListFlag(nmsgoffset, true);

                  copy_of_csm.SaveMsgToLog(false, false);

         }
         // contact decline message (reply from contact request in negative)
         else if (copy_of_csm.msg_type == CSingleMessage::MESSAGE) {

                  CString temp_string;
                  temp_string.Format("%s - incoming msg received", copy_of_csm.nickname.GetBuffer(0) );
                  CString descrip;
                  descrip = "New Message Received";

                  if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) {

                           //AddSystemMsg( &copy_of_csm, copy_of_csm.msg_type, temp_string, descrip );
                           NewInsertSystemMessage(temp_string, copy_of_csm.chat_id_from,
                                                                        descrip, copy_of_csm.nickname, copy_of_csm.time_sent);

                  }

                  TRACE("in message received handler\n");
                  sndPlaySound("driveby.wav", SND_ASYNC);

                  // the current messages list/ messages vector has a flag whether it has been processed yet, it has so set this flag
                  // to a true value.  upon creation (in addmessages) it will be set to false.  if i receive a message for,
                  // say another user on this computer by accident (there is a short window of somewhere under 30 seconds
                  // when you switch accounts when you might get a message for the old user), 
                  // i can tell by this flag on the message whether the message still
                  // needs to be processed, eventually this message list will be serialized so that on shutdown or whatever
                  // the messagelist will be recreated for these unprocessed messages (note this is separate from the log
                  // which is more just a history of what happens).  the serialization will have to be a constant thing to avoid
                  // power lossage/loss of info problems.
                  if (nmsgoffset >= 0) 
                           pSockApp->UpdateMsgListFlag(nmsgoffset, false);

                  copy_of_csm.SaveMsgToLog(false, false);

         }

         long li = 1;
         return li;

}

HTREEITEM CSecuresockDlg::NewInsertSystemMessage(CString label_text, unsigned long chat_id,
                                                               CString msg, CString nickname, CString created )
{

         HTREEITEM hi;
         hi = GetTreeItemByCriteria(CSecuresockDlg::TYPE_LOOKUP, (int)SYSTEM_GROUP) ;
         if ( hi == 0) {

                  hi = m_TreeCtrl.InsertSysNotifyGrp();
                  if (! hi)
                  {
                           AfxMessageBox("warning, unable to create new system group, make note for programmer");

                           hi = m_TreeCtrl.GetRootItem();
                           if (hi == 0) {
                                    AfxMessageBox("new system message lost, notify Scott");
                                    return false;
                           }
                  }

         }

         if (chat_id == 0) {
                  AfxMessageBox("associated chat id for this system message is zero, possible bug,"
                           " make note for programmer");
                  return false;
         }

         int nindex = GetIndexFromIconID(IDI_ICON83);

         HTREEITEM newitem = m_TreeCtrl.InsertItem( label_text.GetBuffer(0), nindex, nindex, hi);
         m_TreeCtrl.Expand( hi, TVE_EXPAND);

         ChatItemInfo *citemp = new ChatItemInfo;
         citemp->chat_id = chat_id;
         citemp->ntype = SYSTEM_MSG;

         CString time;
         GetTimeString(&time);

         citemp->create_time = time.GetBuffer(0) ;
         //citemp->
         citemp->msg = msg.GetBuffer(0);
         citemp->nickname = nickname.GetBuffer(0);

         // since the user may delete objects and they are added constantly i'm using a version of garbage
         // collection for now to delete all this on application shutdown.  the second param shows what time to cast
         // the pointer to before you delete it, source to function is in securesock.cpp
         add_ptr_to_garbage( (LPVOID)citemp, "ChatItemInfo");

         m_TreeCtrl.SetItemData( newitem, (DWORD)citemp );

         return newitem;

}



int CSecuresockDlg::GetGoodIndex(int *icon_id) {

         int iret;
         if (*icon_id == 0) {
                  iret = GetIndexFromIconID(IDI_ICON31);
                  *icon_id = IDI_ICON31;
         }
         else {
                  iret = GetIndexFromIconID(*icon_id);
                  if (iret  == -1) {
                           iret = GetIndexFromIconID(IDI_ICON31);
                           *icon_id = IDI_ICON31;
                  }
         }
         return iret;

}

HTREEITEM CSecuresockDlg::GetPendingContactGroup(void)
{

         HTREEITEM hi;
         hi = GetTreeItemByCriteria(CSecuresockDlg::TYPE_LOOKUP, (int)PENDING_CONTACTS_GROUP) ;
         if ( hi == 0) {

                  hi = m_TreeCtrl.InsertItem( "Pending Contact Requests", 29, 29, TVI_ROOT, TVI_LAST);
                  CString string_time = GetTimeString();

                  ChatItemInfo *newci = new ChatItemInfo(0L, PENDING_CONTACTS_GROUP, 
                                             CString("Pending Contact Requests Group"), string_time );

                  m_TreeCtrl.SetItemData( hi, (DWORD)newci );
                  add_ptr_to_garbage(newci, "ChatItemInfo");
         }
         return hi;

}

void CSecuresockDlg::GetLatency() 
{
         

         if (pSockApp->bTroubleConnecting) {
                  AfxMessageBox("You don't appear to be online, hence your latency is infinite");
                  return;
         }

         DWORD start = GetTickCount();
         // attempt to check in 
         CString send_url;
         send_url.Format("/cgi-bin/check_in.pl?my_scno=%lu", pSockApp->my_controls.chat_id);

         CMySocket newconn("www.drakis.com");
         CString response;
         newconn.GetFileAsString( send_url.GetBuffer(0),
                  "www.drakis.com", &response);


         bool bConnected = true;
         if ( response.Find("ok^", 0) == -1 ) {
                  //AfxMessageBox("trouble connecting");
                  bConnected = false;
         } else {
                  //AfxMessageBox("connected");
         }


         DWORD end = GetTickCount();
         if ( end < start ) {
                  AfxMessageBox("the timer just cycled it does this every 49 days, the chances of this happening are like one "
                           "in ten billion.  Unfortunately there is no lottery award =(.  Retry to check latency.");
                  return;
         }

         double diff = end - start;
         diff = diff / (double)1000;

         CString temp_string;

         temp_string.Format("Server Latency: %3.3f seconds\n "
                           "A lower latency means a better connection, if your latency is high the server may "
                           "be busy or you may be on a bad connection.", diff);

         AfxMessageBox(temp_string);

}
 
void CSecuresockDlg::SwitchUsers(int offset) 
{

         int newchat_id = 126;
         // make sure you save any new groups, contacts, etc. so call SaveTree before
         // changing the default ID (via pSockApp->my_controls.chat_id).
         SaveTree();

         // note this also will return false (i.e. fail) if we are already set to this chat_id, which
         // means we really dont need to do anything, just return
         if (! pSockApp->SetDefaultUser( offset ) ) {
                  //AfxMessageBox("trouble finding this new chat_id internal logic synch error notify Scott");
                  //note: error msg handled in method itself not needed here
                  //AfxMessageBox("did nothing");
                  return;
         }

         CString temp = pSockApp->my_controls.GetStringByTokenName("user_icon");
         int ICONIDD = atoi(temp.GetBuffer(0));
         if (ICONIDD == 0) {
                  AfxMessageBox("trouble retrieving new users icon");
                  ICONIDD = IDI_ICON31;
         }

         HICON hIcon = ::LoadIcon (AfxGetResourceHandle(), 
                              MAKEINTRESOURCE(ICONIDD));

         m_mypersonalbutton.SetIcon( hIcon );         
         m_my_personal_icon_id = ICONIDD;

         temp.Format("tf_u%lu.dra", pSockApp->my_controls.chat_id);

         CFile *myfile = new CFile();

         bool bopenokay = true;
         try {
                  myfile->Open( temp.GetBuffer(0), CFile::modeRead );

         } catch ( ... ) {

         }

         if (myfile->m_hFile == (UINT)CFile::hFileNull) {
                  delete myfile;
                  myfile = (CFile *)NULL;
         }


         m_TreeCtrl.DeleteAllItems();

         // if treeFile is NULL this is okay it recreates a generic tree
         BuildTreeFromFile(m_TreeCtrl, myfile, true );

         delete myfile;

         // set back ground color for tree if available
         CString colors = pSockApp->my_controls.GetStringByTokenName("tree_back_color");
         if (! colors.IsEmpty() ) {
                  unsigned long ulcolor = strtoul(colors.GetBuffer(0), NULL, 10);
                  COLORREF x2 = (COLORREF)ulcolor;
                  m_TreeCtrl.SetBkColor(x2) ;
         }
         GetTreeFontFromFile();

         // get saved online status (ghost mode, busy, afk, or active, based on their last entry before
         // last save
         CString saved_status = pSockApp->my_controls.GetStringByTokenName("user_online_status");

         if ( saved_status.IsEmpty() || atoi(saved_status.GetBuffer(0)) == 0) 
                  m_imy_status = CSecuresockDlg::ACTIVE;
         else 
                  m_imy_status = atoi(saved_status.GetBuffer(0));

         ::SetMyOnlineStatus(m_imy_status);

         UpdateMyStatusText();


         temp.Format("Changed control to user:%s", pSockApp->my_controls.nickname.GetBuffer(0) );

         AfxMessageBox(temp );
         //temp.Format("new chat id is now: %lu", pSockApp->my_controls.chat_id);


         //AfxMessageBox( temp );

}

// update the "status: online" kind of textbox, to whatever is current condition
void CSecuresockDlg::UpdateStatusText(void)
{
         CWnd *pwnd2 = (CWnd *)(&m_online_status); // m_online_status is created via code not as a dialog item on
                                                                                                   // the resource (for various reasons, like ease of setting font stuff)
         if (pSockApp->bTroubleConnecting)
                  pwnd2->SetWindowText("Server: Offline");
         else
                  pwnd2->SetWindowText("Server: Online");

         //pwnd2->Invalidate(); // cause color repaint, not sure if strictly necessary
                                             // color is changed in WM_CTL_COLOR handler
         //pwnd2 = (CWnd *)(&m_my_status);
         //CString temp;
         //pwnd2->GetWindowText(temp);
         //pwnd2->SetWindowText( "scooby" );
         //pwnd2->Invalidate(TRUE);

}         

bool CSecuresockDlg::OnSend(ITEMINFO *pItem)
{

         OnOutgoingMsg((WPARAM)pItem, 0);
         return true;

}

bool CSecuresockDlg::ProcessChatRequest(HTREEITEM thishitem, ChatItemInfo *tempci, bool bAccept)
{

         //vector<TreeGroupInfo> tgiVector;

         // if they accepted the chat request
         if (bAccept) {

                  this->GetGroupLabels();

                  CMoveContactDlg mcd;
                  mcd.nocopy = true;
                  mcd.ptgiVector = tgiVector;
                  mcd.DoModal();
                  int nindex = GetIndexFromIconID(tempci->icon_id);

                  HTREEITEM higroup;
                  if (mcd.nchoice == -1) {
                           higroup = m_TreeCtrl.GetRootItem();
                           if (higroup == 0) {
                                    higroup = m_TreeCtrl.InsertItem( "New Group", nindex, 
                                                                                 nindex, TVI_ROOT, TVI_LAST);
                           }
                  } else {
                           higroup = tgiVector[mcd.nchoice].htItem;
                  }

                  HTREEITEM newitem = m_TreeCtrl.InsertItem( tempci->nickname.GetBuffer(0), nindex, nindex, higroup);
                  m_TreeCtrl.Expand( higroup, TVE_EXPAND);

                  ChatItemInfo *citemp = new ChatItemInfo;
                  citemp->chat_id = tempci->chat_id;
                  citemp->ntype = CHAT_CONTACT;
                  citemp->create_time = GetTimeString() ;
                  citemp->msg = "";
                  citemp->icon_id = tempci->icon_id ;
                  citemp->nickname = tempci->nickname;

                  add_ptr_to_garbage(citemp, "ChatItemInfo");

                  m_TreeCtrl.SetItemData( newitem, (DWORD)citemp );

                  // pointer deleted in onoutgoingmsg
                  ITEMINFO *pItem = new ITEMINFO();

                  // this would be a good place for a operator= method probably will add this to ITEMINFO at
                  // some point, right now it's just a plain old structure not a class. 
                  pItem->chat_id.Format("%lu", tempci->chat_id);
                  pItem->nickname = pSockApp->my_controls.GetStringByTokenName("nickname");
                  pItem->nickname_to = tempci->nickname.GetBuffer(0);
                  pItem->msg = "Contact request accepted";
                  pItem->csm_msg_type = CSingleMessage::CR_ACCEPTED;
                  pItem->ntype = OUTGOING_MSG;

                  OnOutgoingMsg((WPARAM)pItem, 0);
         

         } else {

                  // pointer deleted in onoutgoingmsg
                  ITEMINFO *pItem = new ITEMINFO();

                  pItem->chat_id.Format("%lu", tempci->chat_id);
                  pItem->msg = "Contact request declined";
                  pItem->csm_msg_type = CSingleMessage::CR_DECLINED;
                  pItem->ntype = OUTGOING_MSG;
                  pItem->nickname = pSockApp->my_controls.GetStringByTokenName("nickname");
                  pItem->nickname_to = tempci->nickname.GetBuffer(0);

                  OnOutgoingMsg((WPARAM)pItem, 0);

         }

         m_TreeCtrl.DeleteItem( thishitem );

         return true;
}

LONG CSecuresockDlg::ShowOnlineStatus(WPARAM w, LPARAM l)
{

         OnlineResults *por = (OnlineResults *)w;
         //CString display;
         //display.Format("%lu", por->chat_id);
         if (por->bOnline) {

                  //display += " is online";
                  if (por->nstatus == 0 || por->nstatus == this->ACTIVE)
                           m_TreeCtrl.SetItemOverlayIndex( por->hitem, 1);
                  if ( por->nstatus == this->BUSY)
                           m_TreeCtrl.SetItemOverlayIndex( por->hitem, 3);
                  if ( por->nstatus == this->SHORT_AFK)
                           m_TreeCtrl.SetItemOverlayIndex( por->hitem, 4);
                  if ( por->nstatus == this->LONG_AFK)
                           m_TreeCtrl.SetItemOverlayIndex( por->hitem, 4);
                  if ( por->nstatus == this->INVISIBLE)
                           m_TreeCtrl.SetItemOverlayIndex( por->hitem, 2);

         } else {
                  //display += " is NOT online";
                  m_TreeCtrl.SetItemOverlayIndex( por->hitem, 2);
         }

         //AfxMessageBox(display);
         delete por;
         return 0L;

}

LONG CSecuresockDlg::OnOutgoingMsg(WPARAM w, LPARAM l)
{

         ITEMINFO *pItem = (ITEMINFO *)w;

         // this is chat_id to send to, in this case
         unsigned long chat_id = strtoul( pItem->chat_id.GetBuffer(0), NULL, 10 );
         CString temp;
         CString created;
         created = "";
         CString descrip;

         //HICON hIcon = ::LoadIcon (AfxGetResourceHandle(), 
         //                     MAKEINTRESOURCE(ICONIDD));
         //m_mypersonalbutton.SetIcon( hIcon );         
         //m_my_personal_icon_id = ICONIDD;

         // ultra paranoia here but to be safe
         if (chat_id == 0) {

                  AfxMessageBox("attempt to send a message to a chat_id of ZERO "
                           "probable logic error in OnOutgoingMsg function, notify programmer "
                           "msg not sent.");

                  temp.Format("%s - msg not sent logic error", pItem->nickname.GetBuffer(0) );

                  // second parameter not strictly necessary but provided for clarity
                  // add a system message to the tree control about what we are doing
                  descrip = "error with send: chat id was zero.";
                  NewInsertSystemMessage(temp, 0L,
                                                               descrip, pItem->nickname_to, created);

                  //AddSystemMsg( pItem, CSingleMessage::NOT_SENT_LOGIC_ERROR, temp, descrip );
                  return 0L;

         }

         if (pItem->csm_msg_type == CSingleMessage::CONTACT_REQUEST) {

                  temp.Format("%s - contact request sent", pItem->nickname.GetBuffer(0) );

                  //pItem->msg = "outgoing contact request";

                  CString msg_text = "Outgoing contact request sent";

                  // second parameter not strictly necessary but provided for clarity
                  // add a system message to the tree control about what we are doing
                  //AddSystemMsg( pItem, pItem->csm_msg_type, temp, msg_text );

                  if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) {

                           NewInsertSystemMessage(temp, chat_id,
                                                                        msg_text, pItem->nickname_to, created);

                  }
                  // create a message info structure of info to pass to thread
                  MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type,
                                             chat_id, pSockApp->my_controls.chat_id, 
                                             pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id );

                  AfxBeginThread(send_msg, pMsgInfo);

         }

         if (pItem->csm_msg_type == CSingleMessage::CR_ACCEPTED) {

                  temp.Format("%s - contact accept msg sent", pItem->nickname_to.GetBuffer(0) );

                  descrip = "contact acceptance msg sent";

                  //AddSystemMsg( pItem, pItem->csm_msg_type, temp, descrip );
                  if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) {

                           NewInsertSystemMessage(temp, chat_id, descrip, pItem->nickname_to, created);

                  }

                  MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type,
                                             chat_id, pSockApp->my_controls.chat_id, 
                                             pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id);

                  AfxBeginThread(send_msg, pMsgInfo);
                  gb_lookat = true;

         }

         if (pItem->csm_msg_type == CSingleMessage::CR_DECLINED) {

                  temp.Format("%s - contact decline msg sent", pItem->nickname_to.GetBuffer(0) );

                  descrip = "contact decline msg sent";

                  //AddSystemMsg( pItem, pItem->csm_msg_type, temp, descrip );
                  if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) {
                           NewInsertSystemMessage(temp, chat_id,
                                                               descrip, pItem->nickname_to, created);
                  }

                  MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type,
                                             chat_id, pSockApp->my_controls.chat_id, 
                                             pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id );

                  AfxBeginThread(send_msg, pMsgInfo);

         }

         if (pItem->csm_msg_type == CSingleMessage::MESSAGE) {

                  temp.Format("chat message sent to %s", pItem->nickname_to.GetBuffer(0) );

                  //pItem->msg = "outgoing contact request";

                  CString msg_text = "Chat message sent";

                  // second parameter not strictly necessary but provided for clarity
                  // add a system message to the tree control about what we are doing
                  //AddSystemMsg( pItem, pItem->csm_msg_type, temp, msg_text );
                  if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) {

                           NewInsertSystemMessage(temp, chat_id,
                                                               msg_text, pItem->nickname_to, created);

                  }

                  // create a message info structure of info to pass to thread
                  MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type,
                                             chat_id, pSockApp->my_controls.chat_id, 
                                             pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id,
                                             pItem->backcolor.GetBuffer(0) );

                  AfxBeginThread(send_msg, pMsgInfo);

         }

         


         delete pItem;

         return 0L;

}

/*

HTREEITEM CSecuresockDlg::InsertSystemMessage(CString label_text, HTREEITEM &hiGrp, unsigned long chat_id,
                                                               TypeInfo ti_type, CString msg, ITEMINFO *pItemInfo, CString param_msg)
{

         int nindex = GetIndexFromIconID(IDI_ICON83);

         HTREEITEM newitem = m_TreeCtrl.InsertItem( label_text.GetBuffer(0), nindex, nindex, hiGrp);
         m_TreeCtrl.Expand( hiGrp, TVE_EXPAND);

         ChatItemInfo *citemp = new ChatItemInfo;
         citemp->chat_id = chat_id;
         citemp->ntype = ti_type;

         CString time = "n/a"; //GetTimeString();

         citemp->create_time = time.GetBuffer(0) ;

         citemp->msg = param_msg.GetBuffer(0);
         citemp->nickname = pItemInfo->nickname.GetBuffer(0);

         add_ptr_to_garbage( (LPVOID)citemp, "ChatItemInfo");

         //delete citemp;
         m_TreeCtrl.SetItemData( newitem, (DWORD)citemp );

         return newitem;

}
bool CSecuresockDlg::AddSystemMsg(CSingleMessage *temp, int imsg_type, CString label_text, CString msg)
{

         ITEMINFO *newii = new ITEMINFO();

         CString temp_string;
         temp_string.Format("%lu", temp->chat_id_from );
         newii->chat_id = temp_string.GetBuffer(0);
         newii->csm_msg_type = temp->msg_type;
         newii->msg = temp->msg.GetBuffer(0);
         newii->nickname = temp->nickname.GetBuffer(0);

         newii->nickname_to = temp->nickname.GetBuffer(0);
         return AddSystemMsg( newii, imsg_type, label_text, msg);

}

bool CSecuresockDlg::AddSystemMsg(ITEMINFO *pItemInfo, int imsg_type, CString label_text, CString msg)
{

         HTREEITEM hi;
         hi = GetTreeItemByCriteria(CSecuresockDlg::TYPE_LOOKUP, (int)SYSTEM_GROUP) ;
         if ( hi == 0) {

                  hi = m_TreeCtrl.InsertSysNotifyGrp();
                  if (! hi)
                  {
                           AfxMessageBox("warning, unable to create new system group, make note for programmer");

                           hi = m_TreeCtrl.GetRootItem();
                           if (hi == 0)
                                    return false;
                  }


         }

         unsigned long chat_id = strtoul( pItemInfo->chat_id.GetBuffer(0), NULL, 10 );
         if (chat_id == 0) {
                  AfxMessageBox("associated chat id for this system message is zero, possible bug,"
                           " make note for programmer");
                  return false;
         }

         InsertSystemMessage(label_text, hi, chat_id, SYSTEM_MSG, pItemInfo->msg, pItemInfo, msg);
         return true;

}
*/

// handler method for WM_CONNECT_STATUS message
LONG CSecuresockDlg::OnConnectStatus(WPARAM w, LPARAM l)
{

         CONNECTINFO *conn_info = (CONNECTINFO *)w;

         // this is called from wm_init_dialog sort of in a roundabout way, this is when
         // we have first connected (or failed).  it only gets called once from here this is
         // done so that the whole dialog doesn't pause if it can't connect (for 17 seconds)
         // which happens when called this logic directly and trying to connect.  so I handle this
         // special case with the same code as normal default handler operation for the ACK or the
         // "try to connect when not connected" timer calls that usually are handled in code below this.
         if (bStartupFlag) {

                  bStartupFlag = false;
                  pSockApp->bTroubleConnecting = ! conn_info->bIsConnected ;
                  UpdateStatusText();
                  delete conn_info;
                  return 0L;
         } 

         // if something has changed, handle it, if it has changed from connected to not connected
         // or not connected to connected, change the timer value, and change the status text accordingly
         if ( conn_info->bIsConnected && pSockApp->bTroubleConnecting) {
                  pSockApp->bTroubleConnecting = false;
                  UpdateStatusText();
                  //KillTimer(2);
                  // when online okay send acks every 5 seconds
                  //SetTimer(2, 5000, NULL);
         } else if (! conn_info->bIsConnected && ! pSockApp->bTroubleConnecting) {
                  pSockApp->bTroubleConnecting = true;
                  UpdateStatusText();
                  //KillTimer(2);
                  // when trouble connecting only retry every 25 seconds
                  //SetTimer(2, 5000, NULL);
         }

         delete conn_info;
         return 0L;
}

// this thread has to do with sending messages or sending chat partner requests or similar
// pParam is a MessageInfo pointer
unsigned int send_msg(LPVOID pParam)
{

         // retrieve the structure
         MessageInfo *pHelper = (MessageInfo *)pParam;
         TRACE("entering send_msg\n");
         int i = 0;

         if          (gb_lookat) {
                  //ASSERT(0);
                  gb_lookat = false;
         }


         CString temp;
         temp.Format("%i sends a message saying: %s", pHelper->chat_id, pHelper->msg.GetBuffer(0));
         //AfxMessageBox( temp );

         // get this persons IP if they are online
         CString send_url;
         send_url.Format("http://www.drakis.com/cgi-bin/get_recent_url.pl?chat_id=%lu", pHelper->chat_id);
         //AfxMessageBox( send_url );
         //TRACE( send_url );

         CString response = ::url_get(send_url.GetBuffer(0));

         bool bSentOkay = false;
         CString direct_response;
         CString direct_msg;

         // this class CSingleMessage wraps some miscellaneous sending and receiving functions
         CSingleMessage msg;
         msg.chat_id_from = pHelper->sender_id;
         msg.chat_id_to = pHelper->chat_id;
         msg.time_sent = GetTimeString();
         msg.server_time_sent = "";
         msg.bfrom_server = 0;
         msg.msg = pHelper->msg;
         msg.msg_length = pHelper->msg.GetLength();
         msg.msg_type = pHelper->ntype;
         msg.nickname = pHelper->nickname;
         msg.icon_id = pHelper->icon_id;
         //ASSERT(0);
         msg.backcolor = pHelper->backcolor.GetBuffer(0);
         //ASSERT(0);

         // if "ok" then they have a recent IP, try to send to it
         if (response.Left(2) == "ok" ) {

                  CString IP = response.Mid(3);
                  IP.Replace("^", ""); // strip out EOM character, I use caret (^) as an informal end of message marker at times

                  // create a socket and try to connect to this IP # at socket 29807, this is the default securesock
                  // service IP for send or receive
                  CMySocket newconn(IP.GetBuffer(0), 29807 );


                  // if connected okay
                  if (! newconn.bError ) {

                           // build the socket "string", "look Mom no RPC"
                           // (we know that RPC was created by demons at the behest of their leader, Bill)
                           // RPC is a way of bundling data when sending it across computer wires which is related to IDL
                           // and COM (at least in the Microsoft implementation).  I prefer to write my data encoding and
                           // extracting routines via a raw string that I then parse the results out of.  This makes it humanly
                           // readable if you haven't spent 9 months studying COM books.
                           CString direct_msg;

                           // create a socket send string from this message object
                           msg.CreateStringFromObj(&direct_msg);

                           // attempt to send this string via the socket
                           newconn.socksend( direct_msg.GetBuffer(0) );


                           // if no errors (so far)
                           if (! newconn.bError ) {

                                    //char *cresponse;

                                    int ncnt = 0;

                                    // sometimes there is a slight delay after connect before reading is allowed, 
                                    // since this is in a thread we can just
                                    // use a slight pause (unscientific but appears to work)
                                    Sleep(400);

                                    // loop thru a few times and see if we can get a confirmation string back, like "ok"

                                    char *direct_response2 = new char[201];
                                    direct_response2[0] = (char)0;
                                    int ioffset = 0;

                                    // try for 5 seconds total, no reply or activity within 5 seconds is a sign they didn't get it
                                    while (! newconn.bFinished && ! newconn.bError && (ncnt++ < 20) ) {

                                             // attempt to receive anything pending in socket buffer, note this is non-blocking (hence
                                             // the while loop)
                                             TRACE("calling sock receive\n");
                                             newconn.sockreceive();
                                             if ( strlen(newconn.myout) > 0) {
                                                      if ( strlen(newconn.myout) + ioffset > 200 ) {
                                                               strncpy(direct_response2 + ioffset, newconn.myout, 200 - ioffset );
                                                               direct_response2[200] = (char)0;
                                                               break;
                                                      }
                                                      TRACE("appending to direct response 2\n");
                                                      strcpy(direct_response2 + ioffset, newconn.myout);
                                                      ioffset += strlen(newconn.myout);
                                                      //direct_response += newconn.myout;
                                             } 
                                             
                                             // calling sleep is nice otherwise we are performance hogging a bit which isn't necessary
                                             // there is no real hurry going on here no need to continually be hitting sockreceive
                                             // i could also make sockreceive blocking I might do that, but this offers a nice level of
                                             // extra control. blocking timeout vals are weird under Windows.
                                             Sleep(100); // how does multi-tasking under windows handle sleep? does it ignore the function
                                                      // or thread that is calling sleep for a bit?  I hope so but not sure.
                                    }

                                    direct_response = direct_response2;

                                    delete [] direct_response2;

                                    // they should send "ok:" type messages back, add further confirmation type processing later
                                    // e.g. checksums back or something to verify they got the full message or whatever
                                    if ( direct_response.Left(2) == "ok") {

                                             // save info on send to the local log file
                                             TRACE("saving message to log\n");
                                             msg.SaveMsgToLog(true, true);
                                             bSentOkay = true;

                                    }

                           }

                  }
                  //bSentOkay = true;

         }

         // trouble sending directly or server didn't have current IP, so sending via offline (server msg)
         if (! bSentOkay ) {

                  CString send_url;

                  // when sending special characters via CGI params remember some characters don't work so
                  // I wrote my own cgi_encode type function, source in securesock.cpp. see notes on how cgi
                  // handles parameters with characters like % or = in any text on http or related RFC's.
                  CString url_string;

                  // create a string with parameters in CGI format for sending to server
                  msg.CreateURLStringFromObj(&url_string);

                  // create full send string now
                  send_url.Format("http://www.drakis.com/cgi-bin/offline_msg.pl?%s",
                                    url_string.GetBuffer(0) );

                  CString tempx;
                  tempx = "sent via server";
                  CMiscStuff::WaitWindow( tempx, NULL);
                  Sleep(500);
                  CMiscStuff::ClearWaitWindow();

                  //AfxMessageBox("User offline - sent via server");
                  //AfxMessageBox( send_url );

                  // maybe replace this with my version of socket send using mysocket object
                  // at times ::url_get is failing if sending the same info it is not truly sending but pretending to
                  // send and pulling from the cache, this happens even if you set DONTUSECACHE flag on (possible bug).
                  CString response = ::url_get(send_url.GetBuffer(0));

                  // if we receive a happy response, save to log file and continue
                  if ( response.Left(2) == "ok" ) {
                           msg.SaveMsgToLog(true, false);

                  } else {

                           // otherwise set the error flag, this is important to have because we may try adding in resend logic
                           msg.bSendFailure = true;
                           // save to log as usual
                           msg.SaveMsgToLog(true, false);
                           // warning
                           AfxMessageBox("the last message could not be sent directly and server may have been down so "
                                                      "it was not sent.  It will be queued and retried in the background until server is backup.");

                  }


         }

         delete pHelper;
         TRACE("leaving send_msg\n");

         return 0;

}

// this thread has to do with sending messages ack to the server to tell them we are on line
// pParam is a MessageInfo pointer
unsigned int send_ack_msg(LPVOID pParam)
{

         /*         if (g_attempting_server_contact) {
                  TRACE("still in routine, timer send_ack_msg AVOIDED\n");
                  return;
         } */

         double x1 = CMiscStuff::GetSeconds();

         MessageInfo *pMsgInfo = new MessageInfo();
         CString send_url;

         while (1) {

                  Sleep(5000);

                  pMsgInfo->ntype = 0;
                  pMsgInfo->chat_id = 0;
                  pMsgInfo->sender_id = ::GetCurrentChatID();
                  //unsigned long x = pSockApp->my_controls.chat_id;

                  pMsgInfo->msg = "";

                  // note this is this->m_hWnd (securesockdlg member item m_hWnd)
                  HWND hwndmd = ::GetMainDlgHWND();
                  pMsgInfo->phwnd = &hwndmd;

                  pMsgInfo->n_online_status = ::GetMyOnlineStatus(); // this->m_imy_status;

                  //TRACE("send ack msg called as normal\n");
                  //AfxBeginThread(send_ack_msg, (LPVOID)pMsgInfo);

                  //x2 = CMiscStuff::GetSeconds();
                  //temp.Format("%3.3f", x2 - x1);
                  //TRACE("timer 2:%s\n", temp.GetBuffer(0));

                  //g_attempting_server_contact = true;
                  //TRACE("entering send_msg_ack\n");

                  //MessageInfo *pMsgInfo = (MessageInfo *)pParam;

                  // retrieve the structure
                  HWND *phwnd = pMsgInfo->phwnd;
                  int i = 0;

                  int nstatus = pMsgInfo->n_online_status;

                  // attempt to check in 
                  send_url.Format("/cgi-bin/check_in.pl?my_scno=%lu&my_status=%i", pMsgInfo->sender_id, pMsgInfo->n_online_status);

                  // calling raw methods not class methods (raw functions, global functions) helps to avoid problems with
                  // threads accessing CObject related thingies which can sometimes cause problems.

                  //send_url.Format("http://www.drakis.com/cgi-bin/check_in.pl?my_scno=%lu", pMsgInfo->sender_id);
                  //CString response = ::url_get(send_url.GetBuffer(0));

                  // using the "other way" via url_get has some issues with it and less control
                  // a. the default windows timeout value is very high, like 18 seconds or so on my computer
                  // b. sometimes it hits the cache even when you tell it not to
                  // url_get uses the cinternetfile and similar windows inet functions, whereas using cmysocket
                  // creates a raw socket connection.  doing it with raw sockets avoids a) (you can set the timeout to whatever
                  // you want) and b) (it never pulls from the cache, which since this lookup is called every 20 seconds or so
                  // is a prime example of something windows would pull from the cache, and does, even when you set a flag to
                  // explicitly not use the cache.  at least, this was my experience with a recent bug). 

                  while (g_ssd_insocket) 
                           Sleep(20);
                  g_ssd_insocket = true;

                  CMySocket newconn("www.drakis.com");
                  CString response;
                  newconn.GetFileAsString( send_url.GetBuffer(0),
                           "www.drakis.com", &response);

                  g_ssd_insocket = false;

                  // since this runs in a thread it could be operating during a shutdown if so we want to return quickly
                  if (::stopping_threads() ) {
                           TRACE("leaving thread okay\n");
                           break;
                  }
                  // if "ok" then they connected, updated okay

                  bool bConnected = true;
                  if ( response.Find("ok^", 0) == -1 ) {
                           //AfxMessageBox("trouble connecting");
                           bConnected = false;
                  } else {
                           bConnected = true;
                           //AfxMessageBox("connected");
                  }

                  CONNECTINFO *conn_info = new CONNECTINFO; // pointer deleted in message receiving function

                  // passing info back to the window via a message, again this is thread stuff see Prosise
                  conn_info->bIsConnected = bConnected;
                  //pMsgInfo->phwnd = &m_hWnd;

                  // thread safe way to return value, post to a windows message
                  ::PostMessage(*phwnd, WM_CONNECT_STATUS, (WPARAM)conn_info, 0); 

                  //g_attempting_server_contact = false;

         }

         delete pMsgInfo;
         TRACE("leaving send_msg_ack\n");

         return 0;

}

// this thread gets whether the related users are online or not
unsigned int check_online_status(LPVOID pParam)
{

         g_getting_online_status = true;

         MessageInfo *pMsgInfo = (MessageInfo *)pParam;

         // retrieve the structure
         HWND *phwnd = pMsgInfo->phwnd;
         CString response;
         CString send_url;

         TRACE("entering get online status\n");
         int n;
         for (n=0;n < online_chk_vector.size(); n++) {

                  TRACE("getting online status for %lu", online_chk_vector[n].chat_id );

                  // get this persons IP if they are online
                  send_url.Format("/cgi-bin/get_recent_url.pl?chat_id=%lu", 
                                             online_chk_vector[n].chat_id );

                  while (g_ssd_insocket) 
                           ;
                  g_ssd_insocket = true;

                  CMySocket newconn("www.drakis.com");

                  // clear response not sure if necessary
                  response = "";
                  newconn.GetFileAsString( send_url.GetBuffer(0),
                           "www.drakis.com", &response);
                  newconn.sockclose();
                  g_ssd_insocket = false;

                  //AfxMessageBox( response );

                  // if "ok" then they have a recent IP == they are online now
                  if ( response.Find("ok:", 0) != -1 ) {

                           //AfxMessageBox( response );
                           int npos = response.Find("ok:", 0);
                           int npos2 = response.Find("^", 0);
                           int npos3 = response.Find("status:", 0);

                           CString str_status;
                           int nstatus;

                           if (npos3 != -1) {
                                    str_status = response.Mid(npos3+7);
                                    str_status = str_status.Left(5);
                                    //CString showstat;
                                    nstatus = atoi( str_status.GetBuffer(0) ) ;

                                    //showstat.Format("%i", atoi( str_status.GetBuffer(0) ) );
                                    //AfxMessageBox( showstat );
                           } else {
                                    nstatus = 0;
                           }

                           CString IP;

                           if (npos != -1 && npos2 != -1 && npos2 >= npos + 3 ) {
                                    IP = response.Mid(npos+3);
                                    IP = IP.Left( npos2 - npos - 3 );
                           } else {
                                    IP = "";
                           }
                           //AfxMessageBox( IP );

                           IP.Replace("^", ""); // strip out EOM character, I use caret (^) as an informal end of message marker at times


                           OnlineResults *por = new OnlineResults( online_chk_vector[n].chat_id, online_chk_vector[n].hitem, 
                                                      IP.GetBuffer(0), true, nstatus);

                           // thread safe way to return value, post to a windows message
                           ::PostMessage(*phwnd, WM_SHOW_ONLINE_STATUS, (WPARAM)por, 0); 

                  } else {

                           OnlineResults *por = new OnlineResults( online_chk_vector[n].chat_id, online_chk_vector[n].hitem, 
                                                      "", false, 0 );

                           // thread safe way to return value, post to a windows message
                           ::PostMessage(*phwnd, WM_SHOW_ONLINE_STATUS, (WPARAM)por, 0); 

                  }

         } 

         delete pMsgInfo;

         g_getting_online_status = false;

         return 0;

}

ChatItemInfo::ChatItemInfo()
{
         this->chat_id = 0;
         this->create_time = "";
         this->msg = "";
         this->ntype = UNKNOWN;
         this->time_received = "";
         this->nickname = "";
         this->icon_id = 0;
         this->bPendingMsgs = false;

}

ChatItemInfo::ChatItemInfo(unsigned long chat_id, TypeInfo ntype, CString msg, CString create_time,
                                                         CString time_received, CString nickname, int icon_id ) 
{

         this->chat_id = chat_id;
         this->create_time = create_time.GetBuffer(0);
         this->msg = msg.GetBuffer(0);
         this->ntype = ntype;
         this->time_received = time_received.GetBuffer(0);
         this->nickname = nickname.GetBuffer(0);
         this->icon_id = icon_id;
         this->bPendingMsgs = false;

}

ChatItemInfo::ChatItemInfo(unsigned long tchat_id, TypeInfo ntype, CString msg, CString create_time)
{

         this->chat_id = tchat_id;
         this->create_time = create_time.GetBuffer(0);
         this->msg = msg.GetBuffer(0);
         this->ntype = ntype;
         this->time_received = "";
         this->nickname = "";
         this->icon_id = 0;
         this->bPendingMsgs = false;


}

TreeGroupInfo::TreeGroupInfo(CString tlabel, HTREEITEM thtItem)
{
         label = tlabel;
         htItem = thtItem;
}

TreeGroupInfo::TreeGroupInfo(char *tlabel, HTREEITEM thtItem)
{
         label = tlabel;
         htItem = thtItem;
}


CString ChatItemInfo::TypeDescrip(TypeInfo s) 
{
         CString temp;
         if (s==UNKNOWN) { temp = "Unknown Type"; }
         if (s==CHAT_CONTACT) { temp = "Chat Contact"; }
         if (s==GROUP) { temp = "Group" ; }
         if (s==SYSTEM_MSG) { temp = "System Message"; }
         if (s==SYSTEM_GROUP) { temp = "System Group" ; }
         if (s==PENDING_CONTACTS_GROUP) { temp = "Pending Contacts Group"; }
         if (s==INCOMING_CONTACT_REQUEST) { temp = "Incoming Contact Request"; }
         if (s==OUTGOING_CONTACT_REQUEST) { temp = "Outgoing Contact Request"; }
         return temp;
}

                  

MessageInfo::MessageInfo()
{

         this->ntype = UNKNOWN;
         this->chat_id = 0L;
         this->sender_id = 0L;
         this->nickname = "";
         this->msg = "";
         this->icon_id = 0;
         this->backcolor = "";
         this->n_online_status = CSecuresockDlg::ACTIVE;

}

MessageInfo::MessageInfo(int ntype, unsigned long chat_id, unsigned long sender_id, CString nickname,
                                                                        CString msg, int icon_id, char *pbackcolor)
{

         this->ntype = ntype;
         this->chat_id = chat_id;
         this->sender_id = sender_id;
         this->nickname = nickname.GetBuffer(0);
         this->msg = msg.GetBuffer(0);
         this->icon_id = icon_id;
         if (pbackcolor)
                  this->backcolor = pbackcolor;
         else
                  this->backcolor = "";

         this->n_online_status = CSecuresockDlg::ACTIVE;

}


BOOL CSecuresockDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
         // TODO: Add your message handler code here and/or call default
         // turn this on to set the main cursor to a blue arrow
         /*
         if (1) { // message == 512) {
                  SetCursor( AfxGetApp()->LoadCursor(IDC_CURSOR8));
                  //TRACE("%lu\n", message );
                  return TRUE;
         }
         */

         return CDialog::OnSetCursor(pWnd, nHitTest, message);

}

TreeStatusHelper::TreeStatusHelper(HTREEITEM hitem, unsigned long chat_id) 
{
         this->hitem = hitem;
         this->chat_id = chat_id;
}

OnlineResults::OnlineResults(unsigned long chat_id, HTREEITEM hitem, 
                                                      char *IP, bool bOnline, int nstatus)
{
         this->chat_id = chat_id;
         this->hitem = hitem;
         this->IP = IP;
         this->bOnline = bOnline;
         this->nstatus = nstatus;

}

HWND GetMainDlgHWND() { return g_md_hwnd; }
void SetMainDlgHWND(HWND x) { g_md_hwnd = x; }
int GetMyOnlineStatus() { return g_i_mystatus; }
void SetMyOnlineStatus(int status) { g_i_mystatus = status; }