]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/decl/DialogDeclBrowser.cpp
hello world
[icculus/iodoom3.git] / neo / tools / decl / DialogDeclBrowser.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "../../sys/win32/rc/DeclEditor_resource.h"
33 #include "../../sys/win32/rc/ScriptEditor_resource.h"
34
35 #include "../comafx/CPathTreeCtrl.h"
36 #include "../script/DialogScriptEditor.h"
37 #include "DialogDeclBrowser.h"
38 #include "DialogDeclEditor.h"
39 #include "DialogDeclNew.h"
40
41 #ifdef ID_DEBUG_MEMORY
42 #undef new
43 #undef DEBUG_NEW
44 #define DEBUG_NEW new
45 #endif
46
47 const int DECLTYPE_SHIFT                        = 24;
48 const int DECLINDEX_MASK                        = ( 1 << DECLTYPE_SHIFT ) - 1;
49 const int DECLTYPE_SCRIPT                       = 126;
50 const int DECLTYPE_GUI                          = 127;
51
52 #define GetIdFromTypeAndIndex( type, index )            ( ( (int)type << DECLTYPE_SHIFT ) | index )
53 #define GetTypeFromId( id )                                                     ( (declType_t) ( (int)id >> DECLTYPE_SHIFT ) )
54 #define GetIndexFromId( id )                                            ( (int)id & DECLINDEX_MASK )
55
56 toolTip_t DialogDeclBrowser::toolTips[] = {
57         { IDC_DECLBROWSER_TREE, "decl browser" },
58         { IDC_DECLBROWSER_EDIT_SEARCH_NAMES, "search for declarations with matching name, use meta characters: *, ? and [abc...]" },
59         { IDC_DECLBROWSER_EDIT_SEARCH_TEXT, "search for declarations containing text" },
60         { IDC_DECLBROWSER_BUTTON_FIND, "find declarations matching the search strings" },
61         { IDC_DECLBROWSER_BUTTON_EDIT, "edit selected declaration" },
62         { IDC_DECLBROWSER_BUTTON_NEW, "create new declaration" },
63         { IDC_DECLBROWSER_BUTTON_RELOAD, "reload declarations" },
64         { IDOK, "ok" },
65         { IDCANCEL, "cancel" },
66         { 0, NULL }
67 };
68
69
70 static DialogDeclBrowser *g_DeclDialog = NULL;
71
72
73 IMPLEMENT_DYNAMIC(DialogDeclBrowser, CDialog)
74
75 /*
76 ================
77 DialogDeclBrowser::DialogDeclBrowser
78 ================
79 */
80 DialogDeclBrowser::DialogDeclBrowser( CWnd* pParent /*=NULL*/ )
81         : CDialog(DialogDeclBrowser::IDD, pParent)
82         , m_pchTip(NULL)
83         , m_pwchTip(NULL)
84 {
85 }
86
87 /*
88 ================
89 DialogDeclBrowser::~DialogDeclBrowser
90 ================
91 */
92 DialogDeclBrowser::~DialogDeclBrowser() {
93         delete m_pwchTip;
94         delete m_pchTip;
95 }
96
97 /*
98 ================
99 DialogDeclBrowser::DoDataExchange
100 ================
101 */
102 void DialogDeclBrowser::DoDataExchange(CDataExchange* pDX) {
103         CDialog::DoDataExchange(pDX);
104         //{{AFX_DATA_MAP(DialogDeclBrowser)
105         DDX_Control(pDX, IDC_DECLBROWSER_TREE, declTree);
106         DDX_Control(pDX, IDC_DECLBROWSER_STATIC_SEARCH_NAMES, findNameStatic);
107         DDX_Control(pDX, IDC_DECLBROWSER_STATIC_SEARCH_TEXT, findTextStatic);
108         DDX_Control(pDX, IDC_DECLBROWSER_EDIT_SEARCH_NAMES, findNameEdit);
109         DDX_Control(pDX, IDC_DECLBROWSER_EDIT_SEARCH_TEXT, findTextEdit);
110         DDX_Control(pDX, IDC_DECLBROWSER_BUTTON_FIND, findButton);
111         DDX_Control(pDX, IDC_DECLBROWSER_BUTTON_EDIT, editButton);
112         DDX_Control(pDX, IDC_DECLBROWSER_BUTTON_NEW, newButton);
113         DDX_Control(pDX, IDC_DECLBROWSER_BUTTON_RELOAD, reloadButton);
114         DDX_Control(pDX, IDCANCEL, cancelButton);
115         //}}AFX_DATA_MAP
116 }
117
118 /*
119 ================
120 DialogDeclBrowser::AddDeclTypeToTree
121 ================
122 */
123 template< class type >
124 int idListDeclSortCompare( const type *a, const type *b ) {
125         return idStr::IcmpPath( (*a)->GetName(), (*b)->GetName() );
126 }
127
128 void DialogDeclBrowser::AddDeclTypeToTree( declType_t type, const char *root, CPathTreeCtrl &tree ) {
129         int i;
130         idList<const idDecl*> decls;
131         idPathTreeStack stack;
132         idStr rootStr, declName;
133
134         decls.SetNum( declManager->GetNumDecls( type ) );
135         for ( i = 0; i < decls.Num(); i++ ) {
136                 decls[i] = declManager->DeclByIndex( type, i, false );
137         }
138         decls.Sort( idListDeclSortCompare );
139
140         rootStr = root;
141         rootStr += "/";
142
143         stack.PushRoot( NULL );
144
145         for ( i = 0; i < decls.Num(); i++) {
146                 declName = rootStr + decls[i]->GetName();
147
148                 declName.BackSlashesToSlashes();
149                 declName.Strip(' ');
150
151                 tree.AddPathToTree( declName, GetIdFromTypeAndIndex( type, decls[i]->Index() ), stack );
152         }
153 }
154
155 /*
156 ================
157 DialogDeclBrowser::AddScriptsToTree
158 ================
159 */
160 void DialogDeclBrowser::AddScriptsToTree( CPathTreeCtrl &tree ) {
161         int i;
162         idPathTreeStack stack;
163         idStr scriptName;
164         idFileList *files;
165
166         files = fileSystem->ListFilesTree( "script", ".script", true );
167
168         stack.PushRoot( NULL );
169
170         for ( i = 0; i < files->GetNumFiles(); i++) {
171                 scriptName = files->GetFile( i );
172
173                 scriptName.BackSlashesToSlashes();
174                 scriptName.StripFileExtension();
175
176                 tree.AddPathToTree( scriptName, GetIdFromTypeAndIndex( DECLTYPE_SCRIPT, i ), stack );
177         }
178
179         fileSystem->FreeFileList( files );
180 }
181
182 /*
183 ================
184 DialogDeclBrowser::AddGUIsToTree
185 ================
186 */
187 void DialogDeclBrowser::AddGUIsToTree( CPathTreeCtrl &tree ) {
188         int i;
189         idPathTreeStack stack;
190         idStr scriptName;
191         idFileList *files;
192
193         files = fileSystem->ListFilesTree( "guis", ".gui", true );
194
195         stack.PushRoot( NULL );
196
197         for ( i = 0; i < files->GetNumFiles(); i++) {
198                 scriptName = files->GetFile( i );
199
200                 scriptName.BackSlashesToSlashes();
201                 scriptName.StripFileExtension();
202
203                 tree.AddPathToTree( scriptName, GetIdFromTypeAndIndex( DECLTYPE_GUI, i ), stack );
204         }
205
206         fileSystem->FreeFileList( files );
207 }
208
209 /*
210 ================
211 DialogDeclBrowser::InitBaseDeclTree
212 ================
213 */
214 void DialogDeclBrowser::InitBaseDeclTree( void ) {
215         int i;
216
217         numListedDecls = 0;
218         baseDeclTree.DeleteAllItems();
219
220         for ( i = 0; i < declManager->GetNumDeclTypes(); i++ ) {
221                 AddDeclTypeToTree( (declType_t)i, declManager->GetDeclNameFromType( (declType_t)i ), baseDeclTree );
222         }
223
224         AddScriptsToTree( baseDeclTree );
225         AddGUIsToTree( baseDeclTree );
226 }
227
228 /*
229 ================
230 DialogDeclBrowser::GetDeclName
231 ================
232 */
233 void DialogDeclBrowser::GetDeclName( HTREEITEM item, idStr &typeName, idStr &declName ) const {
234         HTREEITEM parent;
235         idStr itemName;
236
237         declName.Clear();
238         for( parent = declTree.GetParentItem( item ); parent; parent = declTree.GetParentItem( parent ) ) {
239                 itemName = declTree.GetItemText( item );
240                 declName = itemName + "/" + declName;
241                 item = parent;
242         }
243         declName.Strip( '/' );
244         typeName = declTree.GetItemText( item );
245 }
246
247 /*
248 ================
249 DialogDeclBrowser::GetDeclFromTreeItem
250 ================
251 */
252 const idDecl *DialogDeclBrowser::GetDeclFromTreeItem( HTREEITEM item ) const {
253         int id, index;
254         declType_t type;
255         const idDecl *decl;
256
257         if ( declTree.GetChildItem( item ) ) {
258                 return NULL;
259         }
260
261         id = declTree.GetItemData( item );
262         type = GetTypeFromId( id );
263         index = GetIndexFromId( id );
264
265         if ( type < 0 || type >= declManager->GetNumDeclTypes() ) {
266                 return NULL;
267         }
268
269         decl = declManager->DeclByIndex( type, index, false );
270
271         return decl;
272 }
273
274 /*
275 ================
276 DialogDeclBrowser::GetSelectedDecl
277 ================
278 */
279 const idDecl *DialogDeclBrowser::GetSelectedDecl( void ) const {
280         return GetDeclFromTreeItem( declTree.GetSelectedItem() );
281 }
282
283 /*
284 ================
285 DialogDeclBrowser::EditSelected
286 ================
287 */
288 void DialogDeclBrowser::EditSelected( void ) const {
289         int id, index;
290         idDict spawnArgs;
291         const idDecl *decl;
292         declType_t type;
293         HTREEITEM item;
294
295         item = declTree.GetSelectedItem();
296
297         if ( declTree.GetChildItem( item ) ) {
298                 return;
299         }
300
301         id = declTree.GetItemData( item );
302         type = GetTypeFromId( id );
303         index = GetIndexFromId( id );
304
305         switch( type ) {
306                 case DECL_AF: {
307                         decl = declManager->DeclByIndex( type, index, false );
308                         spawnArgs.Set( "articulatedFigure", decl->GetName() );
309                         AFEditorInit( &spawnArgs );
310                         break;
311                 }
312                 case DECL_PARTICLE: {
313                         decl = declManager->DeclByIndex( type, index, false );
314                         spawnArgs.Set( "model", decl->GetName() );
315                         ParticleEditorInit( &spawnArgs );
316                         break;
317                 }
318                 case DECL_PDA: {
319                         decl = declManager->DeclByIndex( type, index, false );
320                         spawnArgs.Set( "pda", decl->GetName() );
321                         PDAEditorInit( &spawnArgs );
322                         break;
323                 }
324                 case DECLTYPE_SCRIPT:
325                 case DECLTYPE_GUI: {
326                         idStr typeName, declName;
327                         GetDeclName( item, typeName, declName );
328                         DialogScriptEditor *scriptEditor;
329                         scriptEditor = new DialogScriptEditor;
330                         scriptEditor->Create( IDD_DIALOG_SCRIPTEDITOR, GetParent() );
331                         scriptEditor->OpenFile( typeName + "/" + declName + ( ( type == DECLTYPE_SCRIPT ) ? ".script" : ".gui" ) );
332                         scriptEditor->ShowWindow( SW_SHOW );
333                         scriptEditor->SetFocus();
334                         break;
335                 }
336                 default: {
337                         decl = declManager->DeclByIndex( type, index, false );
338                         DialogDeclEditor *declEditor;
339                         declEditor = new DialogDeclEditor;
340                         declEditor->Create( IDD_DIALOG_DECLEDITOR, GetParent() );
341                         declEditor->LoadDecl( const_cast<idDecl *>( decl ) );
342                         declEditor->ShowWindow( SW_SHOW );
343                         declEditor->SetFocus();
344                         break;
345                 }
346         }
347 }
348
349 /*
350 ================
351 DeclBrowserCompareDecl
352 ================
353 */
354 bool DeclBrowserCompareDecl( void *data, HTREEITEM item, const char *name ) {
355         return reinterpret_cast<DialogDeclBrowser *>(data)->CompareDecl( item, name );
356 }
357
358 /*
359 ================
360 DialogDeclBrowser::CompareDecl
361 ================
362 */
363 bool DialogDeclBrowser::CompareDecl( HTREEITEM item, const char *name ) const {
364         if ( findNameString.Length() ) {
365                 if ( !idStr::Filter( findNameString, name, false ) ) {
366                         return false;
367                 }
368         }
369
370         if ( findTextString.Length() ) {
371                 int id, index;
372                 declType_t type;
373
374                 id = declTree.GetItemData( item );
375                 type = GetTypeFromId( id );
376                 index = GetIndexFromId( id );
377
378                 if ( type == DECLTYPE_SCRIPT || type == DECLTYPE_GUI ) {
379                         // search for the text in the script or gui
380                         idStr text;
381                         void *buffer;
382                         if ( fileSystem->ReadFile( idStr( name ) + ( ( type == DECLTYPE_SCRIPT ) ? ".script" : ".gui" ), &buffer ) == -1 ) {
383                                 return false;
384                         }
385                         text = (char *) buffer;
386                         fileSystem->FreeFile( buffer );
387                         if ( text.Find( findTextString, false ) == -1 ) {
388                                 return false;
389                         }
390                 } else {
391                         // search for the text in the decl
392                         const idDecl *decl = declManager->DeclByIndex( type, index, false );
393                         char *declText = (char *)_alloca( ( decl->GetTextLength() + 1 ) * sizeof( char ) );
394                         decl->GetText( declText );
395                         if ( idStr::FindText( declText, findTextString, false ) == -1 ) {
396                                 return false;
397                         }
398                 }
399         }
400
401         return true;
402 }
403
404 /*
405 ================
406 DialogDeclBrowser::OnInitDialog
407 ================
408 */
409 BOOL DialogDeclBrowser::OnInitDialog()  {
410
411         com_editors |= EDITOR_DECL;
412
413         CDialog::OnInitDialog();
414
415         GetClientRect( initialRect );
416
417         statusBar.CreateEx( SBARS_SIZEGRIP, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, initialRect, this, AFX_IDW_STATUS_BAR );
418
419         baseDeclTree.Create( 0, initialRect, this, IDC_DECLBROWSER_BASE_TREE );
420
421         InitBaseDeclTree();
422
423         findNameString = "*";
424         findNameEdit.SetWindowText( findNameString );
425
426         findTextString = "";
427         findTextEdit.SetWindowText( findTextString );
428
429         numListedDecls = baseDeclTree.SearchTree( DeclBrowserCompareDecl, this, declTree );
430
431         statusBar.SetWindowText( va( "%d decls listed", numListedDecls ) );
432
433         EnableToolTips( TRUE );
434
435         return TRUE;  // return TRUE unless you set the focus to a control
436                       // EXCEPTION: OCX Property Pages should return FALSE
437 }
438
439 /*
440 ================
441 DeclBrowserInit
442 ================
443 */
444 void DeclBrowserInit( const idDict *spawnArgs ) {
445
446         if ( renderSystem->IsFullScreen() ) {
447                 common->Printf( "Cannot run the declaration editor in fullscreen mode.\n"
448                                         "Set r_fullscreen to 0 and vid_restart.\n" );
449                 return;
450         }
451
452         if ( g_DeclDialog == NULL ) {
453                 InitAfx();
454                 g_DeclDialog = new DialogDeclBrowser();
455         }
456
457         if ( g_DeclDialog->GetSafeHwnd() == NULL) {
458                 g_DeclDialog->Create( IDD_DIALOG_DECLBROWSER );
459 /*
460                 // FIXME: restore position
461                 CRect rct;
462                 g_DeclDialog->SetWindowPos( NULL, rct.left, rct.top, 0, 0, SWP_NOSIZE );
463 */
464         }
465
466         idKeyInput::ClearStates();
467
468         g_DeclDialog->ShowWindow( SW_SHOW );
469         g_DeclDialog->SetFocus();
470
471         if ( spawnArgs ) {
472         }
473 }
474
475 /*
476 ================
477 DeclBrowserRun
478 ================
479 */
480 void DeclBrowserRun( void ) {
481 #if _MSC_VER >= 1300
482         MSG *msg = AfxGetCurrentMessage();                      // TODO Robert fix me!!
483 #else
484         MSG *msg = &m_msgCur;
485 #endif
486
487         while( ::PeekMessage(msg, NULL, NULL, NULL, PM_NOREMOVE) ) {
488                 // pump message
489                 if ( !AfxGetApp()->PumpMessage() ) {
490                 }
491         }
492 }
493
494 /*
495 ================
496 DeclBrowserShutdown
497 ================
498 */
499 void DeclBrowserShutdown( void ) {
500         delete g_DeclDialog;
501         g_DeclDialog = NULL;
502 }
503
504 /*
505 ================
506 DeclBrowserReloadDeclarations
507 ================
508 */
509 void DeclBrowserReloadDeclarations( void ) {
510         if ( g_DeclDialog ) {
511                 g_DeclDialog->ReloadDeclarations();
512         }
513 }
514
515 /*
516 ================
517 DialogDeclBrowser::ReloadDeclarations
518 ================
519 */
520 void DialogDeclBrowser::ReloadDeclarations( void ) {
521         InitBaseDeclTree();
522         OnBnClickedFind();
523 }
524
525 BEGIN_MESSAGE_MAP(DialogDeclBrowser, CDialog)
526         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
527         ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
528         ON_WM_DESTROY()
529         ON_WM_ACTIVATE()
530         ON_WM_MOVE()
531         ON_WM_SIZE()
532         ON_WM_SIZING()
533         ON_WM_SETFOCUS()
534         ON_NOTIFY(TVN_SELCHANGED, IDC_DECLBROWSER_TREE, OnTreeSelChanged)
535         ON_NOTIFY(NM_DBLCLK, IDC_DECLBROWSER_TREE, OnTreeDblclk)
536         ON_BN_CLICKED(IDC_DECLBROWSER_BUTTON_FIND, OnBnClickedFind)
537         ON_BN_CLICKED(IDC_DECLBROWSER_BUTTON_EDIT, OnBnClickedEdit)
538         ON_BN_CLICKED(IDC_DECLBROWSER_BUTTON_NEW, OnBnClickedNew)
539         ON_BN_CLICKED(IDC_DECLBROWSER_BUTTON_RELOAD, OnBnClickedReload)
540         ON_BN_CLICKED(IDOK, OnBnClickedOk)
541         ON_BN_CLICKED(IDCANCEL, OnBnClickedCancel)
542 END_MESSAGE_MAP()
543
544 // DialogDeclBrowser message handlers
545
546 /*
547 ================
548 DialogDeclBrowser::OnActivate
549 ================
550 */
551 void DialogDeclBrowser::OnActivate( UINT nState, CWnd *pWndOther, BOOL bMinimized ) {
552         CDialog::OnActivate( nState, pWndOther, bMinimized );
553 }
554
555 /*
556 ================
557 DialogDeclBrowser::OnToolTipNotify
558 ================
559 */
560 BOOL DialogDeclBrowser::OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ) {
561         // need to handle both ANSI and UNICODE versions of the message
562         TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
563         TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
564
565         if ( pNMHDR->hwndFrom == declTree.GetSafeHwnd() ) {
566                 CString toolTip;
567                 const idDecl *decl = GetDeclFromTreeItem( (HTREEITEM) pNMHDR->idFrom );
568
569                 if ( !decl ) {
570                         return FALSE;
571                 }
572
573                 toolTip = va( "%s, line: %d", decl->GetFileName(), decl->GetLineNum() );
574
575 #ifndef _UNICODE
576                 if( pNMHDR->code == TTN_NEEDTEXTA ) {
577                         delete m_pchTip;
578                         m_pchTip = new TCHAR[toolTip.GetLength() + 2];
579                         lstrcpyn( m_pchTip, toolTip, toolTip.GetLength() + 1 );
580                         pTTTW->lpszText = (WCHAR*)m_pchTip;
581                 } else {
582                         delete m_pwchTip;
583                         m_pwchTip = new WCHAR[toolTip.GetLength() + 2];
584                         _mbstowcsz( m_pwchTip, toolTip, toolTip.GetLength() + 1 );
585                         pTTTW->lpszText = (WCHAR*)m_pwchTip;
586                 }
587 #else
588                 if( pNMHDR->code == TTN_NEEDTEXTA ) {
589                         delete m_pchTip;
590                         m_pchTip = new TCHAR[toolTip.GetLength() + 2];
591                         _wcstombsz( m_pchTip, toolTip, toolTip.GetLength() + 1 );
592                         pTTTA->lpszText = (LPTSTR)m_pchTip;
593                 } else {
594                         delete m_pwchTip;
595                         m_pwchTip = new WCHAR[toolTip.GetLength() + 2];
596                         lstrcpyn( m_pwchTip, toolTip, toolTip.GetLength() + 1 );
597                         pTTTA->lpszText = (LPTSTR) m_pwchTip;
598                 }
599 #endif
600                 return TRUE;
601         }
602
603         return DefaultOnToolTipNotify( toolTips, id, pNMHDR, pResult );
604 }
605
606 /*
607 ================
608 DialogDeclBrowser::OnSetFocus
609 ================
610 */
611 void DialogDeclBrowser::OnSetFocus( CWnd *pOldWnd ) {
612         CDialog::OnSetFocus( pOldWnd );
613 }
614
615 /*
616 ================
617 DialogDeclBrowser::OnDestroy
618 ================
619 */
620 void DialogDeclBrowser::OnDestroy() {
621
622         com_editors &= ~EDITOR_DECL;
623
624         return CDialog::OnDestroy();
625 }
626
627 /*
628 ================
629 DialogDeclBrowser::OnMove
630 ================
631 */
632 void DialogDeclBrowser::OnMove( int x, int y ) {
633         if ( GetSafeHwnd() ) {
634                 CRect rct;
635                 GetWindowRect( rct );
636                 // FIXME: save position
637         }
638         CDialog::OnMove( x, y );
639 }
640
641 /*
642 ================
643 DialogDeclBrowser::OnMove
644 ================
645 */
646 #define BORDER_SIZE                     4
647 #define BUTTON_SPACE            4
648 #define TOOLBAR_HEIGHT          24
649
650 void DialogDeclBrowser::OnSize( UINT nType, int cx, int cy ) {
651         CRect clientRect, rect;
652
653         LockWindowUpdate();
654
655         CDialog::OnSize( nType, cx, cy );
656
657         GetClientRect( clientRect );
658
659         if ( declTree.GetSafeHwnd() ) {
660                 rect.left = BORDER_SIZE;
661                 rect.top = BORDER_SIZE;
662                 rect.right = clientRect.Width() - BORDER_SIZE;
663                 rect.bottom = clientRect.Height() - 100;
664                 declTree.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
665         }
666
667         if ( findNameStatic.GetSafeHwnd() ) {
668                 rect.left = BORDER_SIZE + 2;
669                 rect.top = clientRect.Height() - 100 + BUTTON_SPACE + 2;
670                 rect.right = BORDER_SIZE + 80;
671                 rect.bottom = clientRect.Height() - 76 + 2;
672                 findNameStatic.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
673         }
674
675         if ( findTextStatic.GetSafeHwnd() ) {
676                 rect.left = BORDER_SIZE + 2;
677                 rect.top = clientRect.Height() - 78 + BUTTON_SPACE + 2;
678                 rect.right = BORDER_SIZE + 80;
679                 rect.bottom = clientRect.Height() - 54 + 2;
680                 findTextStatic.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
681         }
682
683         if ( findNameEdit.GetSafeHwnd() ) {
684                 rect.left = BORDER_SIZE + 80;
685                 rect.top = clientRect.Height() - 100 + BUTTON_SPACE;
686                 rect.right = clientRect.Width() - BORDER_SIZE;
687                 rect.bottom = clientRect.Height() - 76;
688                 findNameEdit.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
689         }
690
691         if ( findTextEdit.GetSafeHwnd() ) {
692                 rect.left = BORDER_SIZE + 80;
693                 rect.top = clientRect.Height() - 78 + BUTTON_SPACE;
694                 rect.right = clientRect.Width() - BORDER_SIZE;
695                 rect.bottom = clientRect.Height() - 54;
696                 findTextEdit.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
697         }
698
699         if ( findButton.GetSafeHwnd() ) {
700                 findButton.GetClientRect( rect );
701                 int width = rect.Width();
702                 int height = rect.Height();
703                 rect.left = BORDER_SIZE;
704                 rect.top = clientRect.Height() - TOOLBAR_HEIGHT - height;
705                 rect.right = BORDER_SIZE + width;
706                 rect.bottom = clientRect.Height() - TOOLBAR_HEIGHT;
707                 findButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
708         }
709
710         if ( editButton.GetSafeHwnd() ) {
711                 editButton.GetClientRect( rect );
712                 int width = rect.Width();
713                 int height = rect.Height();
714                 rect.left = BORDER_SIZE + BUTTON_SPACE + width;
715                 rect.top = clientRect.Height() - TOOLBAR_HEIGHT - height;
716                 rect.right = BORDER_SIZE + BUTTON_SPACE + 2 * width;
717                 rect.bottom = clientRect.Height() - TOOLBAR_HEIGHT;
718                 editButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
719         }
720
721         if ( newButton.GetSafeHwnd() ) {
722                 newButton.GetClientRect( rect );
723                 int width = rect.Width();
724                 int height = rect.Height();
725                 rect.left = BORDER_SIZE + 2 * BUTTON_SPACE + 2 * width;
726                 rect.top = clientRect.Height() - TOOLBAR_HEIGHT - height;
727                 rect.right = BORDER_SIZE + 2 * BUTTON_SPACE + 3 * width;
728                 rect.bottom = clientRect.Height() - TOOLBAR_HEIGHT;
729                 newButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
730         }
731
732         if ( reloadButton.GetSafeHwnd() ) {
733                 reloadButton.GetClientRect( rect );
734                 int width = rect.Width();
735                 int height = rect.Height();
736                 rect.left = BORDER_SIZE + 3 * BUTTON_SPACE + 3 * width;
737                 rect.top = clientRect.Height() - TOOLBAR_HEIGHT - height;
738                 rect.right = BORDER_SIZE + 3 * BUTTON_SPACE + 4 * width;
739                 rect.bottom = clientRect.Height() - TOOLBAR_HEIGHT;
740                 reloadButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
741         }
742
743         if ( cancelButton.GetSafeHwnd() ) {
744                 cancelButton.GetClientRect( rect );
745                 int width = rect.Width();
746                 int height = rect.Height();
747                 rect.left = clientRect.Width() - BORDER_SIZE - width;
748                 rect.top = clientRect.Height() - TOOLBAR_HEIGHT - height;
749                 rect.right = clientRect.Width() - BORDER_SIZE;
750                 rect.bottom = clientRect.Height() - TOOLBAR_HEIGHT;
751                 cancelButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
752         }
753
754         if ( statusBar.GetSafeHwnd() ) {
755                 rect.left = clientRect.Width() - 2;
756                 rect.top = clientRect.Height() - 2;
757                 rect.right = clientRect.Width() - 2;
758                 rect.bottom = clientRect.Height() - 2;
759                 statusBar.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
760         }
761
762         UnlockWindowUpdate();
763 }
764
765 /*
766 ================
767 DialogDeclBrowser::OnSizing
768 ================
769 */
770 void DialogDeclBrowser::OnSizing( UINT nSide, LPRECT lpRect ) {
771         /*
772                 1 = left
773                 2 = right
774                 3 = top
775                 4 = left - top
776                 5 = right - top
777                 6 = bottom
778                 7 = left - bottom
779                 8 = right - bottom
780         */
781
782         CDialog::OnSizing( nSide, lpRect );
783
784         if ( ( nSide - 1 ) % 3 == 0 ) {
785                 if ( lpRect->right - lpRect->left < initialRect.Width() ) {
786                         lpRect->left = lpRect->right - initialRect.Width();
787                 }
788         } else if ( ( nSide - 2 ) % 3 == 0 ) {
789                 if ( lpRect->right - lpRect->left < initialRect.Width() ) {
790                         lpRect->right = lpRect->left + initialRect.Width();
791                 }
792         }
793         if ( nSide >= 3 && nSide <= 5 ) {
794                 if ( lpRect->bottom - lpRect->top < initialRect.Height() ) {
795                         lpRect->top = lpRect->bottom - initialRect.Height();
796                 }
797         } else if ( nSide >= 6 && nSide <= 9 ) {
798                 if ( lpRect->bottom - lpRect->top < initialRect.Height() ) {
799                         lpRect->bottom = lpRect->top + initialRect.Height();
800                 }
801         }
802 }
803
804 /*
805 ================
806 DialogDeclBrowser::OnTreeSelChanged
807 ================
808 */
809 void DialogDeclBrowser::OnTreeSelChanged( NMHDR* pNMHDR, LRESULT* pResult ) {
810         LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
811
812         const idDecl *decl = GetSelectedDecl();
813         if ( decl ) {
814                 statusBar.SetWindowText( va( "%d decls listed    -    %s, line: %d", numListedDecls, decl->GetFileName(), decl->GetLineNum() ) );
815                 findNameEdit.SetWindowText( va( "%s/%s", declManager->GetDeclNameFromType( decl->GetType() ), decl->GetName() ) );
816         } else {
817                 HTREEITEM item = declTree.GetSelectedItem();
818                 idStr typeName, declName;
819                 GetDeclName( item, typeName, declName );
820                 findNameEdit.SetWindowText( va( "%s/%s*", typeName.c_str(), declName.c_str() ) );
821                 statusBar.SetWindowText( va( "%d decls listed", numListedDecls ) );
822         }
823
824         *pResult = 0;
825 }
826
827 /*
828 ================
829 DialogDeclBrowser::OnTreeDblclk
830 ================
831 */
832 void DialogDeclBrowser::OnTreeDblclk( NMHDR *pNMHDR, LRESULT *pResult ) {
833         // post a message as if the edit button was clicked to make sure the editor gets focus
834         PostMessage( WM_COMMAND, ( BN_CLICKED << 16 ) | editButton.GetDlgCtrlID(), 0 );
835
836         *pResult = 1;
837 }
838
839 /*
840 ================
841 DialogDeclBrowser::OnBnClickedFind
842 ================
843 */
844 void DialogDeclBrowser::OnBnClickedFind() {
845         CString windowText;
846
847         findNameEdit.GetWindowText( windowText );
848         findNameString = windowText;
849         findNameString.Strip( ' ' );
850
851         findTextEdit.GetWindowText( windowText );
852         findTextString = windowText;
853         findTextString.Strip( ' ' );
854         
855         numListedDecls = baseDeclTree.SearchTree( DeclBrowserCompareDecl, this, declTree );
856
857         statusBar.SetWindowText( va( "%d decls listed", numListedDecls ) );
858 }
859
860 /*
861 ================
862 DialogDeclBrowser::OnBnClickedEdit
863 ================
864 */
865 void DialogDeclBrowser::OnBnClickedEdit() {
866         EditSelected();
867 }
868
869 /*
870 ================
871 DialogDeclBrowser::OnBnClickedNew
872 ================
873 */
874 void DialogDeclBrowser::OnBnClickedNew() {
875         HTREEITEM item;
876         idStr typeName, declName;
877         const idDecl *decl;
878         DialogDeclNew newDeclDlg;
879
880         newDeclDlg.SetDeclTree( &baseDeclTree );
881
882         item = declTree.GetSelectedItem();
883         if ( item ) {
884                 GetDeclName( item, typeName, declName );
885                 newDeclDlg.SetDefaultType( typeName );
886                 newDeclDlg.SetDefaultName( declName );
887         }
888
889         decl = GetSelectedDecl();
890         if ( decl ) {
891                 newDeclDlg.SetDefaultFile( decl->GetFileName() );
892         }
893
894         if ( newDeclDlg.DoModal() != IDOK ) {
895                 return;
896         }
897
898         decl = newDeclDlg.GetNewDecl();
899
900         if ( decl ) {
901                 declName = declManager->GetDeclNameFromType( decl->GetType() );
902                 declName += "/";
903                 declName += decl->GetName();
904
905                 int id = GetIdFromTypeAndIndex( decl->GetType(), decl->Index() );
906
907                 baseDeclTree.InsertPathIntoTree( declName, id );
908                 item = declTree.InsertPathIntoTree( declName, id );
909                 declTree.SelectItem( item );
910
911                 EditSelected();
912         }
913 }
914
915 /*
916 ================
917 DialogDeclBrowser::OnBnClickedReload
918 ================
919 */
920 void DialogDeclBrowser::OnBnClickedReload() {
921
922         declManager->Reload( false );
923
924         ReloadDeclarations();
925 }
926
927 /*
928 ================
929 DialogDeclBrowser::OnBnClickedOk
930 ================
931 */
932 void DialogDeclBrowser::OnBnClickedOk() {
933         // with a modeless dialog once it is closed and re-activated windows seems
934         // to enjoy mapping ENTER back to the default button ( OK ) even if you have
935         // it NOT set as the default.. in this case use cancel button exit and ignore
936         // default IDOK handling.
937         // OnOK();
938 }
939
940 /*
941 ================
942 DialogDeclBrowser::OnBnClickedCancel
943 ================
944 */
945 void DialogDeclBrowser::OnBnClickedCancel() {
946         OnCancel();
947 }