File: CommandForm.cpp

package info (click to toggle)
cccc 3.pre84-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k, lenny
  • size: 3,816 kB
  • ctags: 4,969
  • sloc: ansic: 33,244; cpp: 10,694; java: 622; makefile: 164; sh: 11
file content (325 lines) | stat: -rw-r--r-- 8,637 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
// CommandForm.cpp : implementation file
//


#include "stdafx.h"

// Turn off warnings due to long names arising out of STL use
#pragma warning ( disable : 4786 4503 )

#include "CcccDevStudioAddIn.h"
#include "CommandForm.h"

#include <list>
#include <string>
#include <fstream>

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

namespace
{
	// This namespace encapsulates a function to search for 
	// a particular file in a list of directories.
	// Parameter fileName is initialized with the unqualified name
	// of the file which is sought, while path contains a list of 
	// strings for the directories where the file might be.
	typedef std::list<std::string> PathList;

	bool findFileOnPath(std::string& fileName, const PathList& path)
	{
		bool retval=false;
		PathList::const_iterator plIter=path.begin();
		while( (retval==false) && (plIter!=path.end()) )
		{
			std::string testName=*plIter+fileName;
			std::ifstream testStr(testName.c_str());
			if(testStr.good())
			{
				retval=true;
				fileName="\""+testName+"\"";

			}
			plIter++;
		}
		return retval;
	} // end of findFileOnPath()
} // end of anonymous namespace

// The standard for registry paths appears to be Software/<vendor>/<package>
// hence the fact that I am putting my name in your registry.
// It's not just vanity, honest.
HKEY registryTopLevelKey=HKEY_CURRENT_USER;
const char* registryKeyPath="Software\\TimLittlefair\\CcccDevStudioAddIn";
const char* registryValueName="STRINGS";

const int BUF_SIZE=10240;

/////////////////////////////////////////////////////////////////////////////
// CCommandForm dialog


CCommandForm::CCommandForm(CWnd* pParent /*=NULL*/)
	: CDialog(CCommandForm::IDD, pParent)
{
	//{{AFX_DATA_INIT(CCommandForm)
	//}}AFX_DATA_INIT

	loadConfiguration();
}

CCommandForm::~CCommandForm()
{
	saveConfiguration();
}

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

	DDX_Text(pDX, IDC_EDIT1, m_Cmd[0]);
	DDX_Text(pDX, IDC_EDIT2, m_Cmd[1]);
	DDX_Text(pDX, IDC_EDIT3, m_Cmd[2]);
	DDX_Text(pDX, IDC_EDIT4, m_Cmd[3]);
	DDX_Text(pDX, IDC_EDIT5, m_Cmd[4]);
	DDX_Text(pDX, IDC_EDIT6, m_Cmd[5]);
	DDX_Text(pDX, IDC_EDIT7, m_Cmd[6]);
	DDX_Text(pDX, IDC_EDIT8, m_Cmd[7]);

	// save the modified information in the registry
	saveConfiguration();
}


BEGIN_MESSAGE_MAP(CCommandForm, CDialog)
	//{{AFX_MSG_MAP(CCommandForm)
	ON_BN_CLICKED(IDC_BUTTON1, OnDefaults)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCommandForm message handlers

void CCommandForm::setDefaults()
{
	// This function is virtual so that it could
	// be overridden for a specific application

	// For the moment I am hard-coding the strings required
	// for my CCCC AddIn app here, but it would be better to 
	// inherit and override.

	// The next string is used in the message displayed at the end of
	// this function.
	std::string missingFiles;

	// The command to run CCCC.
	std::string ccccName="cccc.exe";
	PathList ccccSearchPath;
	ccccSearchPath.push_back("C:\\Program Files\\CCCC\\");
	if( findFileOnPath(ccccName,ccccSearchPath) )
	{
		m_Cmd[0]=ccccName.c_str();
	}
	else
	{
		m_Cmd[0]="echo No location configured for CCCC.EXE";
		missingFiles="the program CCCC.EXE";
	}

	// We also need to know the location of a browser.
	// The default is to search a couple of likely locations for
	// a copy of Internet Explorer.  This is very much the lowest common
	// denominator because I know it is more likely to be present than
	// not.  The CCCC report should be equally easy to read with a version
	// of Netscape/Mozilla, Opera, or any other graphical browser (lynx won't
	// work too well, I'm afraid).
	// I would welcome advice on other locations IE might be in: the two below
	// reflect my Win95 OSR2 box at home and WinNT 4.0 at work, so I assume that
	// Win98, Win98SE and Win2000 may need still different locations.
	// If you find one of these, please mail me on tim_littlefair@hotmail.com.
	std::string browserName="iexplore.exe";
	PathList browserSearchPath;
	browserSearchPath.push_back("C:\\Program Files\\Plus!\\Microsoft Internet\\");
	browserSearchPath.push_back("C:\\Program Files\\Internet Explorer\\");
	if( findFileOnPath(browserName,browserSearchPath) )
	{
		m_Cmd[1]=browserName.c_str() ;
	}
	else
	{
		m_Cmd[1]="echo No location configured for HTML browser";
		if(missingFiles.size()>0)
		{
			missingFiles+=" and ";
		}
		missingFiles+="a program to browse HTML reports";
	}

	// Finally, report back on the process
	std::string message;
	if(missingFiles.size()==0)
	{
		message="The add-in has configured itself to use";
		message+=m_Cmd[0];
		message+=" to analyze files and ";
		message+=m_Cmd[1];
		message+=" to browse the resulting HTML reports.  ";
		message+="These locations can be changed at any time using the ";
		message+="configuration toolbar button.";
	}
	else
	{
		message="The add-in's self-configuration script has been "
			"unable too find ";
		message+=missingFiles;
		message+=".  You will need to use the configuration toolbar "
			"button to specify a location for the missing program(s) "
			"before using the add-in to analyze files.";
	}

	AfxMessageBox(message.c_str());

	// save the configuration data in the registry.
	saveConfiguration();
}

