CMD Enhancements:
[reactos.git] / rosapps / devutils / vmingw / main.cpp
1 /********************************************************************
2 * Module: main.cpp. This is part of Visual-MinGW.
3 *
4 * Purpose: Main module.
5 *
6 * Authors: Manu B.
7 *
8 * License: Visual-MinGW is a C/C++ Integrated Development Environment.
9 * Copyright (C) 2001 Manu.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
24 * USA.
25 *
26 * (See license.htm for more details.)
27 *
28 * Revisions:
29 * Manu B. 12/15/01 CFileList created.
30 *
31 ********************************************************************/
32 #include <windows.h>
33 #include <commctrl.h>
34 #include <stdio.h>
35 #include <ctype.h>
36 #include "process.h"
37 #include "project.h"
38 #include "main.h"
39 #include "rsrc.h"
40
41 #define MSG_MODIFIED "Modified"
42
43 CCriticalSection CriticalSection;
44 extern CMessageBox MsgBox;
45 CFindReplaceDlg EditorDlg;
46 void Main_CmdTest(HWND hwnd);
47
48 /* Globals */
49 char * g_env_path = NULL;
50 char * g_vm_path = NULL;
51 CWinApp winApp;
52 CProject Project;
53 CChrono Chrono;
54
55 // File filters & flags.
56 DWORD singleFileOpen = OFN_EXPLORER | OFN_FILEMUSTEXIST;
57 DWORD multipleFileOpen = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;
58 DWORD fileSave = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
59 OFN_OVERWRITEPROMPT;
60
61 char * defFilter = "All Sources\0*.c;*.cpp;*.cxx;*.h;*.hpp;*.hxx;*.rc;*.mingw;*.prj\0"
62 "C Files\0*.c;*.cpp;*.cxx;*.rc\0"
63 "Headers\0*.h;*.hpp;*.hxx\0"
64 "Ini file\0*.ini\0"
65 "All Files (*.*)\0*.*\0\0";
66
67 char * prjFilter = "Project Files (*.prj)\0*.prj\0All Files (*.*)\0*.*\0\0";
68 char * prjDefExt = "prj";
69
70 char * srcFilter = "All Sources\0*.c;*.cpp;*.cxx;*.h;*.hpp;*.hxx;*.rc\0"
71 "C Files\0*.c;*.cpp;*.cxx;*.rc\0"
72 "Headers\0*.h;*.hpp;*.hxx\0"
73 "All Files (*.*)\0*.*\0\0";
74 char * srcDefExt = "cpp";
75
76 /* For tests */
77 CChooseFontDlg CChooseFont;
78 void Main_CmdTest(HWND){
79 winApp.Process.AddTask(
80 "sh.exe",
81 IN_PIPE || OUTERR_PIPE,
82 LVOUT_ERROR);
83 winApp.Process.Run();
84 /* CChooseFont.Create(&winApp);*/
85 return;
86 }
87
88
89 /********************************************************************
90 * Class: CFileDlg.
91 *
92 * Purpose: A CFileDlgBase for Open/Save dlg boxes.
93 *
94 * Revisions:
95 *
96 ********************************************************************/
97 CFileDlg::CFileDlg(){
98 }
99
100 CFileDlg::~CFileDlg(){
101 }
102
103 bool CFileDlg::Open(CWindow * pWindow, char * pszFileName, DWORD nMaxFile, int fileflag){
104
105 switch(fileflag){
106 // Project file.
107 case PRJ_FILE:
108 SetData(prjFilter, prjDefExt, singleFileOpen);
109 break;
110
111 // Add multiple files to project.
112 case ADD_SRC_FILE:
113 Reset();
114 SetTitle("Add files to project");
115 nMaxFile = 2048;
116 SetFilterIndex(1);
117 SetData(srcFilter, srcDefExt, multipleFileOpen);
118 break;
119
120 default: // SRC_FILE
121 SetData(defFilter, srcDefExt, singleFileOpen);
122 SetFilterIndex(1);
123 break;
124 }
125 return OpenFileName(pWindow, pszFileName, nMaxFile);
126 }
127
128 bool CFileDlg::Save(CWindow * pWindow, char * pszFileName, DWORD nMaxFile, int fileflag){
129 Reset();
130
131 switch(fileflag){
132 case SRC_FILE:
133 SetData(defFilter, srcDefExt, fileSave);
134 SetFilterIndex(1);
135 break;
136
137 default: // PRJ_FILE
138 SetData(prjFilter, prjDefExt, fileSave);
139 break;
140 }
141 return SaveFileName(pWindow, pszFileName, nMaxFile);
142 }
143
144
145 /********************************************************************
146 * Class: CPreferencesDlg.
147 *
148 * Purpose:
149 *
150 * Revisions:
151 *
152 ********************************************************************/
153 CPreferencesDlg::CPreferencesDlg(){
154 }
155
156 CPreferencesDlg::~CPreferencesDlg(){
157 }
158
159 int CPreferencesDlg::Create(void){
160 return CreateModal(&winApp, IDD_PREFERENCES, (LPARAM) this);
161 }
162
163 LRESULT CALLBACK CPreferencesDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){
164 switch(Message){
165 case WM_INITDIALOG:
166 return OnInitDialog((HWND) wParam, lParam);
167
168 case WM_NOTIFY:
169 OnNotify((int) wParam, (LPNMHDR) lParam);
170 break;
171
172 case WM_COMMAND:
173 OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam);
174 break;
175
176 case WM_CLOSE:
177 EndDlg(0);
178 break;
179 }
180 return FALSE;
181 }
182
183 BOOL CPreferencesDlg::OnInitDialog(HWND, LPARAM){
184 // Tab control handle and TCITEM.
185 _hWndTab = ::GetDlgItem(_hWnd, IDC_PREF_TABS);
186 tcitem.mask = TCIF_TEXT | TCIF_PARAM;
187
188 // Insert tabs.
189 HWND hwndChild = EnvDlg.Create(this, IDD_ENVIRON, NULL, (long) NULL);
190 tcitem.pszText = "Environment";
191 tcitem.lParam = (long) &EnvDlg;
192 ::SendMessage(_hWndTab, TCM_INSERTITEM, 0, (LPARAM)&tcitem);
193 SetChildPosition(hwndChild);
194
195 /* tcitem.pszText = "General";
196 tcitem.lParam = (long) NULL;
197 ::SendMessage(_hWndTab, TCM_INSERTITEM, 1, (LPARAM)&tcitem);
198
199 tcitem.pszText = "Find in files";
200 tcitem.lParam = (long) NULL;
201 ::SendMessage(_hWndTab, TCM_INSERTITEM, 2, (LPARAM)&tcitem);*/
202
203 // Show the dialog and default pane.
204 Show();
205 EnvDlg.Show();
206 EnvDlg.SetFocus();
207 return TRUE;
208 }
209
210 BOOL CPreferencesDlg::OnCommand(WORD, WORD wID, HWND){
211 switch (wID){
212 case IDOK:
213 EnvDlg.OnCommand(0, wID, 0);
214 EndDlg(IDOK);
215 return TRUE;
216
217 case IDCANCEL:
218 EndDlg(IDCANCEL);
219 return FALSE;
220
221 case IDAPPLY:
222 EnvDlg.OnCommand(0, wID, 0);
223 return TRUE;
224 }
225 return FALSE;
226 }
227
228 BOOL CPreferencesDlg::EndDlg(int nResult){
229 EnvDlg.EndDlg(0);
230 EnvDlg.bIsVisible = false;
231 if (_hWnd){
232 BOOL result = ::EndDialog(_hWnd, nResult);
233 _hWnd = 0;
234 return result;
235 }
236 return false;
237 }
238
239
240 /********************************************************************
241 * Class: CEnvDlg.
242 *
243 * Purpose:
244 *
245 * Revisions:
246 *
247 ********************************************************************/
248 CEnvDlg::CEnvDlg(){
249 }
250
251 CEnvDlg::~CEnvDlg(){
252 }
253
254 LRESULT CALLBACK CEnvDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){
255 switch(Message){
256 case WM_INITDIALOG:
257 return OnInitDialog((HWND) wParam, lParam);
258
259 case WM_COMMAND:
260 OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam);
261 break;
262 }
263 return FALSE;
264 }
265
266 BOOL CEnvDlg::OnInitDialog(HWND, LPARAM){
267 bIsVisible = false;
268 bModified = false;
269 /* Get control handles */
270 hApply = ::GetDlgItem(_pParent->_hWnd, IDAPPLY);
271 hSetCcBin = GetItem(IDC_SET_CCBIN);
272 hCcBinDir = GetItem(IDC_CCBIN);
273 hBrowseCc = GetItem(IDC_BROWSE_CC);
274 hSetCmdBin = GetItem(IDC_SET_CMDBIN);
275 hCmdBinDir = GetItem(IDC_CMDBIN);
276 hBrowseCmd = GetItem(IDC_BROWSE_CMD);
277 hAutoexec = GetItem(IDC_AUTOEXEC);
278 hEnvView = GetItem(IDC_ENV_VIEW);
279
280 if (winApp.bSetCcEnv)
281 ::SendMessage(hSetCcBin, BM_SETCHECK, BST_CHECKED, 0);
282 if (winApp.bSetCmdEnv)
283 ::SendMessage(hSetCmdBin, BM_SETCHECK, BST_CHECKED, 0);
284 if (winApp.bSetDefEnv)
285 ::SendMessage(hAutoexec, BM_SETCHECK, BST_CHECKED, 0);
286
287 SetItemText(hCcBinDir, winApp.szCcBinDir);
288 SetItemText(hCmdBinDir, winApp.szCmdBinDir);
289 SetEnvText();
290 /* hCcIncDir = GetItem(IDC_CC_INCDIR);
291
292 SetItemText(hCcIncDir, winApp.includeDir);*/
293 bIsVisible = true;
294 return TRUE;
295 }
296
297 BOOL CEnvDlg::OnCommand(WORD wNotifyCode, WORD wID, HWND){
298 char directory[MAX_PATH];
299
300 switch (wID){
301 case IDC_BROWSE_CC:
302 if (winApp.ShellDlg.BrowseForFolder(&winApp, directory, "Browse",
303 BIF_RETURNONLYFSDIRS)){
304 SetItemText(hCcBinDir, directory);
305 }
306 return TRUE;
307
308 case IDC_BROWSE_CMD:
309 if (winApp.ShellDlg.BrowseForFolder(&winApp, directory, "Browse",
310 BIF_RETURNONLYFSDIRS)){
311 SetItemText(hCmdBinDir, directory);
312 }
313 return TRUE;
314
315 case IDOK:
316 winApp.bSetCcEnv =
317 (BST_CHECKED==::SendMessage(hSetCcBin, BM_GETCHECK, 0, 0));
318 winApp.bSetCmdEnv =
319 (BST_CHECKED==::SendMessage(hSetCmdBin, BM_GETCHECK, 0, 0));
320 winApp.bSetDefEnv =
321 (BST_CHECKED==::SendMessage(hAutoexec, BM_GETCHECK, 0, 0));
322
323 GetItemText(hCcBinDir, winApp.szCcBinDir, MAX_PATH);
324 GetItemText(hCmdBinDir, winApp.szCmdBinDir, MAX_PATH);
325 // GetItemText(hCcIncDir, winApp.includeDir, MAX_PATH);
326 if (bModified)
327 winApp.SetEnv();
328 return TRUE;
329
330 case IDCANCEL:
331 return FALSE;
332
333 case IDAPPLY:
334 if (bModified){
335 winApp.bSetCcEnv =
336 (BST_CHECKED==::SendMessage(hSetCcBin, BM_GETCHECK, 0, 0));
337 winApp.bSetCmdEnv =
338 (BST_CHECKED==::SendMessage(hSetCmdBin, BM_GETCHECK, 0, 0));
339 winApp.bSetDefEnv =
340 (BST_CHECKED==::SendMessage(hAutoexec, BM_GETCHECK, 0, 0));
341
342 GetItemText(hCcBinDir, winApp.szCcBinDir, MAX_PATH);
343 GetItemText(hCmdBinDir, winApp.szCmdBinDir, MAX_PATH);
344 winApp.SetEnv();
345 SetEnvText();
346 bModified = false;
347 ::EnableWindow(hApply, false);
348 }
349 return TRUE;
350
351 default:
352 if (bIsVisible && !bModified){
353 switch(wNotifyCode){
354 case EN_CHANGE:
355 case BN_CLICKED:
356 bModified = true;
357 ::EnableWindow(hApply, true);
358 return TRUE;
359 }
360 }
361 break;
362 }
363 return FALSE;
364 }
365
366 void CEnvDlg::SetEnvText(void){
367 if (g_vm_path){
368 char * text = (char *) malloc(strlen(g_vm_path)+20); // 10 lines max.
369 char * start = text;
370 char * parse = g_vm_path;
371 while (*parse){
372 if (*parse == ';'){
373 // Change ';' into CR/LF.
374 *text = '\r';
375 text++;
376 *text = '\n';
377 text++;
378 parse++;
379 }else if (*parse == '='){
380 // Rewind buffer.
381 text = start;
382 parse++;
383 }else{
384 // Copy one char.
385 *text = *parse;
386 text++;
387 parse++;
388 }
389 }
390 *text = '\0';
391 SetItemText(hEnvView, start);
392 free(start);
393 }
394 }
395
396
397 /********************************************************************
398 * Class: CGrepDlg.
399 *
400 * Purpose:
401 *
402 * Revisions:
403 *
404 ********************************************************************/
405 CGrepDlg::CGrepDlg(){
406 *findWhat = '\0';
407 *gDir = '\0';
408 }
409
410 CGrepDlg::~CGrepDlg(){
411 }
412
413 int CGrepDlg::Create(void){
414 return CreateModal(&winApp, IDD_GREP, (LPARAM) this);
415 }
416
417 LRESULT CALLBACK CGrepDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){
418 switch(Message){
419 case WM_INITDIALOG:
420 return OnInitDialog((HWND) wParam, lParam);
421
422 case WM_COMMAND:
423 OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam);
424 break;
425
426 case WM_CLOSE:
427 EndDlg(0);
428 break;
429 }
430 return FALSE;
431 }
432
433 BOOL CGrepDlg::OnInitDialog(HWND, LPARAM){
434 hFindWhat = GetItem(IDC_FINDWHAT);
435 hgDir = GetItem(IDC_GFILTER);
436
437 SetItemText(hFindWhat, findWhat);
438 SetItemText(hgDir, gDir);
439 // Show the dialog and default pane.
440 Show();
441 return TRUE;
442 }
443
444 BOOL CGrepDlg::OnCommand(WORD, WORD wID, HWND){
445 switch (wID){
446 case IDOK:
447 GetItemText(hFindWhat, findWhat, sizeof(findWhat));
448 GetItemText(hgDir, gDir, sizeof(gDir));
449 FindInFiles(findWhat, gDir);
450 return TRUE;
451
452 case IDCANCEL:
453 EndDlg(IDCANCEL);
454 return FALSE;
455 }
456 return FALSE;
457 }
458
459 void CGrepDlg::FindInFiles(char * findWhat, char * fileFilter){
460 if (!findWhat || !fileFilter || winApp.Process.isRunning())
461 return;
462
463 winApp.Report.Clear();
464 winApp.Report.Append("Grep search...", LVOUT_NORMAL);
465
466 winApp.Process.AddTask("grep -G -n -H ", OUTERR_PIPE, LVOUT_ERROR);
467 winApp.Process.CmdCat(findWhat);
468 winApp.Process.CmdCat(" ");
469 winApp.Process.CmdCat(fileFilter);
470
471 winApp.Process.Run();
472 }
473
474
475 /********************************************************************
476 * Functions: WinMain procedure.
477 *
478 * Purpose: Runs the application.
479 *
480 * Revisions:
481 *
482 ********************************************************************/
483 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
484 return winApp.Run(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
485 }
486
487
488 /********************************************************************
489 * Class: CWinApp.
490 *
491 * Purpose: Manages the all application.
492 *
493 * Revisions:
494 *
495 ********************************************************************/
496 CWinApp::CWinApp(){
497 *iniFileName = '\0';
498 hmod = NULL;
499 *openFilesDir ='\0';
500 *projectDir = '\0';
501 *includeDir = '\0';
502 bSetCcEnv = false;
503 bSetCmdEnv = false;
504 bSetDefEnv = false;
505 *szCcBinDir = '\0';
506 *szCmdBinDir = '\0';
507
508 firstRun = false;
509 // Child windows dimensions.
510 deltaY = 0;
511 tbarHeight = 26;
512 sbarHeight = 20;
513 tvWidth = 140;
514 lvHeight = 120;
515
516 hSplitter = 4;
517 vSplitter = 4;
518 }
519
520 CWinApp::~CWinApp(){
521 }
522
523 bool CWinApp::CustomInit(void){
524 /* Get PATH environment variable */
525 char * env_path = getenv("PATH");
526 if (env_path)
527 g_env_path = strdup(env_path);
528
529 SetName("Visual MinGW", APP_VERSION);
530 MsgBox.SetCaption("Visual MinGW");
531 IsWinNT();
532 ReadIniFile("visual-mingw.ini");
533
534 hAccel = LoadAccelerators(_hInst, "ACCELS");
535 hmod = LoadLibrary("SciLexer.DLL");
536 if (!hmod){
537 MsgBox.DisplayFatal("Unable to load SciLexer.DLL");
538 return false;
539 }
540 return true;
541 }
542
543 bool CWinApp::Release(void){
544 WriteIniFile();
545 if (hmod)
546 FreeLibrary(hmod);
547 if (g_env_path)
548 free(g_env_path);
549 return true;
550 }
551
552 bool CWinApp::ReadIniFile(char * fileName){
553 ParseCmdLine(iniFileName);
554 strcat(iniFileName, fileName);
555
556 if (!IniFile.Load(iniFileName)){
557 /* Create an empty file and fill it */
558 firstRun = true;
559 MsgBox.DisplayWarning("Visual-MinGW first run !\n"
560 "Step 1: User interface initialization.\n"
561 "Please report bugs to Visual-MinGW home page.\n"
562 "See the Readme text for more information.");
563 FILE * file = fopen(iniFileName, "wb");
564 if (!file)
565 return false;
566 SaveIniFile(file);
567 fclose(file);
568 return false;
569 }
570 // [General] section
571 IniFile.GetString(openFilesDir, "FilesDirectory", "General" );
572 IniFile.GetString(projectDir, "ProjectDirectory" );
573 bSetDefEnv = IniFile.GetInt( "SetDefEnv" );
574 bSetCmdEnv = IniFile.GetInt( "SetBinDir" );
575 IniFile.GetString(szCmdBinDir, "BinDir" );
576 // [Compiler] section
577 IniFile.GetString(includeDir, "IncludeDir", "Compiler" );
578 bSetCcEnv = IniFile.GetInt( "SetBinDir" );
579 IniFile.GetString(szCcBinDir, "BinDir" );
580
581 SetEnv();
582 return true;
583 }
584
585 void CWinApp::SaveIniFile(FILE * file){
586 // [General]
587 fprintf (file, "\t; Generated automatically by Visual-MinGW.\n");
588 fprintf (file, "\t ; http://visual-mingw.sourceforge.net/\n");
589 fprintf (file, "[General]\nSignature = 40");
590 fprintf (file, "\nFilesDirectory = %s", openFilesDir);
591 fprintf (file, "\nProjectDirectory = %s", projectDir);
592 fprintf (file, "\nTvWidth = %d", tvWidth);
593 fprintf (file, "\nLvHeight = %d", lvHeight);
594 fprintf (file, "\nSetDefEnv = %d", bSetDefEnv);
595 fprintf (file, "\nSetBinDir = %d", bSetCmdEnv);
596 fprintf (file, "\nBinDir = %s", szCmdBinDir);
597 // [Compiler]
598 fprintf (file, "\n\n[Compiler]\nIncludeDir = %s", includeDir);
599 fprintf (file, "\nSetBinDir = %d", bSetCcEnv);
600 fprintf (file, "\nBinDir = %s", szCcBinDir);
601 }
602
603 bool CWinApp::WriteIniFile(void){
604 if (*iniFileName == '\0')
605 return false;
606 FILE * file = fopen(iniFileName, "wb");
607 if (!file)
608 return false;
609 SaveIniFile(file);
610 fclose(file);
611 IniFile.Close();
612 return true;
613 }
614
615 bool CWinApp::SetEnv(void){
616 // Free previous variable.
617 //getenv("PATH=");
618 // Malloc a buffer.
619 int len = 0;
620 if (bSetCcEnv)
621 len += strlen(winApp.szCcBinDir);
622 if (bSetCmdEnv)
623 len += strlen(winApp.szCmdBinDir);
624 if (bSetDefEnv && g_env_path)
625 len += strlen(g_env_path);
626 g_vm_path = (char *) malloc(len+8);
627
628 // Copy the environment variable.
629 strcpy(g_vm_path, "PATH=");
630 if (bSetCcEnv && *winApp.szCcBinDir){
631 strcat(g_vm_path, winApp.szCcBinDir);
632 strcat(g_vm_path, ";");
633 }
634 if (bSetCmdEnv && *winApp.szCmdBinDir){
635 strcat(g_vm_path, winApp.szCmdBinDir);
636 strcat(g_vm_path, ";");
637 }
638 if (bSetDefEnv && g_env_path)
639 strcat(g_vm_path, g_env_path);
640
641 len = strlen(g_vm_path) - 1;
642 if (g_vm_path[len] == ';')
643 g_vm_path[len] = '\0';
644 if (putenv(g_vm_path) == -1){
645 free(g_vm_path);
646 g_vm_path = NULL;
647 return false;
648 }
649 return true;
650 }
651
652
653 /********************************************************************
654 * CWinApp: Create each application's window.
655 ********************************************************************/
656 bool CWinApp::CreateUI(void){
657
658 InitCommonControls();
659
660 // Custom values.
661 wc.style = 0;
662 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
663 wc.hCursor = NULL;
664 wc.hbrBackground = //NULL;
665 (HBRUSH)(COLOR_INACTIVEBORDER + 1);
666 wc.lpszMenuName = MAKEINTRESOURCE(ID_MENU);
667 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
668
669 if(!MainRegisterEx("main_class")) {
670 MsgBox.DisplayFatal("Can't Register Main Window");
671 return false;
672 }
673
674 // Custom values.
675 wc.hbrBackground = NULL;
676 wc.lpszMenuName = 0;
677
678 if(!ChildRegisterEx("child_class")) {
679 MsgBox.DisplayFatal("Can't Register MDI Class");
680 return false;
681 }
682
683 // Use a CreateWindowEx like procedure.
684 HWND hwnd = CreateEx(
685 this, // Owner class.
686 0,
687 mainClass,
688 appName,
689 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
690 CW_USEDEFAULT,
691 CW_USEDEFAULT,
692 CW_USEDEFAULT,
693 CW_USEDEFAULT,
694 0,
695 NULL);
696
697 if(!hwnd) {
698 MsgBox.DisplayFatal("Can't create Main window");
699 return false;
700 }
701 MsgBox.SetParent(hwnd);
702
703 // SW_SHOWMAXIMIZED.
704 ::ShowWindow(hwnd, SW_SHOWMAXIMIZED);
705 ::UpdateWindow(hwnd);
706 if (firstRun)
707 FirstRunTest();
708 firstRun = false;
709 return true;
710 }
711
712 void CWinApp::FirstRunTest(void){
713 MsgBox.DisplayWarning("Visual-MinGW first run !\n"
714 "Step 2: You will now set your environment variables.\n"
715 "\"Use default environment variables\" should be checked.\n"
716 "Then Visual-MinGW will try to launch the compiler.");
717 PreferencesDlg.Create();
718 MsgBox.DisplayWarning("Visual-MinGW first run !\n"
719 "Step 3: Installation checking.\n"
720 "Try to launch rm and gcc.\n"
721 "See \"Main\" or \"Log\" report views for results.\n");
722 winApp.Report.Clear();
723 winApp.Report.Append("Testing for first run...", LVOUT_NORMAL);
724
725 // Put the command line and the run flag in the command stack.
726 winApp.Process.AddTask("gcc -v", OUTERR_PIPE, LVOUT_NORMAL);
727 winApp.Process.AddTask("rm --version", OUTERR_PIPE, LVOUT_NORMAL);
728 winApp.Process.Run();
729 return;
730 }
731
732 void CWinApp::CreateToolbar(void){
733 Toolbar.CreateEx(
734 this,
735 0,
736 WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
737 |TBSTYLE_FLAT | TBSTYLE_TOOLTIPS
738 | CCS_NORESIZE);
739
740 Toolbar.AddBitmap(IDB_TOOLBAR, 15);
741
742 TBBUTTON tbButtons [] =
743 { { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0},
744 { 0, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0},
745 { 1, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0},
746 { 2, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0},
747 { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0},
748 { 3, IDM_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0},
749 { 4, IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0},
750 { 5, IDM_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0},
751 { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0},
752 { 6, IDM_UNDO, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0},
753 { 7, IDM_REDO, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0} };
754
755 int numbutton = sizeof tbButtons/sizeof tbButtons[0];
756
757 Toolbar.AddButtons(&tbButtons[0], numbutton);
758 }
759
760 void CWinApp::CreateSplitter(void){
761 MainSplitter.Init(&ChildSplitter, &Report, SPLSTYLE_HORZ, lvHeight, SPLMODE_2);
762 ChildSplitter.Init(&Manager, &MdiClient, SPLSTYLE_VERT, tvWidth, SPLMODE_1);
763
764 // File Manager.
765 Manager.Create(this);
766 // MDI client.
767 CreateMDI();
768 // ListView.
769 Report.Create(this);
770 }
771
772 void CWinApp::CreateMDI(void){
773 MdiClient.Init(3, ID_FIRSTCHILD);
774 MdiClient.CreateEx(
775 this,
776 WS_EX_CLIENTEDGE,
777 WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
778 | WS_VSCROLL | WS_HSCROLL
779 );
780 }
781
782 HWND CWinApp::CreateChild(char * caption, LPVOID lParam){
783
784 CChildView * mdiChild = new CChildView;
785
786 HWND hwnd = mdiChild->CreateEx(
787 &MdiClient, // MUST be an MdiClient *.
788 WS_EX_MDICHILD,
789 MDIS_ALLCHILDSTYLES | WS_CHILD | WS_SYSMENU | WS_CAPTION
790 | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
791 | WS_MAXIMIZE,
792 caption,
793 0,
794 lParam);
795
796 if (!hwnd)
797 delete mdiChild;
798 return hwnd;
799 }
800
801 void CWinApp::CreateStatusBar(void){
802 Sbar.CreateEx(
803 this,
804 0,
805 WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBARS_SIZEGRIP);
806
807 int sbWidths[] = {60, 120, -1};
808
809 int numparts = sizeof sbWidths/sizeof sbWidths[0];
810
811 Sbar.SetParts(numparts, &sbWidths[0]);
812 }
813
814 void CWinApp::SendCaretPos(int caretPos) {
815 // To display the "Line : xxxx" message, we use our standard msgBuf[256].
816 sprintf(msgBuf, "Line : %d", caretPos);
817 Sbar.SendMessage(SB_SETTEXT, 0, (LPARAM) msgBuf);
818 return;
819 }
820
821
822 /********************************************************************
823 * CWinApp: Message handling procedures.
824 ********************************************************************/
825 LRESULT CALLBACK CWinApp::CMainWndProc(UINT Message, WPARAM wParam, LPARAM lParam){
826 switch(Message){
827 case WM_CREATE:
828 return OnCreate((LPCREATESTRUCT) lParam);
829
830 case WM_PAINT:
831 return OnPaint((HDC) wParam);
832
833 case WM_SIZE:
834 return OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
835
836 case WM_DESTROY:
837 return OnDestroy();
838
839 case WM_COMMAND:
840 return OnCommand(wParam, lParam);
841
842 case WM_CLOSE:
843 return OnClose();
844
845 case WM_NOTIFY:
846 return OnNotify((int) wParam, (LPNMHDR) lParam);
847
848 case WM_LBUTTONDOWN:
849 return OnLButtonDown((short) LOWORD(lParam), (short) HIWORD(lParam), wParam);
850
851 case WM_MOUSEMOVE:
852 return OnMouseMove((short) LOWORD(lParam), (short) HIWORD(lParam), wParam);
853
854 case WM_LBUTTONUP:
855 return OnLButtonUp((short) LOWORD(lParam), (short) HIWORD(lParam), wParam);
856
857 case WM_SETCURSOR:
858 OnSetCursor((HWND) wParam, (UINT) LOWORD(lParam), (UINT) HIWORD(lParam));
859 return DefWindowProc(_hWnd, Message, wParam, lParam);
860
861 default:
862 return DefFrameProc(_hWnd, MdiClient.GetId(), Message, wParam, lParam);
863 }
864 return 0;
865 }
866
867 BOOL CWinApp::OnCreate(LPCREATESTRUCT){
868 // Toolbar.
869 CreateToolbar();
870 // Splitter.
871 CreateSplitter();
872 // Statusbar.
873 CreateStatusBar();
874 return TRUE;
875 }
876
877 BOOL CWinApp::OnPaint(HDC){
878 PAINTSTRUCT ps;
879 BeginPaint(_hWnd, &ps);
880 EndPaint(_hWnd, &ps);
881 return 0;
882 }
883
884 BOOL CWinApp::OnSize(UINT, int width, int height){
885 // TreeView and MDI Client delta-height.
886 deltaY = height-sbarHeight-lvHeight-vSplitter-tbarHeight;
887
888 if (deltaY>3){
889 Toolbar.SetPosition(0,
890 0, 0,
891 width, tbarHeight,
892 0);
893
894 MainSplitter.SetPosition(0,
895 0, tbarHeight,
896 width, height-tbarHeight-sbarHeight,
897 0);
898
899 Sbar.SetPosition(0,
900 0, height-sbarHeight,
901 width, sbarHeight,
902 0);
903 }
904 InvalidateRect(_hWnd, NULL, false);
905 return 0;
906 }
907
908 BOOL CWinApp::OnDestroy(void){
909 PostQuitMessage(0);
910 return 0;
911 }
912
913 BOOL CWinApp::OnClose(void){
914 if (IDCANCEL == Manager.SaveAll(IDASK)) // Ask to save.
915 return TRUE; // Cancelled by user.
916 ::DestroyWindow(_hWnd);
917 return 0;
918 }
919
920 BOOL CWinApp::OnNotify(int idCtrl, LPNMHDR notify){
921 Manager.OnNotify(idCtrl, notify);
922 Report.OnNotify(idCtrl, notify);
923 return 0;
924 }
925
926 BOOL CWinApp::OnLButtonDown(short xPos, short yPos, UINT){
927 MainSplitter.OnLButtonDown(_hWnd, xPos, yPos);
928 ChildSplitter.OnLButtonDown(_hWnd, xPos, yPos);
929 return 0;
930 }
931
932 BOOL CWinApp::OnMouseMove(short xPos, short yPos, UINT){
933 MainSplitter.OnMouseMove(_hWnd, xPos, yPos);
934 ChildSplitter.OnMouseMove(_hWnd, xPos, yPos);
935 return 0;
936 }
937
938 BOOL CWinApp::OnLButtonUp(short xPos, short yPos, UINT){
939 MainSplitter.OnLButtonUp(_hWnd, xPos, yPos);
940 ChildSplitter.OnLButtonUp(_hWnd, xPos, yPos);
941 return 0;
942 }
943
944 BOOL CWinApp::OnSetCursor(HWND, UINT nHittest, UINT){
945 if (nHittest == HTCLIENT) {
946 if (MainSplitter.OnSetCursor(_hWnd, 0)){
947 return 0;
948 }else if (ChildSplitter.OnSetCursor(_hWnd, 0)){
949 return 0;
950 }else{
951 ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
952 }
953 }
954 return 0;
955 }
956
957
958 /********************************************************************
959 * CWinApp: Dispatch command messages.
960 ********************************************************************/
961 BOOL CWinApp::OnCommand(WPARAM wParam, LPARAM lParam){
962 int wID = LOWORD(wParam);
963
964 switch (wID){
965 /* File Menu */
966 case IDM_NEW:
967 Manager.FilesView.New();
968 break;
969
970 case IDM_OPEN:
971 Manager.OpenFileDialog();
972 break;
973
974 case IDM_NEW_PROJECT:
975 Manager.NewProjectDialog();
976 break;
977
978 case IDM_OPEN_PROJECT:
979 Manager.OpenProjectDialog();
980 break;
981
982 case IDM_SAVE_PROJECT:
983 Manager.SaveProjectFiles(IDYES);
984 break;
985
986 case IDM_CLOSE_PROJECT:
987 Manager.CloseProject();
988 break;
989
990 case IDM_PREFERENCES:
991 PreferencesDlg.Create();
992 break;
993
994 case IDM_QUIT:
995 PostMessage(_hWnd, WM_CLOSE, 0, 0);
996 break;
997
998 /* Find Menu */
999 case IDM_GREP:
1000 GrepDlg.Create();
1001 break;
1002
1003 /* Window Menu */
1004 case IDM_CASCADE:
1005 PostMessage(MdiClient.GetId(), WM_MDICASCADE, 0, 0);
1006 break;
1007 case IDM_TILEHORZ:
1008 PostMessage(MdiClient.GetId(), WM_MDITILE, MDITILE_HORIZONTAL, 0);
1009 break;
1010 case IDM_TILEVERT:
1011 PostMessage(MdiClient.GetId(), WM_MDITILE, MDITILE_VERTICAL, 0);
1012 break;
1013 case IDM_ARRANGE:
1014 PostMessage(MdiClient.GetId(), WM_MDIICONARRANGE, 0, 0);
1015 break;
1016
1017 /* Project Menu */
1018 case IDM_NEW_MODULE:
1019 Project.NewModuleDlg();
1020 break;
1021
1022 case IDM_ADD:
1023 Project.AddFiles();
1024 break;
1025
1026 case IDM_REMOVE_FILE:
1027 Manager.RemoveProjectFile();
1028 break;
1029
1030 case IDM_REMOVE_MODULE:
1031 Manager.RemoveProjectModule();
1032 break;
1033
1034 case IDM_OPTION:
1035 Project.OptionsDlg();
1036 break;
1037
1038 case IDM_ZIP_SRCS:
1039 Project.ZipSrcs();
1040 break;
1041
1042 case IDM_EXPLORE:
1043 Project.Explore(_hWnd);
1044 break;
1045
1046 /* Build Menu */
1047 case IDM_BUILD:
1048 Project.Build();
1049 break;
1050
1051 case IDM_REBUILDALL:
1052 Project.RebuildAll();
1053 break;
1054
1055 case IDM_RUN_TARGET:
1056 Project.RunTarget();
1057 break;
1058
1059 case IDM_MKCLEAN:
1060 Project.MakeClean();
1061 break;
1062
1063 case IDM_MKF_BUILD:
1064 Project.BuildMakefile();
1065 break;
1066
1067 case IDM_RUN_CMD:
1068 winApp.Process.CommandDlg.Create();
1069 break;
1070
1071 case IDM_TEST:
1072 Main_CmdTest(_hWnd);
1073 break;
1074
1075 default:{
1076 if (wID >= ID_FIRSTCHILD){
1077 DefFrameProc(_hWnd, MdiClient.GetId(), WM_COMMAND, wParam, lParam);
1078 }else{
1079 HWND hChildWindow = (HWND) MdiClient.SendMessage(WM_MDIGETACTIVE);
1080
1081 if (hChildWindow)
1082 ::SendMessage(hChildWindow, WM_COMMAND, wParam, lParam);
1083 }
1084 }
1085 }
1086 return TRUE;
1087 }
1088
1089
1090 /********************************************************************
1091 * CWinApp: Handles child messages.
1092 ********************************************************************/
1093 LRESULT CALLBACK CWinApp::CChildWndProc(CWindow * pWnd, UINT Message, WPARAM wParam, LPARAM lParam){
1094
1095 CChildView * childView = (CChildView *) pWnd;
1096 HWND hwndChild = childView->_hWnd;
1097
1098 switch(Message){
1099 case WM_CREATE:
1100 childView->OnCreate((LPCREATESTRUCT) lParam);
1101 break;
1102
1103 case WM_SIZE:
1104 childView->OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
1105 break;
1106
1107 case WM_COMMAND:
1108 childView->OnCommand(wParam, lParam);
1109 break;
1110
1111 case WM_DESTROY:
1112 childView->OnDestroy();
1113 break;
1114
1115 case WM_CLOSE:
1116 if (childView->OnClose()){
1117 MdiClient.SendMessage(WM_MDIDESTROY,(WPARAM) hwndChild, 0);
1118 }
1119 return true;
1120
1121 case WM_NOTIFY:
1122 childView->OnNotify((int) wParam, (LPNMHDR) lParam);
1123 break;
1124
1125 case WM_SETFOCUS:
1126 childView->OnSetFocus((HWND) wParam);
1127 break;
1128
1129 case WM_MDIACTIVATE:
1130 childView->OnActivate((HWND) wParam, (HWND) lParam);
1131 break;
1132 }
1133 return DefMDIChildProc(hwndChild, Message, wParam, lParam);
1134 }
1135
1136
1137 /********************************************************************
1138 * Class: CChildView.
1139 *
1140 * Purpose: MDI child window class.
1141 *
1142 * Revisions:
1143 *
1144 ********************************************************************/
1145 CChildView::CChildView(){
1146 modified = false;
1147 }
1148
1149 CChildView::~CChildView(){
1150 }
1151
1152 bool CChildView::OnCreate(LPCREATESTRUCT){
1153 CFileItem * file = (CFileItem *) GetLong(GWL_USERDATA);
1154
1155 // Create Scintilla Editor Control.
1156 HWND hwnd = Editor.CreateEx(
1157 this,
1158 0,
1159 WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
1160 | WS_VSCROLL | WS_HSCROLL);
1161
1162 if (!hwnd)
1163 return false; // @@TODO need to manage creation failure.
1164
1165 // Set window handles
1166 file->pMdiChild = this;
1167
1168 // Load a file if there is one to load.
1169 Editor.LoadFile(file);
1170 return true;
1171 }
1172
1173 bool CChildView::OnSize(UINT wParam, int width, int height){
1174 if(wParam != SIZE_MINIMIZED){
1175 Editor.SetPosition(0,
1176 0,
1177 0,
1178 width,
1179 height,
1180 0);
1181 }
1182 return true;
1183 }
1184
1185 BOOL CChildView::OnClose(void){
1186 if (modified){
1187 int decision = MsgBox.AskToSave(true);
1188 switch (decision){
1189 case IDCANCEL:
1190 return FALSE;
1191
1192 case IDYES:
1193 CmdSave();
1194 break;
1195 }
1196 }
1197 return TRUE;
1198 }
1199
1200 BOOL CChildView::OnDestroy(void){
1201 CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA);
1202
1203 if (file){
1204 if (!file->isInProject){
1205 // A simple file.
1206 winApp.Manager.FilesView.CloseFile(file);
1207 }else{
1208 // A project one.
1209 file->pMdiChild = NULL;
1210 //modified = false;
1211 }
1212 }
1213 return 0;
1214 }
1215
1216 BOOL CChildView::OnNotify(int, LPNMHDR notify){
1217 SCNotification * notification = (SCNotification *) notify;
1218
1219 // Notify Message from Current Editor Control.
1220 if (notify->hwndFrom == Editor._hWnd){
1221 switch (notify->code){
1222 case SCN_UPDATEUI:
1223 Editor.GetCurrentPos();
1224 winApp.SendCaretPos(Editor.caretPos);
1225 break;
1226
1227 case SCN_SAVEPOINTREACHED:
1228 modified = false;
1229 winApp.Sbar.WriteString("", 1);
1230 break;
1231
1232 case SCN_SAVEPOINTLEFT:
1233 modified = true;
1234 winApp.Sbar.WriteString(MSG_MODIFIED, 1);
1235 break;
1236
1237 case SCN_MARGINCLICK:
1238 if (notification->margin == 2)
1239 Editor.MarginClick(notification->position, notification->modifiers);
1240 break;
1241 }
1242 }
1243 return 0;
1244 }
1245
1246 BOOL CChildView::OnSetFocus(HWND){
1247 CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA);
1248 if (!file)
1249 return false;
1250 // Select corresponding TreeView item.
1251 CTreeView * pTreeView = file->pTreeView;
1252
1253 if(!pTreeView)
1254 return false;
1255
1256 pTreeView->SendMessage(TVM_SELECTITEM, (WPARAM)TVGN_CARET, (LPARAM)file->_hItem);
1257
1258 // Set Focus on Editor Control.
1259 Editor.SetFocus();
1260
1261 // Display "Modified" message or nothing in the Status Bar.
1262 winApp.SendCaretPos(Editor.caretPos);
1263
1264 if(modified)
1265 winApp.Sbar.SendMessage(SB_SETTEXT, 1, (LPARAM) MSG_MODIFIED);
1266 else
1267 winApp.Sbar.SendMessage(SB_SETTEXT, 1, (LPARAM) "");
1268
1269 int selectedTab = winApp.Manager.SendMessage(TCM_GETCURSEL);
1270
1271 if (file->isInProject == true && selectedTab != PROJECT_TAB){
1272 winApp.Manager.SendMessage(TCM_SETCURFOCUS, PROJECT_TAB);
1273 }else if (file->isInProject == false && selectedTab != FILES_TAB){
1274 winApp.Manager.SendMessage(TCM_SETCURFOCUS, FILES_TAB);
1275 }
1276 return 0;
1277 }
1278
1279 BOOL CChildView::OnActivate(HWND, HWND hwndChildAct){
1280 HMENU hMenu;
1281 HMENU hFileMenu;
1282 BOOL EnableFlag;
1283 HWND hwndMain = winApp._hWnd;
1284
1285 hMenu = GetMenu(hwndMain);
1286
1287 if(_hWnd == hwndChildAct){
1288 EnableFlag = TRUE; //being activated
1289 }else{
1290 EnableFlag = FALSE; //being de-activated
1291 }
1292 // Menu items.
1293 EnableMenuItem(hMenu, 1, MF_BYPOSITION | (EnableFlag ? MF_ENABLED : MF_GRAYED));
1294 EnableMenuItem(hMenu, 3, MF_BYPOSITION | (EnableFlag ? MF_ENABLED : MF_GRAYED));
1295
1296 // Sub-menu items.
1297 hFileMenu = GetSubMenu(hMenu, 0);
1298 EnableMenuItem(hFileMenu, IDM_SAVE, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED));
1299 EnableMenuItem(hFileMenu, IDM_SAVEAS, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED));
1300 hFileMenu = GetSubMenu(hMenu, 2);
1301 EnableMenuItem(hFileMenu, IDM_FIND, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED));
1302 EnableMenuItem(hFileMenu, IDM_REPLACE, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED));
1303 DrawMenuBar(hwndMain);
1304 return 0;
1305 }
1306
1307 void CChildView::CmdSave(void){
1308 CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA);
1309
1310 if (!file)
1311 return;
1312 /* Untitled file ? */
1313 if (file->nFileOffset == 0){
1314 CmdSaveAs();
1315 return;
1316 }
1317
1318 if (!file->isInProject){
1319 // A simple file.
1320 Editor.SaveFile(file->szFileName);
1321 }else{
1322 // A project one.
1323 Project.szDirBuffer[Project.nFileOffset - 1] = '\\';
1324 strcpy(&Project.szDirBuffer[Project.nFileOffset], file->szFileName);
1325 Editor.SaveFile(Project.szDirBuffer);
1326 Project.szDirBuffer[Project.nFileOffset - 1] = '\0';
1327 }
1328 }
1329
1330 void CChildView::CmdSaveAs(void){
1331 CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA);
1332 if (!file)
1333 return;
1334
1335 char fileName[MAX_PATH];
1336 if (!winApp.FileDlg.Save(&winApp, fileName, MAX_PATH, SRC_FILE)) //@@
1337 return; // canceled by user
1338
1339 ::SetWindowText(_hWnd, fileName);
1340 strcpy(file->szFileName, fileName);
1341
1342 Editor.SaveFile(file->szFileName);
1343 //@@ TODO we need to check for errors
1344 }
1345
1346 BOOL CChildView::OnCommand(WPARAM wParam, LPARAM){
1347 CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA);
1348
1349 if(!file)
1350 return false;
1351
1352 switch (LOWORD(wParam)){
1353 case IDM_SAVE:
1354 CmdSave();
1355 break;
1356
1357 case IDM_SAVEAS:
1358 CmdSaveAs();
1359 break;
1360
1361 case IDM_SAVEALL:
1362 winApp.Manager.SaveAll(IDYES); // Silent.
1363 break;
1364
1365 /* case IDM_CLOSE:
1366 PostMessage(pWnd, WM_CLOSE, 0, 0);
1367 break;
1368 */
1369 // To Scintilla control.
1370 case IDM_FIND:
1371 EditorDlg.Find(&Editor);
1372 break;
1373
1374 case IDM_REPLACE:
1375 EditorDlg.Replace(&Editor);
1376 break;
1377
1378 case IDM_CUT:
1379 Editor.SendMessage(SCI_CUT);
1380 break;
1381 case IDM_COPY:
1382 Editor.SendMessage(SCI_COPY);
1383 break;
1384 case IDM_PASTE:
1385 Editor.SendMessage(SCI_PASTE);
1386 break;
1387 case IDM_UNDO:
1388 Editor.SendMessage(SCI_UNDO);
1389 break;
1390 case IDM_REDO:
1391 Editor.SendMessage(SCI_REDO);
1392 break;
1393 case IDM_SELECTALL:
1394 Editor.SendMessage(SCI_SELECTALL);
1395 break;
1396 }
1397 return TRUE;
1398 }
1399
1400
1401 /********************************************************************
1402 * Class: CManager.
1403 *
1404 * Purpose:
1405 *
1406 * Revisions:
1407 *
1408 ********************************************************************/
1409 CManager::CManager(){
1410 }
1411
1412 CManager::~CManager(){
1413 }
1414
1415 void CManager::OpenFileDialog(void){
1416 CFileItem * file = new CFileItem;
1417
1418 /* Show the "Open file" dialog */
1419 winApp.FileDlg.Reset();
1420 winApp.FileDlg.SetInitialDir(winApp.openFilesDir);
1421
1422 if(!winApp.FileDlg.Open(&winApp, file->szFileName, MAX_PATH, SRC_FILE)){
1423 delete file;
1424 return; // canceled by user
1425 }
1426
1427 /* Get file information */
1428 file->nFileExtension = winApp.FileDlg.GetFileExtension();
1429 file->nFileOffset = winApp.FileDlg.GetFileOffset();
1430 GetFileType(file);
1431 // Copy file directory.
1432 strncpy(winApp.openFilesDir, file->szFileName, (file->nFileOffset - 1));
1433 winApp.openFilesDir[file->nFileOffset-1] = '\0';
1434
1435 /* Load the file */
1436 if(!OpenFile(file)){
1437 delete file;
1438 MsgBox.DisplayString("This file is already opened.");
1439 }
1440 }
1441
1442 bool CManager::OpenFile(CFileItem * file){
1443 if (!file)
1444 return false;
1445
1446 if (!file->isInProject){
1447 if (!FilesView.OpenFile(file))
1448 return false;
1449 }else{
1450 if (!ProjectView.OpenFile(file))
1451 return false;
1452 }
1453 return true;
1454 }
1455
1456 bool CManager::NewProjectDialog(void){
1457 if(IDYES == Project.CloseDecision())
1458 CloseProject();
1459
1460 char fileName[MAX_PATH];
1461 WORD fileOffset;
1462 *fileName = '\0';
1463
1464
1465 if (!winApp.FileDlg.Save(&winApp, fileName, MAX_PATH, PRJ_FILE)){
1466 return false; // canceled by user
1467 }
1468 // Copy prj file's directory.
1469 fileOffset = winApp.FileDlg.GetFileOffset();
1470
1471 ProjectView.CreateRoot("Project");
1472 if (!Project.New(fileName, fileOffset)){
1473 ProjectView.DestroyRoot();
1474 ProjectView.DestroyList();
1475 return false;
1476 }
1477 return true;
1478 }
1479
1480 bool CManager::OpenProjectDialog(void){
1481 if(IDYES == Project.CloseDecision())
1482 CloseProject();
1483
1484 char fileName[MAX_PATH];
1485 WORD offset;
1486 *fileName = '\0';
1487
1488 // Load default values.
1489 winApp.FileDlg.Reset();
1490 winApp.FileDlg.SetInitialDir(winApp.projectDir);
1491
1492 if (!winApp.FileDlg.Open(&winApp, fileName, MAX_PATH, PRJ_FILE)){
1493 return false; // canceled by user
1494 }
1495 // Copy project file's directory.
1496 offset = winApp.FileDlg.GetFileOffset();
1497
1498 // Initialize project tree view.
1499 ProjectView.CreateRoot(fileName+offset);
1500
1501 if (!Project.Open(fileName, offset)){
1502 ProjectView.DestroyRoot();
1503 ProjectView.DestroyList();
1504 return false;
1505 }
1506 return true;
1507 }
1508
1509 bool CManager::CloseProject(void){
1510 return ProjectView.Close();
1511 }
1512
1513 void CManager::RemoveProjectFile(void){
1514 ProjectView.RemoveFile();
1515 }
1516
1517 void CManager::RemoveProjectModule(void){
1518 ProjectView.RemoveModule();
1519 }
1520
1521 int CManager::SaveProjectFiles(int decision){
1522 return ProjectView.SaveAll(decision);
1523 }
1524
1525 int CManager::SaveAll(int decision){
1526 /* Save open files ? */
1527 decision = FilesView.SaveAll(decision);
1528 /* Save project files ? */
1529 decision = ProjectView.SaveAll(decision);
1530 return decision;
1531 }
1532
1533 void CManager::CreateImageList(void){
1534 // Create an empty image list.
1535 ImgList.Create(16, 16, ILC_COLORDDB|ILC_MASK, 8, 1);
1536
1537 // Load treeview bmp and add it to the image list.
1538 CBitmap tvBitmap;
1539 tvBitmap.Load(this, IDB_TREEVIEW);
1540 ImgList.AddMasked(&tvBitmap, RGB(255,0,255));
1541
1542 // We no longer need treeview bmp.
1543 tvBitmap.Destroy();
1544 }
1545
1546 void CManager::Create(CWindow * pParent){
1547 // Create the Tab Control.
1548 CreateEx(
1549 pParent,
1550 WS_EX_CLIENTEDGE,
1551 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
1552 | TCS_BOTTOM | TCS_FOCUSNEVER);
1553
1554 // Give it the default font, create tabs, select first one and show the control.
1555 SendMessage(WM_SETFONT, (long) GetStockObject(DEFAULT_GUI_FONT), 0);
1556
1557 InsertItem(FILES_TAB, TCIF_TEXT, 0, 0, "Files", 16, 0, 0);
1558 InsertItem(PROJECT_TAB, TCIF_TEXT, 0, 0, "Project", 16, 0, 0);
1559 Show();
1560
1561 // Create an Image list and then the Project TreeView.
1562 CreateImageList();
1563 ProjectView.Create(this, &ImgList);
1564 SetItem_Param(PROJECT_TAB, (long) &ProjectView);
1565 FilesView.Create(this, &ImgList);
1566 SetItem_Param(FILES_TAB, (long) &FilesView);
1567 }
1568
1569 bool CManager::SetPosition(HWND, int x, int y, int width, int height, UINT){
1570 /* Overwrites CTabCtrl::SetPosition() so that all child windows are also resized */
1571
1572 // Tab Control.
1573 ::SetWindowPos(_hWnd, 0,
1574 x,
1575 y,
1576 width,
1577 height,
1578 0);
1579 // Child windows.
1580 RECT Rect;
1581 ::GetClientRect(_hWnd, &Rect);
1582 ProjectView.SetPosition(0, Rect.top +5, Rect.left +5,
1583 Rect.right-10, Rect.bottom-30, 0);
1584
1585 FilesView.SetPosition(0, Rect.top +5, Rect.left +5,
1586 Rect.right-10, Rect.bottom-30, 0);
1587 return true;
1588 }
1589
1590 BOOL CManager::OnNotify(int, LPNMHDR notify){
1591 // Dispatch messages.
1592 switch (notify->code){
1593 // Tab Control.
1594 case TCN_SELCHANGING:
1595 OnSelChanging(notify);
1596 break;
1597
1598 case TCN_SELCHANGE:
1599 OnSelChange(notify);
1600 break;
1601
1602 // TreeView.
1603 case TVN_SELCHANGED:
1604 Tv_OnSelchanged((LPNMTREEVIEW) notify);
1605 break;
1606 }
1607 return TRUE;
1608 }
1609
1610 void CManager::OnSelChanging(LPNMHDR notify){
1611 if (_hWnd == notify->hwndFrom){
1612 CTreeView * pTreeView = (CTreeView *) GetItem_Param(GetCurSel());
1613 if (pTreeView){
1614 pTreeView->Hide();
1615 }
1616 }
1617 }
1618
1619 void CManager::OnSelChange(LPNMHDR notify){
1620 if (_hWnd == notify->hwndFrom){
1621 CTreeView * pTreeView = (CTreeView *) GetItem_Param(GetCurSel());
1622 if (pTreeView){
1623 pTreeView->Show();
1624 }
1625 }
1626 }
1627
1628 void CManager::Tv_OnSelchanged(LPNMTREEVIEW notify){
1629 // Get lParam of current tree item.
1630 CFileItem * file = (CFileItem *) notify->itemNew.lParam;
1631
1632 if (file){
1633 CChildView * pMdiChild = (CChildView *) file->pMdiChild;
1634
1635 if(pMdiChild){
1636 // An editor, focus it.
1637 ::SetFocus((HWND) pMdiChild->_hWnd);
1638 }else{
1639 // No editor, the item is part of a project.
1640 Project.SwitchCurrentDir();
1641 winApp.CreateChild(file->szFileName, file);
1642 }
1643 }
1644 }
1645
1646
1647 /********************************************************************
1648 * Class: CFilesView.
1649 *
1650 * Purpose: Open files TreeView.
1651 *
1652 * Revisions:
1653 *
1654 ********************************************************************/
1655 CFilesView::CFilesView(){
1656 hRoot = NULL;
1657 }
1658
1659 CFilesView::~CFilesView(){
1660 }
1661
1662 void CFilesView::New(void){
1663 CFileItem * file = new CFileItem;
1664 if(!winApp.Manager.OpenFile(file)){
1665 delete file;
1666 MsgBox.DisplayString("Untitled file already exist.");
1667 }
1668 }
1669
1670 bool CFilesView::OpenFile(CFileItem * file){
1671 if (!file)
1672 return false;
1673
1674 int listAction;
1675 char * fileName = file->szFileName + file->nFileOffset;
1676
1677 /* Untitled file ? */
1678 if (file->nFileOffset == 0){
1679 //@@TODO add a counter to get Untitled01, 02, etc...
1680 strcpy(file->szFileName, "Untitled");
1681 }
1682
1683 /* Check if this file is already opened */
1684 listAction = InsertSorted_New(file);
1685
1686 if (listAction == FILE_FOUND){
1687 /* Focus the editor window */
1688 CFileItem * currentFile = (CFileItem *) GetCurrent();
1689 if (currentFile){
1690 CMDIChild * pMdiChild = currentFile->pMdiChild;
1691 if (pMdiChild)
1692 pMdiChild->SetFocus();
1693 }
1694 return false;
1695 }
1696
1697 /* Create the editor window */
1698 if (!winApp.CreateChild(file->szFileName, file)){
1699 MsgBox.DisplayFatal("Can't create child window");
1700 return false;
1701 }
1702 // Note: A WM_SETFOCUS message will be send to the child window.
1703
1704 /* Append the file to the list */
1705 InsertLast(file);
1706
1707 /* Create a Tree View item */
1708 file->_hItem = CreateItem(
1709 hRoot, //@@ use a GetRootItem() ?
1710 TVI_LAST,
1711 file->type,
1712 fileName,
1713 (LPARAM) file);
1714
1715 file->pTreeView = this;
1716 return true;
1717 }
1718
1719 void CFilesView::CloseFile(CFileItem * file){
1720 SendMessage(TVM_DELETEITEM, 0, (LPARAM) file->_hItem);
1721 Destroy(file);
1722 }
1723
1724 int CFilesView::SaveAll(int decision){
1725 if (decision == IDNO || decision == IDCANCEL)
1726 return decision;
1727 CFileItem * file = (CFileItem*) First();
1728 while (file){
1729 if (file->pMdiChild){
1730 CChildView * childView = (CChildView *) file->pMdiChild;
1731 /* Modified ? */
1732 if (childView->modified){
1733 /* Ask ? */
1734 if (decision == IDASK){
1735 decision = MsgBox.AskToSave(true); // Cancel button.
1736 if (decision != IDYES)
1737 return decision; // IDNO or IDCANCEL.
1738 }
1739 childView->CmdSave();
1740 }
1741 }
1742 file = (CFileItem*) Next();
1743 }
1744 return decision;
1745 }
1746
1747 HWND CFilesView::Create(CWindow * pParent, CImageList * imgList){
1748 // Create TreeView.
1749 CreateEx(
1750 pParent,
1751 WS_EX_CLIENTEDGE,
1752 WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
1753 | TVS_EDITLABELS | TVS_HASLINES | TVS_HASBUTTONS,
1754 0,
1755 (void*) 12);
1756
1757 // Assign the image list to the treeview control.
1758 SendMessage(TVM_SETIMAGELIST, (long)TVSIL_NORMAL, (long) imgList->GetId());
1759 hRoot = CreateItem(TVI_ROOT, TVI_LAST, WORKSPACE, "Workspace", 0);
1760 return _hWnd;
1761 }
1762
1763
1764 /********************************************************************
1765 * Class: CProjectView.
1766 *
1767 * Purpose: Project TreeView.
1768 *
1769 * Revisions:
1770 *
1771 ********************************************************************/
1772 CProjectView::CProjectView(){
1773 hRoot = NULL;
1774 }
1775
1776 CProjectView::~CProjectView(){
1777 }
1778
1779 CFileItem * CProjectView::NewFile(char * name){
1780 CFileItem * current = (CFileItem *) GetCurrent();
1781 CFileItem * srcFile = new CFileItem;
1782
1783 // Copy directory name.
1784 if (current){
1785 strncpy(srcFile->szFileName, current->szFileName, current->nFileOffset);
1786 srcFile->nFileOffset = current->nFileOffset;
1787 }else{
1788 // No files in the project yet, use makefile directory.
1789 strcpy(srcFile->szFileName, Project.Makefile.mkfDir);
1790 srcFile->nFileOffset = strlen(srcFile->szFileName)+1;
1791 }
1792
1793 srcFile->szFileName[srcFile->nFileOffset - 1] = '\\';
1794
1795 // Append file name.
1796 strcpy(&srcFile->szFileName[srcFile->nFileOffset], name);
1797 //MsgBox.DisplayString(srcFile->szFileName);
1798
1799 if (::CheckFile(srcFile)){
1800 ::GetFileType(srcFile);
1801 srcFile->isInProject = true;
1802 HANDLE hFile;
1803 hFile = ::CreateFile(srcFile->szFileName,
1804 0,
1805 0,
1806 NULL,
1807 CREATE_NEW,
1808 FILE_ATTRIBUTE_ARCHIVE,
1809 NULL);
1810
1811 if (hFile != INVALID_HANDLE_VALUE){
1812 CloseHandle(hFile);
1813 // Try to add new file to the project.
1814 if(OpenFile(srcFile)){
1815 Project.modified = true;
1816 return srcFile;
1817 }
1818 }
1819 }
1820 delete srcFile;
1821 return NULL;
1822 }
1823
1824 bool CProjectView::OpenFile(CFileItem * file){
1825 if (!file)
1826 return false;
1827
1828 int listAction;
1829 char * fileName = file->szFileName + file->nFileOffset;
1830
1831 /* Check if this file is already opened */
1832 listAction = InsertSorted_New(file);
1833
1834 if (listAction == FILE_FOUND){
1835 /* Focus the editor window */
1836 CFileItem * currentFile = (CFileItem *) GetCurrent();
1837 if (currentFile){
1838 CMDIChild * pMdiChild = currentFile->pMdiChild;
1839 if (!pMdiChild){
1840 /* Create a child window */
1841 Project.SwitchCurrentDir();
1842 winApp.CreateChild(file->szFileName, file);
1843 }else{
1844 pMdiChild->SetFocus();
1845 }
1846 }
1847 return false;
1848 }
1849
1850 file->_hDirItem = hRoot;
1851 CreateSubDirItem(file);
1852
1853 if (listAction == EMPTY_LIST){
1854 InsertFirst(file);
1855 }else if (listAction == INSERT_FIRST){
1856 InsertFirst(file);
1857 }else if (listAction == INSERT_LAST){
1858 InsertLast(file);
1859 }else if (listAction == INSERT_BEFORE){
1860 InsertBefore(file);
1861 }else if (listAction == INSERT_AFTER){
1862 InsertAfter(file);
1863 }
1864
1865 /* Create the file icon */
1866 file->_hItem = CreateItem(
1867 file->_hDirItem,
1868 TVI_SORT,
1869 file->type,
1870 fileName,
1871 (LPARAM) file);
1872
1873 file->pTreeView = this;
1874
1875 /* Create an editor view */
1876 if (file->show){
1877 winApp.CreateChild(file->szFileName, file);
1878 }
1879 return true;
1880 }
1881
1882 bool CProjectView::Close(){
1883 if (Project.NoProject())
1884 return false;
1885
1886 int decision = IDASK;
1887 decision = SaveAll(decision);
1888 if (decision == IDCANCEL)
1889 return false;
1890
1891 // Parse the list while there's a next node.
1892 CFileItem * srcFile = (CFileItem *) First();
1893 while(srcFile){
1894 DestroyFile(srcFile, decision);
1895 srcFile = (CFileItem *) Next();
1896 }
1897 Project.loaded = false;
1898
1899 DestroyRoot();
1900 DestroyList();
1901 winApp.Report.Clear();
1902 return true;
1903 }
1904
1905 void CProjectView::RemoveFile(void){
1906 if (Project.NoProject())
1907 return;
1908
1909 CFileItem * srcFile = (CFileItem *) GetSelectedItemParam();
1910
1911 if (srcFile){
1912 if (srcFile->pMdiChild)
1913 DestroyFile(srcFile);
1914 TreeView_DeleteItem(_hWnd, srcFile->_hItem);
1915 if (!TreeView_GetChild(_hWnd, srcFile->_hDirItem))
1916 TreeView_DeleteItem(_hWnd, srcFile->_hDirItem);
1917 /* else
1918 TreeView_SelectItem(_hWnd, srcFile->_hDirItem);*/
1919 Destroy(srcFile);
1920
1921 // we need to save prj file before exit.
1922 //@@ Project.CloseFile, modified & buildMakefile should be private.
1923 Project.modified = true;
1924 Project.buildMakefile = true;
1925 }else{
1926 MsgBox.DisplayWarning("No project file selected");
1927 }
1928 }
1929
1930 void CProjectView::RemoveModule(void){
1931 if (Project.NoProject())
1932 return;
1933
1934 CFileItem * srcFile = (CFileItem *) GetSelectedItemParam();
1935 CFileItem * otherFile;
1936
1937 if (srcFile){
1938 if (srcFile->prev){
1939 otherFile = (CFileItem *) srcFile->prev;
1940 if (otherFile->nFileExtension != 0){
1941 if (0 == strnicmp(srcFile->szFileName, otherFile->szFileName, otherFile->nFileExtension)){
1942 if (otherFile->pMdiChild)
1943 DestroyFile(otherFile);
1944 TreeView_DeleteItem(_hWnd, otherFile->_hItem);
1945 Destroy(otherFile);
1946 }
1947 }
1948 }
1949 if (srcFile->next){
1950 otherFile = (CFileItem *) srcFile->next;
1951 if (otherFile->nFileExtension != 0){
1952 if (0 == strnicmp(srcFile->szFileName, otherFile->szFileName, otherFile->nFileExtension)){
1953 if (otherFile->pMdiChild)
1954 DestroyFile(otherFile);
1955 TreeView_DeleteItem(_hWnd, otherFile->_hItem);
1956 Destroy(otherFile);
1957 }
1958 }
1959 }
1960 if (srcFile->pMdiChild)
1961 DestroyFile(srcFile);
1962 TreeView_DeleteItem(_hWnd, srcFile->_hItem);
1963 Destroy(srcFile);
1964
1965 // we need to save prj file before exit.
1966 //@@ Project.CloseFile, modified & buildMakefile should be private.
1967 Project.modified = true;
1968 Project.buildMakefile = true;
1969 }else{
1970 MsgBox.DisplayWarning("No project file selected");
1971 }
1972 }
1973
1974 int CProjectView::DestroyFile(CFileItem * file, int decision){
1975 if (file && file->pMdiChild){
1976 CChildView * pMdiChild = (CChildView *) file->pMdiChild;
1977
1978 if (pMdiChild->modified && decision != IDNO){
1979 // Ask ?
1980 if (decision == IDASK){
1981 decision = MsgBox.AskToSave(true); // (Cancel button)
1982 if (decision == IDCANCEL)
1983 return decision;
1984 }
1985 pMdiChild->CmdSave();
1986 }
1987
1988 if (pMdiChild->_hWnd) // have an editor window, so destroy it.
1989 winApp.MdiClient.SendMessage(WM_MDIDESTROY, (WPARAM)pMdiChild->_hWnd, 0);
1990 }
1991 return decision;
1992 }
1993
1994 int CProjectView::SaveAll(int decision){
1995 if (!Project.loaded)
1996 return 0;
1997
1998 if (decision == IDNO || decision == IDCANCEL)
1999 return decision;
2000
2001 CFileItem * file = (CFileItem*) First();
2002 while (file){
2003 if (file->pMdiChild){
2004 CChildView * childView = (CChildView *) file->pMdiChild;
2005 /* Modified ? */
2006 if (childView->modified){
2007 /* Ask ? */
2008 if (decision == IDASK){
2009 decision = MsgBox.AskToSave(true); // Cancel button.
2010 if (decision != IDYES)
2011 return decision; // IDNO or IDCANCEL.
2012 }
2013 childView->CmdSave();
2014 }
2015 }
2016 file = (CFileItem*) Next();
2017 }
2018
2019 if (Project.modified)
2020 return Project.SavePrjFile(decision);
2021 return decision;
2022 }
2023
2024 bool CProjectView::CreateSubDirItem(CFileItem * file){
2025 /* Initialize _hDirItem and get a pointer to current file */
2026 file->_hDirItem = hRoot;
2027 CFileItem * currentFile = (CFileItem *) GetCurrent();
2028
2029 /* See if our new file is in the same directory than current file */
2030 if (currentFile){
2031 // There's some files in the list.
2032 if (file->nFileOffset == currentFile->nFileOffset){
2033 // Same directory length, we may have found the directory.
2034 if (0 == strnicmp(file->szFileName, currentFile->szFileName, currentFile->nFileOffset)){
2035 /* We have found the directory, then copy _hDirItem */
2036 file->_hDirItem = currentFile->_hDirItem;
2037 return true;
2038 }
2039 }
2040 }
2041
2042 /* We need to parse the tree view and create directory icons */
2043 char * parse = file->szFileName;
2044 if (*parse == '.' && *(parse+1) == '\\'){
2045 /* This is a valid relative path */
2046 char dir[MAX_PATH];
2047 strcpy(dir, file->szFileName);
2048 parse = dir+2;
2049 char * dirStart;
2050 HTREEITEM hParent = hRoot;
2051 HTREEITEM hFound;
2052 if (*parse){
2053 for ( ; ; ){
2054 /* Found each backslash */
2055 dirStart = parse;
2056 parse = strchr(parse, '\\');
2057 if (!parse)
2058 break; // No more backslash.
2059 else if (parse == dirStart)
2060 return false; // Avoids an endless loop.
2061 *parse = '\0';
2062
2063 /* Find the directory */
2064 hFound = FindDirItem(hParent, dirStart);
2065 if (!hFound){
2066 /* Append a new directory icon */
2067 hParent = CreateDirItem(hParent, dirStart);
2068 }
2069 parse++;
2070 }
2071 }
2072 file->_hDirItem = hParent;
2073 }
2074 return true;
2075 }
2076
2077 HTREEITEM CProjectView::FindDirItem(HTREEITEM hItem, char * dir){
2078 char buffer[_MAX_DIR];
2079 HTREEITEM hNext = TreeView_GetChild(_hWnd, hItem);
2080 while (hNext){
2081 _TvItem.hItem = hNext;
2082 _TvItem.mask = TVIF_HANDLE | TVIF_TEXT;
2083 _TvItem.pszText = buffer;
2084 _TvItem.cchTextMax = _MAX_DIR;
2085 if (TreeView_GetItem(_hWnd, &_TvItem)){
2086 if (!stricmp(dir, buffer))
2087 return hNext;
2088 }
2089 hNext = TreeView_GetNextSibling(_hWnd, hNext);
2090 }
2091 return NULL;
2092 }
2093
2094 HWND CProjectView::Create(CWindow * pParent, CImageList * imgList){
2095 // Create TreeView.
2096 CreateEx(
2097 pParent,
2098 WS_EX_CLIENTEDGE,
2099 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
2100 | TVS_EDITLABELS | TVS_HASLINES | TVS_HASBUTTONS);
2101
2102 // Assign the image list to the treeview control.
2103 SendMessage(TVM_SETIMAGELIST, (long)TVSIL_NORMAL, (long) imgList->GetId());
2104 return _hWnd;
2105 }
2106
2107 void CProjectView::CreateRoot(char * projectName){
2108
2109 _pParent->SendMessage(TCM_SETCURFOCUS, 1, 0);
2110
2111 // Create Root Item.
2112 hRoot = CreateItem(TVI_ROOT, TVI_LAST, PROJECT, projectName, 0);
2113 SendMessage(TVM_EXPAND, (long) TVE_EXPAND, (long) hRoot);
2114 }
2115
2116 void CProjectView::DestroyRoot(void){
2117 TreeView_DeleteItem(_hWnd, hRoot);
2118 hRoot = 0;
2119
2120 _pParent->SendMessage(TCM_SETCURFOCUS, 0, 0);
2121 }
2122
2123 HTREEITEM CProjectView::CreateDirItem(HTREEITEM hParent, char * dir){
2124 return CreateItem(hParent, TVI_SORT, DIR, dir, 0);
2125 }
2126
2127 CFileItem * CProjectView::FindFile(char * szFileName){
2128 if (!szFileName || !*szFileName)
2129 return NULL;
2130
2131 char * currentFile;
2132 bool stripDir = true;
2133 if (*szFileName == '.')
2134 stripDir = false;
2135 // Get the current node.
2136 CFileItem * currentNode = (CFileItem *) GetCurrent();
2137
2138 if(!currentNode)
2139 return NULL; // The list is empty.
2140
2141 currentFile = GetFileName(currentNode, stripDir);
2142 int cmpResult = stricmp(szFileName, currentFile);
2143 // Compare names to know if we must parse Up
2144 // or Down from current node.
2145 if (cmpResult == 0){
2146 return currentNode; // Found !
2147 }
2148 // Search Up -----------------------------------------------------------------
2149 else if (cmpResult == -1){
2150 // Parse the list while there's a previous node.
2151 while (Prev()){
2152 currentNode = (CFileItem *) GetCurrent();
2153 currentFile = GetFileName(currentNode, stripDir);
2154 if(!stricmp(szFileName, currentFile))
2155 return currentNode; // Found !
2156 }
2157 }
2158 // Search Down --------------------------------------------------------------
2159 else if (cmpResult == 1){
2160 // Parse the list while there's a next node.
2161 while (Next()){
2162 currentNode = (CFileItem *) GetCurrent();
2163 currentFile = GetFileName(currentNode, stripDir);
2164 if(!stricmp(szFileName, currentFile))
2165 return currentNode; // Found !
2166 }
2167 }
2168 return NULL;
2169 }
2170
2171 char * CProjectView::GetFileName(CFileItem * currentNode, bool flag){
2172 char * fileName = currentNode->szFileName;
2173 if (flag == true){
2174 fileName += currentNode->nFileOffset;
2175 }
2176 return fileName;
2177 }
2178
2179
2180 /********************************************************************
2181 * Class: CReport.
2182 *
2183 * Purpose:
2184 *
2185 * Revisions:
2186 *
2187 ********************************************************************/
2188 CReport::CReport(){
2189 }
2190
2191 CReport::~CReport(){
2192 }
2193
2194 void CReport::Create(CWindow * pParent){
2195 // Create the Tab Control.
2196 CreateEx(
2197 pParent,
2198 WS_EX_CLIENTEDGE,
2199 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
2200 /*| TCS_BOTTOM*/ | TCS_MULTILINE | TCS_VERTICAL
2201 | TCS_FOCUSNEVER);
2202
2203 // Give it a smart font, create tabs, select first one and show the control.
2204 SendMessage(WM_SETFONT, (long) GetStockObject(DEFAULT_GUI_FONT), 0);
2205
2206 InsertItem(REPORT_MAIN_TAB, TCIF_TEXT, 0, 0, "Main", 16, 0, 0);
2207 InsertItem(REPORT_LOG_TAB, TCIF_TEXT, 0, 0, "Log", 16, 0, 0);
2208 Show();
2209
2210 // Create an Image list and then the Project TreeView.
2211 MainList.Create(this);
2212 SetItem_Param(REPORT_MAIN_TAB, (long) &MainList);
2213 LogList.Create(this);
2214 SetItem_Param(REPORT_LOG_TAB, (long) &LogList);
2215 }
2216
2217 bool CReport::SetPosition(HWND, int x, int y, int width, int height, UINT){
2218 /* Overwrites CTabCtrl::SetPosition() so that all child windows are also resized */
2219
2220 // Tab Control.
2221 ::SetWindowPos(_hWnd, 0,
2222 x,
2223 y,
2224 width,
2225 height,
2226 0);
2227
2228 // Get tab's display area.
2229 RECT area;
2230 area.left = 0;
2231 area.top = 0;
2232 area.right = width;
2233 area.bottom = height;
2234 ::SendMessage(_hWnd, TCM_ADJUSTRECT, FALSE, (LPARAM) &area);
2235 area.right -= area.left;
2236 area.bottom -= area.top;
2237 /* WS_EX_CLIENTEDGE correction */
2238 area.top -= 2;
2239 area.right -= 2;
2240 // Borders.
2241 area.left += 3;
2242 area.top += 3;
2243 area.right -= 6;
2244 area.bottom -= 6;
2245
2246 // Child windows.
2247 MainList.SetPosition(0, area.left, area.top,
2248 area.right, area.bottom, 0);
2249 LogList.SetPosition(0, area.left, area.top,
2250 area.right, area.bottom, 0);
2251 return true;
2252 }
2253
2254 BOOL CReport::OnNotify(int, LPNMHDR notify){
2255 // Dispatch messages.
2256 switch (notify->code){
2257 // Tab Control.
2258 case TCN_SELCHANGING:
2259 OnSelChanging(notify);
2260 break;
2261
2262 case TCN_SELCHANGE:
2263 OnSelChange(notify);
2264 break;
2265
2266 // Main list.
2267 case NM_DBLCLK:
2268 MainList.Lv_OnDbClick((LPNMLISTVIEW) notify);
2269 break;
2270 }
2271 return TRUE;
2272 }
2273
2274 void CReport::OnSelChanging(LPNMHDR notify){
2275 if (_hWnd == notify->hwndFrom){
2276 CWindow * pWindow = (CWindow *) GetItem_Param(GetCurSel());
2277 if (pWindow){
2278 pWindow->Hide();
2279 }
2280 }
2281 }
2282
2283 void CReport::OnSelChange(LPNMHDR notify){
2284 if (_hWnd == notify->hwndFrom){
2285 CWindow * pWindow = (CWindow *) GetItem_Param(GetCurSel());
2286 if (pWindow){
2287 pWindow->Show();
2288 }
2289 }
2290 }
2291
2292 void CReport::Clear(void){
2293 MainList.Clear();
2294 LogList.Clear();
2295 }
2296
2297 bool CReport::Append(char * line, WORD outputFlag){
2298 LogList.Append(line, outputFlag);
2299 MainList.Append(line, outputFlag);
2300 return true;
2301 }
2302
2303
2304 /********************************************************************
2305 * Class: CMainList.
2306 *
2307 * Purpose:
2308 *
2309 * Revisions:
2310 *
2311 ********************************************************************/
2312 CMainList::CMainList(){
2313 }
2314
2315 CMainList::~CMainList(){
2316 }
2317
2318 void CMainList::Create(CWindow * pParent){
2319 CreateEx(
2320 pParent,
2321 WS_EX_CLIENTEDGE,
2322 WS_VISIBLE | WS_CHILD| WS_CLIPCHILDREN | WS_CLIPSIBLINGS
2323 | LVS_REPORT);
2324
2325 SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,
2326 LVS_EX_GRIDLINES, LVS_EX_GRIDLINES);
2327 SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,
2328 LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
2329
2330 // Insert columns.
2331 LVCOLUMN lvc;
2332 lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
2333 lvc.fmt = LVCFMT_LEFT;
2334
2335 lvc.iSubItem = 0;
2336 lvc.cx = 35;
2337 lvc.pszText = "Line";
2338 SendMessage(LVM_INSERTCOLUMN, 0, (LPARAM) &lvc);
2339
2340 lvc.iSubItem = 1;
2341 lvc.cx = 70;
2342 lvc.pszText = "Unit";
2343 SendMessage(LVM_INSERTCOLUMN, 1, (LPARAM) &lvc);
2344
2345 lvc.iSubItem = 2;
2346 lvc.cx = 640;
2347 lvc.pszText = "Message";
2348 SendMessage(LVM_INSERTCOLUMN, 2, (LPARAM) &lvc);
2349 }
2350
2351 void CMainList::Lv_OnDbClick(LPNMLISTVIEW lpnmlv){
2352 if (_hWnd == lpnmlv->hdr.hwndFrom){
2353 char lineBuff[256];
2354 *lineBuff = '\0';
2355 char * c = lineBuff;
2356 LV_ITEM lvi;
2357 lvi.mask = LVIF_TEXT;
2358 lvi.iItem = lpnmlv->iItem;
2359 lvi.iSubItem = 0;
2360 lvi.pszText = lineBuff;
2361 lvi.cchTextMax = 256;
2362 lvi.lParam = 0;
2363 if (!SendMessage(LVM_GETITEMTEXT, lpnmlv->iItem, (long) &lvi))
2364 return;
2365 while(*c){
2366 if (!isdigit(*c))
2367 return;
2368 c++;
2369 }
2370 int line = atoi(lineBuff);
2371
2372 //MsgBox.DisplayLong((long) line);
2373
2374 lvi.iSubItem = 1;
2375 if (!SendMessage(LVM_GETITEMTEXT, lpnmlv->iItem, (long) &lvi))
2376 return;
2377 CFileItem * item = winApp.Manager.ProjectView.FindFile(lineBuff);
2378 if (item && item->isInProject){
2379 CChildView * pMdiChild = (CChildView *) item->pMdiChild;
2380
2381 if(pMdiChild){
2382 // An editor, focus it.
2383 ::SetFocus((HWND) pMdiChild->_hWnd);
2384 }else{
2385 // No editor, the item is part of a project.
2386 Project.SwitchCurrentDir();
2387 winApp.CreateChild(item->szFileName, item);
2388 }
2389 pMdiChild = (CChildView *) item->pMdiChild;
2390 if (pMdiChild)
2391 pMdiChild->Editor.GotoLine(line-1);
2392 }
2393 }
2394 }
2395
2396 bool CMainList::Append(char * line, WORD outputFlag){
2397 int row;
2398
2399 *szLine = '\0';
2400 *szUnit = '\0';
2401 *szMsg = '\0';
2402
2403 if (outputFlag == LVOUT_ERROR){
2404 if (!SplitErrorLine(line))
2405 return false;
2406 }else if (outputFlag == LVOUT_NORMAL){
2407 strcpy (szMsg, line);
2408 }else{
2409 strcpy (szMsg, "Unrecognized outputFlag");
2410 }
2411
2412 // Fill in List View columns, first is column 0.
2413 LV_ITEM lvi;
2414 lvi.mask = LVIF_TEXT; // | LVIF_PARAM;
2415 lvi.iItem = 0x7FFF;
2416 lvi.iSubItem = 0;
2417 lvi.pszText = szLine;
2418 lvi.cchTextMax = strlen(lvi.pszText)+1;
2419 lvi.lParam = 0;
2420
2421 row = SendMessage(LVM_INSERTITEM, 0, (LPARAM) &lvi);
2422
2423 // Continue with column 1.
2424 lvi.iSubItem = 1;
2425 lvi.pszText = szUnit;
2426 lvi.cchTextMax = strlen(lvi.pszText)+1;
2427 SendMessage(LVM_SETITEMTEXT, (WPARAM)row, (LPARAM)&lvi);
2428
2429 // Continue with column 2.
2430 lvi.iSubItem = 2;
2431 lvi.pszText = szMsg;
2432 lvi.cchTextMax = strlen(lvi.pszText)+1;
2433 SendMessage(LVM_SETITEMTEXT, (WPARAM)row, (LPARAM)&lvi);
2434
2435 // Save last row position
2436 lastRow = row+1;
2437
2438 return true;
2439 }
2440
2441 bool CMainList::SplitErrorLine(char * line){
2442 char * chr = line;
2443 char * col;
2444 // line => [unit]:[line_n°]: [error message]
2445 // or => [unit]: [error message]
2446
2447 if (!*line)
2448 return false;
2449
2450 /* Unit */
2451 col = szUnit;
2452 for ( ; ; ){
2453 if (!*chr){
2454 /* Not an error line */
2455 //strcpy(szMsg, szUnit);
2456 *szUnit = '\0';
2457 return false;
2458 }else if (*chr == ':'){
2459 if (*(chr+1) == '\\'){
2460 *col = *chr;
2461 col++;
2462 chr++;
2463 continue;
2464 }else{
2465 chr++;
2466 break;
2467 }
2468 }
2469 *col = *chr;
2470 col++;
2471 chr++;
2472 }
2473 *col = '\0';
2474
2475 /* Line number ? */
2476 col = szLine;
2477 if (*chr && isdigit(*chr)){ //@@ *chr=0 ?
2478 while (*chr && *chr != ':'){
2479 *col = *chr;
2480 col++;
2481 chr++;
2482 }
2483 *col = '\0';
2484 chr++;
2485 }
2486
2487 /* Message */
2488 col = szMsg;
2489 if (isspace(*chr)){
2490 /**col = '>';
2491 col++;
2492 *col = ' ';
2493 col++;*/
2494 chr++;
2495 }
2496
2497 while (*chr){
2498 *col = *chr;
2499 col++;
2500 chr++;
2501 }
2502 *col = '\0';
2503 return true;
2504 }
2505
2506
2507 /********************************************************************
2508 * Class: CLogList.
2509 *
2510 * Purpose:
2511 *
2512 * Revisions:
2513 *
2514 ********************************************************************/
2515 CLogList::CLogList(){
2516 }
2517
2518 CLogList::~CLogList(){
2519 }
2520
2521 void CLogList::Create(CWindow * pParent){
2522 CreateEx(
2523 pParent,
2524 WS_EX_CLIENTEDGE,
2525 WS_CHILD| WS_CLIPCHILDREN | WS_CLIPSIBLINGS | LVS_REPORT
2526 | LVS_NOCOLUMNHEADER);
2527
2528 SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,
2529 LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
2530
2531 // Insert columns.
2532 LVCOLUMN lvc;
2533 lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
2534 lvc.fmt = LVCFMT_LEFT;
2535
2536 lvc.iSubItem = 0;
2537 lvc.cx = 100;
2538 lvc.pszText = "Message";
2539 SendMessage(LVM_INSERTCOLUMN, 0, (LPARAM) &lvc);
2540 }
2541
2542 bool CLogList::SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags){
2543 ::SendMessage(_hWnd, WM_SETREDRAW, FALSE, 0);
2544 ::SetWindowPos(_hWnd, hInsertAfter, x, y, width, height, uFlags);
2545 ::SendMessage(_hWnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM((int) width-22, 0));
2546 ::SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0);
2547 return true;
2548 }
2549
2550 bool CLogList::Append(char * line, WORD /*outputFlag*/){
2551 int row;
2552
2553 *szMsg = '\0';
2554
2555 /* if (outputFlag != LVOUT_ERROR)
2556 return false;
2557 */
2558 // Fill in List View columns, first is column 0.
2559 LV_ITEM lvi;
2560 lvi.mask = LVIF_TEXT; // | LVIF_PARAM;
2561 lvi.iItem = 0x7FFF;
2562 lvi.iSubItem = 0;
2563 lvi.pszText = line;
2564 lvi.cchTextMax = strlen(lvi.pszText)+1;
2565 lvi.lParam = 0;
2566
2567 row = SendMessage(LVM_INSERTITEM, 0, (LPARAM) &lvi);
2568
2569 // Save last row position
2570 lastRow = row+1;
2571
2572 return true;
2573 }
2574
2575
2576 /********************************************************************
2577 * Class: CFileItem.
2578 *
2579 * Purpose: Linked List Node for file parameters.
2580 *
2581 * Revisions:
2582 *
2583 ********************************************************************/
2584 CFileItem::CFileItem(){
2585 type = U_FILE;
2586
2587 *szFileName = '\0';
2588 szFileName[MAX_PATH - 1] = '\0'; // security.
2589 nFileOffset = 0;
2590 nFileExtension = 0;
2591
2592 pTreeView = NULL;
2593 _hDirItem = 0;
2594 _hItem = 0;
2595
2596 pMdiChild = NULL;
2597 show = 0;
2598 isInProject = false;
2599 }
2600
2601 CFileItem::~CFileItem(){
2602 }
2603
2604
2605 /********************************************************************
2606 * Class: CFileList.
2607 *
2608 * Purpose: A CList with a dedicated Compare() procedure.
2609 *
2610 * Revisions:
2611 *
2612 ********************************************************************/
2613 CFileList::CFileList(){
2614 }
2615
2616 CFileList::~CFileList(){
2617 }
2618
2619 int CFileList::Compare(CNode *node1, CNode *node2){
2620 return stricmp(((CFileItem *)node1)->szFileName, ((CFileItem *)node2)->szFileName);
2621 }
2622