Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

GroupDlg.cpp (16420B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 // GroupDlg.cpp : implementation file
     23 //
     24 
     25 #include "stdafx.h"
     26 #include "Radiant.h"
     27 #include "GroupDlg.h"
     28 #include "NameDlg.h"
     29 
     30 #ifdef _DEBUG
     31 #define new DEBUG_NEW
     32 #undef THIS_FILE
     33 static char THIS_FILE[] = __FILE__;
     34 #endif
     35 
     36 #define IMG_PATCH 0
     37 #define IMG_BRUSH 1
     38 #define IMG_GROUP 2
     39 #define IMG_ENTITY 3
     40 #define IMG_ENTITYGROUP 4
     41 #define IMG_MODEL 5
     42 #define IMG_SCRIPT 6
     43 
     44 // misc group support
     45 #define MAX_GROUPS 4096
     46 #define GROUP_DELIMETER '@'
     47 #define GROUPNAME "QER_Group_%i"
     48 
     49 CGroupDlg g_wndGroup;
     50 CGroupDlg *g_pGroupDlg = &g_wndGroup;
     51 
     52 // group_t are loaded / saved through "group_info" entities
     53 // they hold epairs for group settings and additionnal access info (tree nodes)
     54 group_t *g_pGroups = NULL;
     55 
     56 void Group_Add(entity_t *e)
     57 {
     58   group_t *g = (group_t*)qmalloc(sizeof(group_t));
     59   g->epairs = e->epairs;
     60   g->next = NULL;
     61   e->epairs = NULL;
     62   // create a new group node
     63   HTREEITEM hItem = g_wndGroup.m_wndTree.GetSelectedItem();
     64   TVINSERTSTRUCT tvInsert;
     65   memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
     66   tvInsert.item.iImage = IMG_GROUP;
     67   tvInsert.item.iSelectedImage = tvInsert.item.iImage;
     68 	//++timo wasat?
     69   // tvInsert.hParent = (hItem) ? hItem : m_hWorld;
     70   tvInsert.hParent = g_wndGroup.m_hWorld;
     71   tvInsert.hInsertAfter = NULL;
     72   tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
     73   char *pipo = ValueForKey(e->epairs, "group");
     74   tvInsert.item.pszText = _T(ValueForKey(g->epairs, "group"));
     75 	g->itemOwner = g_wndGroup.m_wndTree.InsertItem(&tvInsert);
     76   g->next = g_pGroups;
     77 	g_pGroups = g;
     78 }
     79 
     80 group_t* Group_Alloc(char *name)
     81 {
     82   group_t *g = (group_t*)qmalloc(sizeof(group_t));
     83 	SetKeyValue( g->epairs, "group", name );
     84   return g;
     85 }
     86 
     87 group_t* Group_ForName(const char * name)
     88 {
     89 	group_t *g = g_pGroups;
     90 	while (g != NULL)
     91 	{
     92 		if (strcmp( ValueForKey(g->epairs,"group"), name ) == 0)
     93 			break;
     94 		g = g->next;
     95 	}
     96 	return g;
     97 }
     98 
     99 void Group_AddToItem(brush_t *b, HTREEITEM item)
    100 {
    101   char cBuff[1024];
    102   int nImage = IMG_BRUSH;
    103 	if (!g_qeglobals.m_bBrushPrimitMode)
    104   {
    105     return;
    106   }
    107   const char *pName = NULL;
    108   const char *pNamed = Brush_GetKeyValue(b, "name");
    109  
    110   if (!b->owner || (b->owner == world_entity))
    111   {
    112     if (b->patchBrush) 
    113     {
    114       pName = "Generic Patch";
    115       nImage = IMG_PATCH;
    116     } 
    117     else 
    118     {
    119       pName = "Generic Brush";
    120       nImage = IMG_BRUSH;
    121     }
    122   } 
    123   else 
    124   {
    125     pName = b->owner->eclass->name;
    126     if (b->owner->eclass->fixedsize) 
    127     {
    128       nImage = IMG_ENTITY;
    129     } 
    130     else 
    131     {
    132       nImage = IMG_ENTITYGROUP;
    133     }
    134   }
    135 
    136   strcpy(cBuff, pName);
    137 
    138   TVINSERTSTRUCT tvInsert;
    139   memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
    140   tvInsert.item.iImage = (b->patchBrush) ? IMG_PATCH : IMG_BRUSH;
    141   tvInsert.item.iSelectedImage = tvInsert.item.iImage;
    142   tvInsert.hParent = item;
    143   tvInsert.hInsertAfter = NULL;
    144   tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
    145   tvInsert.item.pszText = cBuff;
    146   HTREEITEM itemNew = g_pGroupDlg->m_wndTree.InsertItem(&tvInsert);
    147   g_pGroupDlg->m_wndTree.SetItemData(itemNew, reinterpret_cast<DWORD>(b));
    148   b->itemOwner = itemNew;
    149   g_pGroupDlg->m_wndTree.RedrawWindow();
    150 
    151 }
    152 
    153 void Group_RemoveBrush(brush_t *b)
    154 {
    155 	if (!g_qeglobals.m_bBrushPrimitMode)
    156 	{
    157 		return;
    158 	}
    159 	if (b->itemOwner)
    160 	{
    161 		g_pGroupDlg->m_wndTree.DeleteItem(b->itemOwner);
    162 		b->itemOwner = NULL;
    163 		g_pGroupDlg->m_wndTree.RedrawWindow();
    164 	}
    165 	DeleteKey(b->epairs, "group");
    166 }
    167 
    168 void Group_AddToWorld(brush_t *b)
    169 {
    170 	if (!g_qeglobals.m_bBrushPrimitMode)
    171   {
    172     return;
    173   }
    174   HTREEITEM itemParent = g_pGroupDlg->m_wndTree.GetRootItem();
    175   Group_AddToItem(b, itemParent);
    176 }
    177 
    178 void Group_AddToProperGroup(brush_t *b)
    179 {
    180 	if (!g_qeglobals.m_bBrushPrimitMode)
    181 	{
    182 		return;
    183 	}
    184 	// NOTE: we do a local copy of the "group" key because it gets erased by Group_RemoveBrush
    185 	const char *pGroup = Brush_GetKeyValue(b, "group");
    186   // remove the entry in the tree if there's one
    187   if (b->itemOwner)
    188   {
    189 		g_pGroupDlg->m_wndTree.DeleteItem(b->itemOwner);
    190 		b->itemOwner = NULL;
    191 		g_pGroupDlg->m_wndTree.RedrawWindow();
    192   }
    193 
    194 	if (*pGroup != 0)
    195 	{
    196 		// find the item
    197 		group_t *g = Group_ForName(pGroup);
    198 		if (g)
    199 			Group_AddToItem(b, g->itemOwner);
    200 #ifdef _DEBUG
    201 		else
    202 			Sys_Printf("WARNING: unexpected Group_ForName not found in Group_AddToProperGroup\n");
    203 #endif
    204 	}
    205 	else
    206 	{
    207 		Group_AddToWorld(b);
    208 	}
    209 }
    210 
    211 void Group_AddToSelected(brush_t *b)
    212 {
    213 	if (!g_qeglobals.m_bBrushPrimitMode)
    214   {
    215     return;
    216   }
    217   HTREEITEM hItem = g_pGroupDlg->m_wndTree.GetSelectedItem();
    218   if (hItem == NULL)
    219   {
    220     hItem = g_pGroupDlg->m_wndTree.GetRootItem();
    221   }
    222   Group_AddToItem(b, hItem);
    223 }
    224 
    225 void Group_Save(FILE *f)
    226 {
    227 	group_t *g = g_pGroups;
    228 	while (g)
    229   {
    230     fprintf(f,"{\n\"classname\" \"group_info\"\n\"group\" \"%s\"\n}\n", ValueForKey( g->epairs, "group" ));
    231     g = g->next;
    232   }
    233 }
    234 
    235 void Group_Init()
    236 {
    237 	if (!g_qeglobals.m_bBrushPrimitMode)
    238   {
    239     return;
    240   }
    241 	// start by cleaning everything
    242   // clean the groups
    243   //++timo FIXME: we leak, delete the groups on the way (I don't have time to do it now)
    244 #ifdef _DEBUG
    245   Sys_Printf("TODO: fix leak in Group_Init\n");
    246 #endif
    247   group_t *g = g_pGroups;
    248   while (g)
    249   {
    250     epair_t *ep,*enext;
    251 	  for (ep = g->epairs ; ep ; ep=enext )
    252 	  {
    253 		  enext = ep->next;
    254 		  free (ep->key);
    255 		  free (ep->value);
    256 		  free (ep);
    257 	  }
    258     g = g->next;
    259   }
    260   g_pGroups = NULL;
    261 	g_wndGroup.m_wndTree.DeleteAllItems();
    262   TVINSERTSTRUCT tvInsert;
    263   memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
    264   tvInsert.hParent = NULL;
    265   tvInsert.hInsertAfter = NULL;
    266   tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
    267   tvInsert.item.pszText = _T("World");
    268   tvInsert.item.iImage = IMG_GROUP;
    269   tvInsert.item.iSelectedImage = IMG_GROUP;
    270   HTREEITEM hWorld = g_wndGroup.m_wndTree.InsertItem(&tvInsert);
    271 	// walk through all the brushes, remove the itemOwner key and add them back where they belong
    272 	brush_t *b;
    273 	for (b = active_brushes.next; b != &active_brushes; b = b->next)
    274 	{
    275 		b->itemOwner = NULL;
    276 		Group_AddToProperGroup(b);
    277 	}
    278 	for (b = selected_brushes.next ; b != &selected_brushes ; b = b->next)
    279 	{
    280 		b->itemOwner = NULL;
    281 		Group_AddToProperGroup(b);
    282 	}
    283 }
    284 
    285 // scan through world_entity for groups in this map?
    286 // we use GROUPNAME "QER_group_%i" to look for existing groups and their naming
    287 //++timo FIXME: is this actually needed for anything?
    288 void Group_GetListFromWorld(CStringArray *pArray)
    289 {
    290 	if (!g_qeglobals.m_bBrushPrimitMode)
    291   {
    292     return;
    293   }
    294 
    295   if (world_entity == NULL)
    296   {
    297     return;
    298   }
    299 
    300   pArray->RemoveAll();
    301   char cBuff[1024];
    302   for (int i =0; i < MAX_GROUPS; i++)
    303   {
    304     sprintf(cBuff, GROUPNAME, i);
    305     char *pGroup = ValueForKey(world_entity, cBuff);
    306     if (pGroup && strlen(pGroup) > 0)
    307     {
    308       pArray->Add(pGroup);
    309     }
    310     else
    311     {
    312       break;
    313     }
    314   }
    315 }
    316 
    317 void Group_RemoveListFromWorld()
    318 {
    319 	if (!g_qeglobals.m_bBrushPrimitMode)
    320   {
    321     return;
    322   }
    323   CStringArray array;
    324   Group_GetListFromWorld(&array);
    325   int nCount = array.GetSize();
    326   for (int i = 0; i < nCount; i++)
    327   {
    328     DeleteKey(world_entity, array.GetAt(i));
    329   }
    330 }
    331 
    332 /*
    333 void Group_SetListToWorld(CStringArray *pArray)
    334 {
    335 	if (!g_qeglobals.m_bBrushPrimitMode)
    336   {
    337     return;
    338   }
    339   char cBuff[1024];
    340   Group_RemoveListFromWorld();
    341   int nCount = pArray->GetSize();
    342   for (int i = 0; i < nCount; i++)
    343   {
    344     sprintf(cBuff, GROUPNAME, i);
    345     SetKeyValue(world_entity, cBuff, pArray->GetAt(i));
    346   }
    347 }
    348 */
    349 
    350 int CountChar(const char *p, char c)
    351 {
    352   int nCount = 0;
    353   int nLen = strlen(p)-1;
    354   while (nLen-- >= 0)
    355   {
    356     if (p[nLen] == c)
    357     {
    358       nCount++;
    359     }
    360   }
    361   return nCount;
    362 }
    363 
    364 /*
    365 // this is not very efficient but should get the job done
    366 // as our trees should never be too big
    367 void Group_BuildTree(CTreeCtrl *pTree)
    368 {
    369 	if (!g_qeglobals.m_bBrushPrimitMode)
    370   {
    371     return;
    372   }
    373   CStringArray array;
    374   int i;
    375   CString strTemp;
    376   CString strRight;
    377 
    378   //++timo WARNING: this is very dangerous! delete all tree items, without checking the brushes
    379   pTree->DeleteAllItems();
    380   TVINSERTSTRUCT tvInsert;
    381   memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
    382   tvInsert.hParent = NULL;
    383   tvInsert.hInsertAfter = NULL;
    384   tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
    385   tvInsert.item.pszText = _T("World");
    386   tvInsert.item.iImage = IMG_GROUP;
    387   tvInsert.item.iSelectedImage = IMG_GROUP;
    388   HTREEITEM hWorld = pTree->InsertItem(&tvInsert);
    389 
    390   Group_GetListFromWorld(&array);
    391 
    392   // groups use @ to delimit levels, the number of @ signs
    393   // start with ROOT item
    394   // nothing is a peer with world, it is ancestor to everything 
    395   // expects things in order so first entry should be a 2nd level item
    396   HTREEITEM itemParent = pTree->GetRootItem();
    397   HTREEITEM itemLast = itemParent;
    398   int nCount = array.GetSize();
    399   int nLastLevel = 1;
    400   for (i = 0; i < nCount; i++)
    401   {
    402     strTemp = array.GetAt(i);
    403     int nLevel = CountChar(strTemp, GROUP_DELIMETER);
    404     if (nLevel < nLastLevel)
    405     {
    406       int nLevelsUp = nLastLevel - nLevel;
    407       while (nLevelsUp-- > 0)
    408       {
    409         itemParent = pTree->GetParentItem(itemParent);
    410       }
    411     }
    412     else if (nLevel > nLastLevel)
    413     {
    414       itemParent = itemLast;
    415     }
    416     nLastLevel = nLevel;
    417     char *pLast = strrchr(strTemp, GROUP_DELIMETER);
    418     pLast++;
    419     itemLast = pTree->InsertItem(pLast, itemParent);
    420   }
    421 }
    422 */
    423 
    424 void DecomposeSiblingList(const char *p, CStringArray *pArray, CTreeCtrl *pTree, HTREEITEM itemChild)
    425 {
    426   CString str = p;
    427   str += GROUP_DELIMETER;
    428   while (itemChild)
    429   {
    430     CString strAdd = str;
    431     strAdd += pTree->GetItemText(itemChild);
    432     // do not want to add brushes or things, just groups 
    433     if (pTree->GetItemData(itemChild) == 0)
    434     {
    435       pArray->Add(strAdd);
    436     }
    437     if (pTree->ItemHasChildren(itemChild))
    438     {
    439       HTREEITEM itemOffspring = pTree->GetChildItem(itemChild);
    440       DecomposeSiblingList(strAdd, pArray, pTree, itemOffspring); 
    441     }
    442     itemChild = pTree->GetNextSiblingItem(itemChild);
    443   }
    444 }
    445 
    446 /*
    447 void Group_DecomposeTree(CTreeCtrl *pTree)
    448 {
    449 	if (!g_qeglobals.m_bBrushPrimitMode)
    450   {
    451     return;
    452   }
    453   CStringArray array;
    454   HTREEITEM itemParent = pTree->GetRootItem();
    455   if (pTree->ItemHasChildren(itemParent))
    456   {
    457     HTREEITEM itemChild = pTree->GetChildItem(itemParent);
    458     DecomposeSiblingList(pTree->GetItemText(itemParent), &array, pTree, itemChild);
    459   }
    460   Group_SetListToWorld(&array);
    461 }
    462 */
    463 
    464 /////////////////////////////////////////////////////////////////////////////
    465 // CGroupDlg dialog
    466 
    467 
    468 CGroupDlg::CGroupDlg(CWnd* pParent /*=NULL*/)
    469 	: CDialog(CGroupDlg::IDD, pParent)
    470 {
    471 	//{{AFX_DATA_INIT(CGroupDlg)
    472 		// NOTE: the ClassWizard will add member initialization here
    473 	//}}AFX_DATA_INIT
    474 }
    475 
    476 
    477 void CGroupDlg::DoDataExchange(CDataExchange* pDX)
    478 {
    479 	CDialog::DoDataExchange(pDX);
    480 	//{{AFX_DATA_MAP(CGroupDlg)
    481 	DDX_Control(pDX, IDC_TREE_GROUP, m_wndTree);
    482 	DDX_Control(pDX, IDC_BTN_EDIT, m_wndEdit);
    483 	DDX_Control(pDX, IDC_BTN_DEL, m_wndDel);
    484 	DDX_Control(pDX, IDC_BTN_ADD, m_wndAdd);
    485 	//}}AFX_DATA_MAP
    486 }
    487 
    488 
    489 BEGIN_MESSAGE_MAP(CGroupDlg, CDialog)
    490 	//{{AFX_MSG_MAP(CGroupDlg)
    491 	ON_WM_SIZE()
    492 	ON_BN_CLICKED(IDC_BTN_ADD, OnBtnAdd)
    493 	ON_BN_CLICKED(IDC_BTN_DEL, OnBtnDel)
    494 	ON_BN_CLICKED(IDC_BTN_EDIT, OnBtnEdit)
    495 	ON_NOTIFY(NM_RCLICK, IDC_TREE_GROUP, OnRclickTreeGroup)
    496 	ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE_GROUP, OnEndlabeleditTreeGroup)
    497 	ON_NOTIFY(NM_CLICK, IDC_TREE_GROUP, OnClickTreeGroup)
    498 	ON_NOTIFY(TVN_SETDISPINFO, IDC_TREE_GROUP, OnSetdispinfoTreeGroup)
    499 	ON_NOTIFY(TVN_BEGINDRAG, IDC_TREE_GROUP, OnBegindragTreeGroup)
    500 	//}}AFX_MSG_MAP
    501 END_MESSAGE_MAP()
    502 
    503 /////////////////////////////////////////////////////////////////////////////
    504 // CGroupDlg message handlers
    505 
    506 void CGroupDlg::OnSize(UINT nType, int cx, int cy) 
    507 {
    508 	CDialog::OnSize(nType, cx, cy);
    509 	CRect rct;
    510   GetClientRect(rct);
    511 
    512   if ( m_wndAdd.GetSafeHwnd())
    513   {
    514     //all borders at 4, spacing at 6
    515     CRect rctButton;
    516     m_wndAdd.GetWindowRect(rctButton);
    517     int nWidth = rctButton.Width();
    518     int nHeight = rctButton.Height();
    519 
    520     int nTop = rct.Height() - nHeight - 4;
    521 
    522     m_wndAdd.SetWindowPos(NULL, 4, nTop, 0, 0, SWP_NOSIZE);
    523     m_wndEdit.SetWindowPos(NULL, 8 + nWidth , nTop, 0, 0, SWP_NOSIZE);
    524     m_wndDel.SetWindowPos(NULL, 12 + (nWidth * 2), nTop, 0, 0, SWP_NOSIZE);
    525     rct.bottom = nTop;
    526     m_wndTree.SetWindowPos(NULL, rct.left + 4, rct.top + 4, rct.Width() - 8, rct.Height() - 8, SWP_SHOWWINDOW);
    527   }
    528 }
    529 
    530 BOOL CGroupDlg::OnInitDialog() 
    531 {
    532 	CDialog::OnInitDialog();
    533 	m_imgList.Create(IDB_BITMAP_GROUPS, 16, 0, ILC_COLOR);
    534 	m_wndTree.SetImageList(&m_imgList, TVSIL_NORMAL);
    535 	InitGroups();
    536 	return TRUE;  // return TRUE unless you set the focus to a control
    537 	// EXCEPTION: OCX Property Pages should return FALSE
    538 }
    539 
    540 void CGroupDlg::InitGroups()
    541 {
    542 	Group_Init();
    543 }
    544 
    545 // add a new group, put all selected brushes into the group
    546 void CGroupDlg::OnBtnAdd() 
    547 {
    548   CNameDlg dlg("New Group", this);
    549   if (dlg.DoModal() == IDOK)
    550   {
    551 		// create a new group node
    552     HTREEITEM hItem = m_wndTree.GetSelectedItem();
    553     TVINSERTSTRUCT tvInsert;
    554     memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
    555     tvInsert.item.iImage = IMG_GROUP;
    556     tvInsert.item.iSelectedImage = tvInsert.item.iImage;
    557 		//++timo wasat?
    558     // tvInsert.hParent = (hItem) ? hItem : m_hWorld;
    559     tvInsert.hParent = m_hWorld;
    560     tvInsert.hInsertAfter = NULL;
    561     tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
    562     tvInsert.item.pszText = _T(dlg.m_strName.GetBuffer(0));
    563 		// create a new group
    564 		group_t *g = Group_Alloc( dlg.m_strName.GetBuffer(0) );
    565 		g->itemOwner = m_wndTree.InsertItem(&tvInsert);
    566 		g->next = g_pGroups;
    567 		g_pGroups = g;
    568 		// now add the selected brushes
    569 		// NOTE: it would be much faster to give the group_t for adding
    570 		// but Select_AddToGroup is the standard way for all other cases
    571 		Select_AddToGroup( dlg.m_strName.GetBuffer(0) );
    572   }
    573 }
    574 
    575 void CGroupDlg::OnBtnDel() 
    576 {
    577 }
    578 
    579 void CGroupDlg::OnBtnEdit() 
    580 {
    581 }
    582 
    583 BOOL CGroupDlg::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult) 
    584 {
    585 	return CDialog::OnChildNotify(message, wParam, lParam, pLResult);
    586 }
    587 
    588 BOOL CGroupDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
    589 {
    590   return CDialog::OnNotify(wParam, lParam, pResult);
    591 }
    592 
    593 void CGroupDlg::OnRclickTreeGroup(NMHDR* pNMHDR, LRESULT* pResult) 
    594 {
    595 	// TODO: Add your control notification handler code here
    596 	
    597 	*pResult = 0;
    598 }
    599 
    600 void CGroupDlg::OnEndlabeleditTreeGroup(NMHDR* pNMHDR, LRESULT* pResult) 
    601 {
    602 	TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
    603   const char *pText = pTVDispInfo->item.pszText;
    604   if (pText && strlen(pText) > 0)
    605   {
    606     HTREEITEM item = pTVDispInfo->item.hItem;
    607     if (m_wndTree.GetRootItem() != item)
    608     {
    609       m_wndTree.SetItemText(item, pText);
    610       if (pTVDispInfo->item.iImage != IMG_GROUP)
    611       {
    612         // if it is an entity
    613       }
    614     }
    615     else
    616     {
    617       Sys_Printf("Cannot rename the world\n");
    618     }
    619   }
    620   m_wndTree.RedrawWindow();
    621 	*pResult = 0;
    622 }
    623 
    624 void CGroupDlg::OnClickTreeGroup(NMHDR* pNMHDR, LRESULT* pResult) 
    625 {
    626 	// TODO: Add your control notification handler code here
    627 	
    628 	*pResult = 0;
    629 }
    630 
    631 void CGroupDlg::OnSetdispinfoTreeGroup(NMHDR* pNMHDR, LRESULT* pResult) 
    632 {
    633 	TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
    634 	// TODO: Add your control notification handler code here
    635 	
    636 	*pResult = 0;
    637 }
    638 
    639 void CGroupDlg::OnCancel()
    640 {
    641   TreeView_EndEditLabelNow(m_wndTree.GetSafeHwnd(), TRUE);
    642 }
    643 
    644 void CGroupDlg::OnOK()
    645 {
    646   TreeView_EndEditLabelNow(m_wndTree.GetSafeHwnd(), FALSE);
    647 }
    648 
    649 void CGroupDlg::OnBegindragTreeGroup(NMHDR* pNMHDR, LRESULT* pResult) 
    650 {
    651 	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    652 	// TODO: Add your control notification handler code here
    653 	
    654 	*pResult = 0;
    655 }