CString CCommandForm::cmdText(int index)
{
	CString retval;
	if(index>=0 && index<8)
	{
		retval=m_Cmd[index];
	}
	return retval;
}

void CCommandForm::OnDefaults() 
{
	// TODO: Add your control notification handler code here
	setDefaults();	
	EndDialog(IDCANCEL);
}

void CCommandForm::loadConfiguration()
{
	// The VC doco says that the RegCreateKey API is only provided 
	// for legacy compatibility, but it seems to be less fussy
	// than other alternatives.
	HKEY configKey;
	DWORD type;
	unsigned char stringBuffer[BUF_SIZE];
	DWORD sbufLen=BUF_SIZE;

	LONG keyStatus=RegCreateKey(
		registryTopLevelKey,registryKeyPath,&configKey);

	if(keyStatus!=ERROR_SUCCESS)
	{
		// failed to create or open the key
		// fall back on the defaults
		setDefaults();
	}
	else
	{		
		LONG queryStatus=RegQueryValueEx(
			configKey,registryValueName,0,
			&type,stringBuffer,&sbufLen);
		if(queryStatus==ERROR_SUCCESS && type==REG_MULTI_SZ)
		{
			// Success - suck in the values
			int i=0;

			// The Win32 API uses unsigned chars which makes it 
			// unsuitable for passing to strlen etc.
			// Hence we keep two differently typed pointers which
			// we move over the same memory locations.
			unsigned char *uptr=stringBuffer;
			char *ptr=reinterpret_cast<char*>(uptr);
			while(i<8 && uptr<(stringBuffer+sbufLen-2))
			{
				// copy the current null terminated string to a 
				// member of the local array
				m_Cmd[i]=ptr;
				// advance ptr to point to the character after the 
				// terminating zero byte
				ptr+=strlen(ptr)+1;
				uptr+=strlen(ptr)+1;
				i++;
			}
		}
		else
		{
			// Whereas not finding the key is a normal situation for first
			// running the program, finding the key but then not finding the
			// value is an unexpected situation, so we report it.
			AfxMessageBox(
				"Registry value query failed, "
				"default configuration will be used. "
				);
			setDefaults();
		}
		RegCloseKey(configKey);
	}
}

void CCommandForm::saveConfiguration()
{
	HKEY configKey;
	unsigned char stringBuffer[BUF_SIZE];
	DWORD sbufLen=BUF_SIZE;

	LONG keyStatus=RegCreateKey(
		registryTopLevelKey,registryKeyPath,&configKey);

	if(keyStatus!=ERROR_SUCCESS)
	{
		// failed to create or open the key
		// fall back on the defaults
		AfxMessageBox("Failed to open registry key");
		setDefaults();
	}
	else
	{		
		// pump out the values
		int i=0;
		memset(stringBuffer,0,BUF_SIZE);
		
		// The Win32 API uses unsigned chars which makes it 
		// unsuitable for passing to strlen etc.
		// Hence we keep two differently typed pointers which
		// we move over the same memory locations.
		unsigned char *uptr=stringBuffer;
		char *ptr=reinterpret_cast<char*>(uptr);
		while(i<8 && (uptr+strlen(ptr)+2)<(stringBuffer+sbufLen) )
		{
			// copy the current string into the buffer, starting at ptr
			strcpy(ptr,m_Cmd[i]);

			// advance ptr to point to the character after the 
			// terminating zero byte
			ptr+=strlen(ptr)+1;
			uptr+=strlen(ptr)+1;
			i++;
		}
		LONG setStatus=RegSetValueEx(
			configKey,registryValueName,0,
			REG_MULTI_SZ,stringBuffer,sbufLen);
		if(setStatus==ERROR_SUCCESS)
		{
			// success - nothing more to do
		}
		else
		{
			AfxMessageBox("Failed to set registry value");
		}
		RegCloseKey(configKey);
	}

}