1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4 
5 This file is part of Quake 2 Tools source code.
6 
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 
23 #include "qe3.h"
24 #include <process.h>
25 #include "mru.h"
26 #include "entityw.h"
27 
28 static HWND      s_hwndToolbar;
29 
30 BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize);
31 BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize);
32 
33 static HWND CreateMyStatusWindow(HINSTANCE hInst);
34 static HWND CreateToolBar(HINSTANCE hinst);
35 
36 extern int WXY_Print( void );
37 
38 /*
39 ==============================================================================
40 
41   MENU
42 
43 ==============================================================================
44 */
45 
46 void OpenDialog (void);
47 void SaveAsDialog (void);
48 qboolean ConfirmModified (void);
49 void  Select_Ungroup (void);
50 
QE_ExpandBspString(char * bspaction,char * out,char * mapname)51 void QE_ExpandBspString (char *bspaction, char *out, char *mapname)
52 {
53 	char	*in;
54 	char	src[1024];
55 	char	rsh[1024];
56 	char	base[256];
57 
58 	ExtractFileName (mapname, base);
59 	sprintf (src, "%s/maps/%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base);
60 	strcpy (rsh, ValueForKey(g_qeglobals.d_project_entity, "rshcmd"));
61 
62 	in = ValueForKey( g_qeglobals.d_project_entity, bspaction );
63 	while (*in)
64 	{
65 		if (in[0] == '!')
66 		{
67 			strcpy (out, rsh);
68 			out += strlen(rsh);
69 			in++;
70 			continue;
71 		}
72 		if (in[0] == '$')
73 		{
74 			strcpy (out, src);
75 			out += strlen(src);
76 			in++;
77 			continue;
78 		}
79 		if (in[0] == '@')
80 		{
81 			*out++ = '"';
82 			in++;
83 			continue;
84 		}
85 		*out++ = *in++;
86 	}
87 	*out = 0;
88 }
89 
90 
91 
RunBsp(char * command)92 void RunBsp (char *command)
93 {
94 	char	sys[1024];
95 	char	batpath[1024];
96 	char	outputpath[1024];
97 	char	temppath[512];
98 	char	name[1024];
99 	FILE	*hFile;
100 	BOOL	ret;
101 	PROCESS_INFORMATION ProcessInformation;
102 	STARTUPINFO	startupinfo;
103 
104 	SetInspectorMode (W_CONSOLE);
105 
106 	if (bsp_process)
107 	{
108 		Sys_Printf ("BSP is still going...\n");
109 		return;
110 	}
111 
112 	GetTempPath(512, temppath);
113 	sprintf (outputpath, "%sjunk.txt", temppath);
114 
115 	strcpy (name, currentmap);
116 	if (region_active)
117 	{
118 		Map_SaveFile (name, false);
119 		StripExtension (name);
120 		strcat (name, ".reg");
121 	}
122 
123 	Map_SaveFile (name, region_active);
124 
125 
126 	QE_ExpandBspString (command, sys, name);
127 
128 	Sys_ClearPrintf ();
129 	Sys_Printf ("======================================\nRunning bsp command...\n");
130 	Sys_Printf ("\n%s\n", sys);
131 
132 	//
133 	// write qe3bsp.bat
134 	//
135 	sprintf (batpath, "%sqe3bsp.bat", temppath);
136 	hFile = fopen(batpath, "w");
137 	if (!hFile)
138 		Error ("Can't write to %s", batpath);
139 	fprintf (hFile, sys);
140 	fclose (hFile);
141 
142 	//
143 	// write qe3bsp2.bat
144 	//
145 	sprintf (batpath, "%sqe3bsp2.bat", temppath);
146 	hFile = fopen(batpath, "w");
147 	if (!hFile)
148 		Error ("Can't write to %s", batpath);
149 	fprintf (hFile, "%sqe3bsp.bat > %s", temppath, outputpath);
150 	fclose (hFile);
151 
152 	Pointfile_Delete ();
153 
154 	GetStartupInfo (&startupinfo);
155 
156 	ret = CreateProcess(
157     batpath,		// pointer to name of executable module
158     NULL,			// pointer to command line string
159     NULL,			// pointer to process security attributes
160     NULL,			// pointer to thread security attributes
161     FALSE,			// handle inheritance flag
162     0 /*DETACHED_PROCESS*/,		// creation flags
163     NULL,			// pointer to new environment block
164     NULL,			// pointer to current directory name
165     &startupinfo,	// pointer to STARTUPINFO
166     &ProcessInformation 	// pointer to PROCESS_INFORMATION
167    );
168 
169 	if (!ret)
170 		Error ("CreateProcess failed");
171 
172 	bsp_process = ProcessInformation.hProcess;
173 
174 	Sleep (100);	// give the new process a chance to open it's window
175 
176 	BringWindowToTop( g_qeglobals.d_hwndMain );	// pop us back on top
177 	SetFocus (g_qeglobals.d_hwndCamera);
178 }
179 
180 /*
181 =============
182 DoColor
183 
184 =============
185 */
DoColor(int iIndex)186 qboolean DoColor(int iIndex)
187 {
188 	CHOOSECOLOR	cc;
189 	static COLORREF	custom[16];
190 
191 	cc.lStructSize = sizeof(cc);
192 	cc.hwndOwner = g_qeglobals.d_hwndMain;
193 	cc.hInstance = g_qeglobals.d_hInstance;
194 	cc.rgbResult =
195 		(int)(g_qeglobals.d_savedinfo.colors[iIndex][0]*255) +
196 		(((int)(g_qeglobals.d_savedinfo.colors[iIndex][1]*255))<<8) +
197 		(((int)(g_qeglobals.d_savedinfo.colors[iIndex][2]*255))<<16);
198     cc.lpCustColors = custom;
199     cc.Flags = CC_FULLOPEN|CC_RGBINIT;
200     //cc.lCustData;
201     //cc.lpfnHook;
202     //cc.lpTemplateName
203 
204 	if (!ChooseColor(&cc))
205 		return false;
206 
207 	g_qeglobals.d_savedinfo.colors[iIndex][0] = (cc.rgbResult&255)/255.0;
208 	g_qeglobals.d_savedinfo.colors[iIndex][1] = ((cc.rgbResult>>8)&255)/255.0;
209 	g_qeglobals.d_savedinfo.colors[iIndex][2] = ((cc.rgbResult>>16)&255)/255.0;
210 
211 	/*
212 	** scale colors so that at least one component is at 1.0F
213 	** if this is meant to select an entity color
214 	*/
215 	if ( iIndex == COLOR_ENTITY )
216 	{
217 		float largest = 0.0F;
218 
219 		if ( g_qeglobals.d_savedinfo.colors[iIndex][0] > largest )
220 			largest = g_qeglobals.d_savedinfo.colors[iIndex][0];
221 		if ( g_qeglobals.d_savedinfo.colors[iIndex][1] > largest )
222 			largest = g_qeglobals.d_savedinfo.colors[iIndex][1];
223 		if ( g_qeglobals.d_savedinfo.colors[iIndex][2] > largest )
224 			largest = g_qeglobals.d_savedinfo.colors[iIndex][2];
225 
226 		if ( largest == 0.0F )
227 		{
228 			g_qeglobals.d_savedinfo.colors[iIndex][0] = 1.0F;
229 			g_qeglobals.d_savedinfo.colors[iIndex][1] = 1.0F;
230 			g_qeglobals.d_savedinfo.colors[iIndex][2] = 1.0F;
231 		}
232 		else
233 		{
234 			float scaler = 1.0F / largest;
235 
236 			g_qeglobals.d_savedinfo.colors[iIndex][0] *= scaler;
237 			g_qeglobals.d_savedinfo.colors[iIndex][1] *= scaler;
238 			g_qeglobals.d_savedinfo.colors[iIndex][2] *= scaler;
239 		}
240 	}
241 
242 	Sys_UpdateWindows (W_ALL);
243 
244 	return true;
245 }
246 
247 
248 /* Copied from MSDN */
249 
DoMru(HWND hWnd,WORD wId)250 BOOL DoMru(HWND hWnd,WORD wId)
251 {
252 	char szFileName[128];
253 	OFSTRUCT of;
254 	BOOL fExist;
255 
256 	GetMenuItem(g_qeglobals.d_lpMruMenu, wId, TRUE, szFileName, sizeof(szFileName));
257 
258 	// Test if the file exists.
259 
260 	fExist = OpenFile(szFileName ,&of,OF_EXIST) != HFILE_ERROR;
261 
262 	if (fExist) {
263 
264 		// Place the file on the top of MRU.
265 		AddNewItem(g_qeglobals.d_lpMruMenu,(LPSTR)szFileName);
266 
267 		// Now perform opening this file !!!
268 		Map_LoadFile (szFileName);
269 	}
270 	else
271 		// Remove the file on MRU.
272 		DelMenuItem(g_qeglobals.d_lpMruMenu,wId,TRUE);
273 
274 	// Refresh the File menu.
275 	PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0),
276 			ID_FILE_EXIT);
277 
278 	return fExist;
279 }
280 
281 
282 /* handle all WM_COMMAND messages here */
CommandHandler(HWND hWnd,WPARAM wParam,LPARAM lParam)283 LONG WINAPI CommandHandler (
284     HWND    hWnd,
285     WPARAM  wParam,
286     LPARAM  lParam)
287 {
288 	HMENU hMenu;
289 
290     switch (LOWORD(wParam))
291     {
292 //
293 // file menu
294 //
295     	case ID_FILE_EXIT:
296             /* exit application */
297 			if (!ConfirmModified())
298 				return TRUE;
299 
300             PostMessage (hWnd, WM_CLOSE, 0, 0L);
301 			break;
302 
303 		case ID_FILE_OPEN:
304 			if (!ConfirmModified())
305 				return TRUE;
306 			OpenDialog ();
307 			break;
308 
309 		case ID_FILE_NEW:
310 			if (!ConfirmModified())
311 				return TRUE;
312 			Map_New ();
313 			break;
314 		case ID_FILE_SAVE:
315 			if (!strcmp(currentmap, "unnamed.map"))
316 				SaveAsDialog ();
317 			else
318 				Map_SaveFile (currentmap, false);	// ignore region
319 			break;
320 		case ID_FILE_SAVEAS:
321 			SaveAsDialog ();
322 			break;
323 
324 		case ID_FILE_LOADPROJECT:
325 			if (!ConfirmModified())
326 				return TRUE;
327 			ProjectDialog ();
328 			break;
329 
330 		case ID_FILE_POINTFILE:
331 			if (g_qeglobals.d_pointfile_display_list)
332 				Pointfile_Clear ();
333 			else
334 				Pointfile_Check ();
335 			break;
336 
337 //
338 // view menu
339 //
340 		case ID_VIEW_ENTITY:
341 			SetInspectorMode(W_ENTITY);
342 			break;
343 		case ID_VIEW_CONSOLE:
344 			SetInspectorMode(W_CONSOLE);
345 			break;
346 		case ID_VIEW_TEXTURE:
347 			SetInspectorMode(W_TEXTURE);
348 			break;
349 
350 		case ID_VIEW_100:
351 			g_qeglobals.d_xy.scale = 1;
352 			Sys_UpdateWindows (W_XY|W_XY_OVERLAY);
353 			break;
354 		case ID_VIEW_ZOOMIN:
355 			g_qeglobals.d_xy.scale *= 5.0/4;
356 			if (g_qeglobals.d_xy.scale > 16)
357 				g_qeglobals.d_xy.scale = 16;
358 			Sys_UpdateWindows (W_XY|W_XY_OVERLAY);
359 			break;
360 		case ID_VIEW_ZOOMOUT:
361 			g_qeglobals.d_xy.scale *= 4.0/5;
362 			if (g_qeglobals.d_xy.scale < 0.1)
363 				g_qeglobals.d_xy.scale = 0.1;
364 			Sys_UpdateWindows (W_XY|W_XY_OVERLAY);
365 			break;
366 
367 		case ID_VIEW_Z100:
368 			z.scale = 1;
369 			Sys_UpdateWindows (W_Z|W_Z_OVERLAY);
370 			break;
371 		case ID_VIEW_ZZOOMIN:
372 			z.scale *= 5.0/4;
373 			if (z.scale > 4)
374 				z.scale = 4;
375 			Sys_UpdateWindows (W_Z|W_Z_OVERLAY);
376 			break;
377 		case ID_VIEW_ZZOOMOUT:
378 			z.scale *= 4.0/5;
379 			if (z.scale < 0.125)
380 				z.scale = 0.125;
381 			Sys_UpdateWindows (W_Z|W_Z_OVERLAY);
382 			break;
383 
384 		case ID_VIEW_CENTER:
385 			camera.angles[ROLL] = camera.angles[PITCH] = 0;
386 			camera.angles[YAW] = 22.5 *
387 				floor( (camera.angles[YAW]+11)/22.5 );
388 			Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
389 			break;
390 
391 		case ID_VIEW_UPFLOOR:
392 			Cam_ChangeFloor (true);
393 			break;
394 		case ID_VIEW_DOWNFLOOR:
395 			Cam_ChangeFloor (false);
396 			break;
397 
398 		case ID_VIEW_SHOWNAMES:
399 			g_qeglobals.d_savedinfo.show_names = !g_qeglobals.d_savedinfo.show_names;
400 			CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWNAMES, MF_BYCOMMAND | (g_qeglobals.d_savedinfo.show_names ? MF_CHECKED : MF_UNCHECKED)  );
401 			Map_BuildBrushData();
402 			Sys_UpdateWindows (W_XY);
403 			break;
404 
405 		case ID_VIEW_SHOWCOORDINATES:
406 			g_qeglobals.d_savedinfo.show_coordinates ^= 1;
407 			CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | (g_qeglobals.d_savedinfo.show_coordinates ? MF_CHECKED : MF_UNCHECKED)  );
408 			Sys_UpdateWindows (W_XY);
409 			break;
410 
411 		case ID_VIEW_SHOWBLOCKS:
412 			g_qeglobals.show_blocks ^= 1;
413 			CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWBLOCKS, MF_BYCOMMAND | (g_qeglobals.show_blocks ? MF_CHECKED : MF_UNCHECKED)  );
414 			Sys_UpdateWindows (W_XY);
415 			break;
416 
417 		case ID_VIEW_SHOWLIGHTS:
418 			if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_LIGHTS ) & EXCLUDE_LIGHTS )
419 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED );
420 			else
421 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_CHECKED );
422 			Sys_UpdateWindows (W_XY|W_CAMERA);
423 			break;
424 
425 		case ID_VIEW_SHOWPATH:
426 			if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_PATHS ) & EXCLUDE_PATHS )
427 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED );
428 			else
429 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_CHECKED );
430 			Sys_UpdateWindows (W_XY|W_CAMERA);
431 			break;
432 
433 		case ID_VIEW_SHOWENT:
434 			if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_ENT ) & EXCLUDE_ENT )
435 				CheckMenuItem( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWENT, MF_BYCOMMAND | MF_UNCHECKED);
436 			else
437 				CheckMenuItem( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWENT, MF_BYCOMMAND | MF_CHECKED);
438 			Sys_UpdateWindows (W_XY|W_CAMERA);
439 			break;
440 
441 		case ID_VIEW_SHOWWATER:
442 			if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_WATER ) & EXCLUDE_WATER )
443 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED );
444 			else
445 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_CHECKED );
446 			Sys_UpdateWindows (W_XY|W_CAMERA);
447 			break;
448 
449 		case ID_VIEW_SHOWCLIP:
450 			if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_CLIP ) & EXCLUDE_CLIP )
451 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED );
452 			else
453 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_CHECKED );
454 			Sys_UpdateWindows (W_XY|W_CAMERA);
455 			break;
456 
457 		case ID_VIEW_SHOWDETAIL:
458 			if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_DETAIL ) & EXCLUDE_DETAIL )
459 			{
460 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWDETAIL, MF_BYCOMMAND | MF_UNCHECKED );
461 				SetWindowText (g_qeglobals.d_hwndCamera, "Camera View (DETAIL EXCLUDED)");
462 			}
463 			else
464 			{
465 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWDETAIL, MF_BYCOMMAND | MF_CHECKED );
466 				SetWindowText (g_qeglobals.d_hwndCamera, "Camera View");
467 			}
468 			Sys_UpdateWindows (W_XY|W_CAMERA);
469 			break;
470 
471 		case ID_VIEW_SHOWWORLD:
472 			if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_WORLD ) & EXCLUDE_WORLD )
473 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED );
474 			else
475 				CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_CHECKED );
476 			Sys_UpdateWindows (W_XY|W_CAMERA);
477 			break;
478 
479 
480 //
481 // grid menu
482 //
483 		case ID_GRID_1:
484 		case ID_GRID_2:
485 		case ID_GRID_4:
486 		case ID_GRID_8:
487 		case ID_GRID_16:
488 		case ID_GRID_32:
489 		case ID_GRID_64:
490 		{
491 			hMenu = GetMenu(hWnd);
492 
493 			CheckMenuItem(hMenu, ID_GRID_1, MF_BYCOMMAND | MF_UNCHECKED);
494 			CheckMenuItem(hMenu, ID_GRID_2, MF_BYCOMMAND | MF_UNCHECKED);
495 			CheckMenuItem(hMenu, ID_GRID_4, MF_BYCOMMAND | MF_UNCHECKED);
496 			CheckMenuItem(hMenu, ID_GRID_8, MF_BYCOMMAND | MF_UNCHECKED);
497 			CheckMenuItem(hMenu, ID_GRID_16, MF_BYCOMMAND | MF_UNCHECKED);
498 			CheckMenuItem(hMenu, ID_GRID_32, MF_BYCOMMAND | MF_UNCHECKED);
499 			CheckMenuItem(hMenu, ID_GRID_64, MF_BYCOMMAND | MF_UNCHECKED);
500 
501 			switch (LOWORD(wParam))
502 			{
503 				case ID_GRID_1: g_qeglobals.d_gridsize = 0; break;
504 				case ID_GRID_2: g_qeglobals.d_gridsize = 1; break;
505 				case ID_GRID_4: g_qeglobals.d_gridsize = 2; break;
506 				case ID_GRID_8: g_qeglobals.d_gridsize = 3; break;
507 				case ID_GRID_16: g_qeglobals.d_gridsize = 4; break;
508 				case ID_GRID_32: g_qeglobals.d_gridsize = 5; break;
509 				case ID_GRID_64: g_qeglobals.d_gridsize = 6; break;
510 			}
511 			g_qeglobals.d_gridsize = 1 << g_qeglobals.d_gridsize;
512 
513 			CheckMenuItem(hMenu, LOWORD(wParam), MF_BYCOMMAND | MF_CHECKED);
514 			Sys_UpdateWindows (W_XY|W_Z);
515 			break;
516 		}
517 
518 //
519 // texture menu
520 //
521 		case ID_VIEW_NEAREST:
522 		case ID_VIEW_NEARESTMIPMAP:
523 		case ID_VIEW_LINEAR:
524 		case ID_VIEW_BILINEAR:
525 		case ID_VIEW_BILINEARMIPMAP:
526 		case ID_VIEW_TRILINEAR:
527 		case ID_TEXTURES_WIREFRAME:
528 		case ID_TEXTURES_FLATSHADE:
529 			Texture_SetMode (LOWORD(wParam));
530 			break;
531 
532 		case ID_TEXTURES_SHOWINUSE:
533 			Sys_BeginWait ();
534 			Texture_ShowInuse ();
535 			SetInspectorMode(W_TEXTURE);
536 			break;
537 
538 		case ID_TEXTURES_INSPECTOR:
539 			DoSurface ();
540 			break;
541 
542 		case CMD_TEXTUREWAD:
543 		case CMD_TEXTUREWAD+1:
544 		case CMD_TEXTUREWAD+2:
545 		case CMD_TEXTUREWAD+3:
546 		case CMD_TEXTUREWAD+4:
547 		case CMD_TEXTUREWAD+5:
548 		case CMD_TEXTUREWAD+6:
549 		case CMD_TEXTUREWAD+7:
550 		case CMD_TEXTUREWAD+8:
551 		case CMD_TEXTUREWAD+9:
552 		case CMD_TEXTUREWAD+10:
553 		case CMD_TEXTUREWAD+11:
554 		case CMD_TEXTUREWAD+12:
555 		case CMD_TEXTUREWAD+13:
556 		case CMD_TEXTUREWAD+14:
557 		case CMD_TEXTUREWAD+15:
558 		case CMD_TEXTUREWAD+16:
559 		case CMD_TEXTUREWAD+17:
560 		case CMD_TEXTUREWAD+18:
561 		case CMD_TEXTUREWAD+19:
562 		case CMD_TEXTUREWAD+20:
563 		case CMD_TEXTUREWAD+21:
564 		case CMD_TEXTUREWAD+22:
565 		case CMD_TEXTUREWAD+23:
566 		case CMD_TEXTUREWAD+24:
567 		case CMD_TEXTUREWAD+25:
568 		case CMD_TEXTUREWAD+26:
569 		case CMD_TEXTUREWAD+27:
570 		case CMD_TEXTUREWAD+28:
571 		case CMD_TEXTUREWAD+29:
572 		case CMD_TEXTUREWAD+30:
573 		case CMD_TEXTUREWAD+31:
574 			Sys_BeginWait ();
575 			Texture_ShowDirectory (LOWORD(wParam));
576 			SetInspectorMode(W_TEXTURE);
577 			break;
578 
579 //
580 // bsp menu
581 //
582 		case CMD_BSPCOMMAND:
583 		case CMD_BSPCOMMAND+1:
584 		case CMD_BSPCOMMAND+2:
585 		case CMD_BSPCOMMAND+3:
586 		case CMD_BSPCOMMAND+4:
587 		case CMD_BSPCOMMAND+5:
588 		case CMD_BSPCOMMAND+6:
589 		case CMD_BSPCOMMAND+7:
590 		case CMD_BSPCOMMAND+8:
591 		case CMD_BSPCOMMAND+9:
592 		case CMD_BSPCOMMAND+10:
593 		case CMD_BSPCOMMAND+11:
594 		case CMD_BSPCOMMAND+12:
595 		case CMD_BSPCOMMAND+13:
596 		case CMD_BSPCOMMAND+14:
597 		case CMD_BSPCOMMAND+15:
598 		case CMD_BSPCOMMAND+16:
599 		case CMD_BSPCOMMAND+17:
600 		case CMD_BSPCOMMAND+18:
601 		case CMD_BSPCOMMAND+19:
602 		case CMD_BSPCOMMAND+20:
603 		case CMD_BSPCOMMAND+21:
604 		case CMD_BSPCOMMAND+22:
605 		case CMD_BSPCOMMAND+23:
606 		case CMD_BSPCOMMAND+24:
607 		case CMD_BSPCOMMAND+25:
608 		case CMD_BSPCOMMAND+26:
609 		case CMD_BSPCOMMAND+27:
610 		case CMD_BSPCOMMAND+28:
611 		case CMD_BSPCOMMAND+29:
612 		case CMD_BSPCOMMAND+30:
613 		case CMD_BSPCOMMAND+31:
614 			{
615 				extern	char	*bsp_commands[256];
616 
617 				RunBsp (bsp_commands[LOWORD(wParam-CMD_BSPCOMMAND)]);
618 			}
619 			break;
620 
621 //
622 // misc menu
623 //
624 		case ID_MISC_BENCHMARK:
625 			SendMessage ( g_qeglobals.d_hwndCamera,
626 			WM_USER+267,	0, 0);
627 			break;
628 
629 		case ID_TEXTUREBK:
630 			DoColor(COLOR_TEXTUREBACK);
631 			Sys_UpdateWindows (W_ALL);
632 			break;
633 
634 		case ID_MISC_SELECTENTITYCOLOR:
635 			{
636 				extern int inspector_mode;
637 
638 				if ( ( inspector_mode == W_ENTITY ) && DoColor(COLOR_ENTITY) == true )
639 				{
640 					extern void AddProp( void );
641 
642 					char buffer[100];
643 
644 					sprintf( buffer, "%f %f %f", g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][0],
645 						g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][1],
646 						g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][2] );
647 
648 					SetWindowText( hwndEnt[EntValueField], buffer );
649 					SetWindowText( hwndEnt[EntKeyField], "_color" );
650 					AddProp();
651 				}
652 				Sys_UpdateWindows( W_ALL );
653 			}
654 			break;
655 
656 		case ID_MISC_PRINTXY:
657 			WXY_Print();
658 			break;
659 
660 		case ID_COLORS_XYBK:
661 			DoColor(COLOR_GRIDBACK);
662 			Sys_UpdateWindows (W_ALL);
663 			break;
664 
665 		case ID_COLORS_MAJOR:
666 			DoColor(COLOR_GRIDMAJOR);
667 			Sys_UpdateWindows (W_ALL);
668 			break;
669 
670 		case ID_COLORS_MINOR:
671 			DoColor(COLOR_GRIDMINOR);
672 			Sys_UpdateWindows (W_ALL);
673 			break;
674 
675 		case ID_MISC_GAMMA:
676 			DoGamma();
677 			break;
678 
679 		case ID_MISC_FINDBRUSH:
680 			DoFind();
681 			break;
682 
683 		case ID_MISC_NEXTLEAKSPOT:
684 			Pointfile_Next();
685 			break;
686 		case ID_MISC_PREVIOUSLEAKSPOT:
687 			Pointfile_Prev();
688 			break;
689 
690 //
691 // brush menu
692 //
693 		case ID_BRUSH_3SIDED:
694 			Brush_MakeSided (3);
695 			break;
696 		case ID_BRUSH_4SIDED:
697 			Brush_MakeSided (4);
698 			break;
699 		case ID_BRUSH_5SIDED:
700 			Brush_MakeSided (5);
701 			break;
702 		case ID_BRUSH_6SIDED:
703 			Brush_MakeSided (6);
704 			break;
705 		case ID_BRUSH_7SIDED:
706 			Brush_MakeSided (7);
707 			break;
708 		case ID_BRUSH_8SIDED:
709 			Brush_MakeSided (8);
710 			break;
711 		case ID_BRUSH_9SIDED:
712 			Brush_MakeSided (9);
713 			break;
714 		case ID_BRUSH_ARBITRARYSIDED:
715 			DoSides ();
716 			break;
717 
718 //
719 // select menu
720 //
721 		case ID_BRUSH_FLIPX:
722 			Select_FlipAxis (0);
723 			break;
724 		case ID_BRUSH_FLIPY:
725 			Select_FlipAxis (1);
726 			break;
727 		case ID_BRUSH_FLIPZ:
728 			Select_FlipAxis (2);
729 			break;
730 		case ID_BRUSH_ROTATEX:
731 			Select_RotateAxis (0, 90);
732 			break;
733 		case ID_BRUSH_ROTATEY:
734 			Select_RotateAxis (1, 90);
735 			break;
736 		case ID_BRUSH_ROTATEZ:
737 			Select_RotateAxis (2, 90);
738 			break;
739 
740 		case ID_SELECTION_ARBITRARYROTATION:
741 			DoRotate ();
742 			break;
743 
744 		case ID_SELECTION_UNGROUPENTITY:
745 			Select_Ungroup ();
746 			break;
747 
748 		case ID_SELECTION_CONNECT:
749 			ConnectEntities ();
750 			break;
751 
752 		case ID_SELECTION_DRAGVERTECIES:
753 			if (g_qeglobals.d_select_mode == sel_vertex)
754 			{
755 				g_qeglobals.d_select_mode = sel_brush;
756 				Sys_UpdateWindows (W_ALL);
757 			}
758 			else
759 			{
760 				SetupVertexSelection ();
761 				if (g_qeglobals.d_numpoints)
762 					g_qeglobals.d_select_mode = sel_vertex;
763 			}
764 			break;
765 		case ID_SELECTION_DRAGEDGES:
766 			if (g_qeglobals.d_select_mode == sel_edge)
767 			{
768 				g_qeglobals.d_select_mode = sel_brush;
769 				Sys_UpdateWindows (W_ALL);
770 			}
771 			else
772 			{
773 				SetupVertexSelection ();
774 				if (g_qeglobals.d_numpoints)
775 					g_qeglobals.d_select_mode = sel_edge;
776 			}
777 			break;
778 
779 		case ID_SELECTION_SELECTPARTIALTALL:
780 			Select_PartialTall ();
781 			break;
782 		case ID_SELECTION_SELECTCOMPLETETALL:
783 			Select_CompleteTall ();
784 			break;
785 		case ID_SELECTION_SELECTTOUCHING:
786 			Select_Touching ();
787 			break;
788 		case ID_SELECTION_SELECTINSIDE:
789 			Select_Inside ();
790 			break;
791 		case ID_SELECTION_CSGSUBTRACT:
792 			CSG_Subtract ();
793 			break;
794 		case ID_SELECTION_MAKEHOLLOW:
795 			CSG_MakeHollow ();
796 			break;
797 
798 		case ID_SELECTION_CLONE:
799 			Select_Clone ();
800 			break;
801 		case ID_SELECTION_DELETE:
802 			Select_Delete ();
803 			break;
804 		case ID_SELECTION_DESELECT:
805 			Select_Deselect ();
806 			break;
807 
808 		case ID_SELECTION_MAKE_DETAIL:
809 			Select_MakeDetail ();
810 			break;
811 		case ID_SELECTION_MAKE_STRUCTURAL:
812 			Select_MakeStructural ();
813 			break;
814 
815 
816 //
817 // region menu
818 //
819 		case ID_REGION_OFF:
820 			Map_RegionOff ();
821 			break;
822 		case ID_REGION_SETXY:
823 			Map_RegionXY ();
824 			break;
825 		case ID_REGION_SETTALLBRUSH:
826 			Map_RegionTallBrush ();
827 			break;
828 		case ID_REGION_SETBRUSH:
829 			Map_RegionBrush ();
830 			break;
831 		case ID_REGION_SETSELECTION:
832 			Map_RegionSelectedBrushes ();
833 			break;
834 
835 		case IDMRU+1:
836 		case IDMRU+2:
837 		case IDMRU+3:
838 		case IDMRU+4:
839 		case IDMRU+5:
840 		case IDMRU+6:
841 		case IDMRU+7:
842 		case IDMRU+8:
843 		case IDMRU+9:
844 			DoMru(hWnd,LOWORD(wParam));
845 			break;
846 
847 //
848 // help menu
849 //
850 
851 		case ID_HELP_ABOUT:
852 			DoAbout();
853 			break;
854 
855 		default:
856             return FALSE;
857     }
858 
859     return TRUE;
860 }
861 
862 /*
863 ============
864 WMAIN_WndProc
865 ============
866 */
WMAIN_WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)867 LONG WINAPI WMAIN_WndProc (
868     HWND    hWnd,
869     UINT    uMsg,
870     WPARAM  wParam,
871     LPARAM  lParam)
872 {
873     LONG    lRet = 1;
874     RECT	rect;
875 	HDC		maindc;
876 
877     GetClientRect(hWnd, &rect);
878 
879     switch (uMsg)
880     {
881 	case WM_TIMER:
882 		QE_CountBrushesAndUpdateStatusBar();
883 		QE_CheckAutoSave();
884 		return 0;
885 
886 	case WM_DESTROY:
887 		SaveMruInReg(g_qeglobals.d_lpMruMenu,"Software\\id\\QuakeEd4\\MRU");
888 		DeleteMruMenu(g_qeglobals.d_lpMruMenu);
889 		PostQuitMessage(0);
890 		KillTimer( hWnd, QE_TIMER0 );
891 		return 0;
892 
893 	case WM_CREATE:
894         maindc = GetDC(hWnd);
895 //	    QEW_SetupPixelFormat(maindc, false);
896 		g_qeglobals.d_lpMruMenu = CreateMruMenuDefault();
897 		LoadMruInReg(g_qeglobals.d_lpMruMenu,"Software\\id\\QuakeEd4\\MRU");
898 
899 		// Refresh the File menu.
900 		PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0),
901 				ID_FILE_EXIT);
902 
903 		return 0;
904 
905 	case WM_SIZE:
906 		// resize the status window
907 		MoveWindow( g_qeglobals.d_hwndStatus, -100, 100, 10, 10, true);
908 		return 0;
909 
910 	case WM_KEYDOWN:
911 		return QE_KeyDown (wParam);
912 
913    	case WM_CLOSE:
914         /* call destroy window to cleanup and go away */
915 		SaveWindowState(g_qeglobals.d_hwndXY, "xywindow");
916 		SaveWindowState(g_qeglobals.d_hwndCamera, "camerawindow");
917 		SaveWindowState(g_qeglobals.d_hwndZ, "zwindow");
918 		SaveWindowState(g_qeglobals.d_hwndEntity, "EntityWindow");
919 		SaveWindowState(g_qeglobals.d_hwndMain, "mainwindow");
920 
921 		// FIXME: is this right?
922 		SaveRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, sizeof(g_qeglobals.d_savedinfo));
923         DestroyWindow (hWnd);
924 		return 0;
925 
926     case WM_COMMAND:
927 		return CommandHandler (hWnd, wParam, lParam);
928 		return 0;
929     }
930 
931     return DefWindowProc (hWnd, uMsg, wParam, lParam);
932 }
933 
934 
935 
936 
937 /*
938 ==============
939 Main_Create
940 ==============
941 */
Main_Create(HINSTANCE hInstance)942 void Main_Create (HINSTANCE hInstance)
943 {
944     WNDCLASS   wc;
945 	int		   i;
946 	HMENU      hMenu;
947 
948     /* Register the camera class */
949 	memset (&wc, 0, sizeof(wc));
950 
951     wc.style         = 0;
952     wc.lpfnWndProc   = (WNDPROC)WMAIN_WndProc;
953     wc.cbClsExtra    = 0;
954     wc.cbWndExtra    = 0;
955     wc.hInstance     = hInstance;
956     wc.hIcon         = 0;
957     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
958     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
959     wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU1);
960     wc.lpszClassName = "QUAKE_MAIN";
961 
962     if (!RegisterClass (&wc) )
963         Error ("WCam_Register: failed");
964 
965 
966 	g_qeglobals.d_hwndMain = CreateWindow ("QUAKE_MAIN" ,
967 		"QuakeEd 3",
968 		WS_OVERLAPPEDWINDOW |
969 		WS_CLIPSIBLINGS |
970 		WS_CLIPCHILDREN,
971 		0,0,screen_width,screen_height+GetSystemMetrics(SM_CYSIZE),	// size
972 		0,
973 		0,		// no menu
974 		hInstance,
975 		NULL);
976 	if (!g_qeglobals.d_hwndMain)
977 		Error ("Couldn't create main window");
978 
979 	/* create a timer so that we can count brushes */
980 	SetTimer( g_qeglobals.d_hwndMain,
981 			  QE_TIMER0,
982 			  1000,
983 		      NULL );
984 
985 	LoadWindowState(g_qeglobals.d_hwndMain, "mainwindow");
986 
987 	s_hwndToolbar = CreateToolBar(hInstance);
988 
989 	g_qeglobals.d_hwndStatus = CreateMyStatusWindow(hInstance);
990 
991 	//
992 	// load misc info from registry
993 	//
994 	i = sizeof(g_qeglobals.d_savedinfo);
995 	LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &i);
996 
997 	if (g_qeglobals.d_savedinfo.iSize != sizeof(g_qeglobals.d_savedinfo))
998 	{
999 		// fill in new defaults
1000 
1001 		g_qeglobals.d_savedinfo.iSize = sizeof(g_qeglobals.d_savedinfo);
1002 		g_qeglobals.d_savedinfo.fGamma = 1.0;
1003 		g_qeglobals.d_savedinfo.iTexMenu = ID_VIEW_NEAREST;
1004 
1005 		g_qeglobals.d_savedinfo.exclude = 0;
1006 		g_qeglobals.d_savedinfo.show_coordinates = true;
1007 		g_qeglobals.d_savedinfo.show_names       = true;
1008 
1009 		for (i=0 ; i<3 ; i++)
1010 		{
1011 			g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25;
1012 			g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0;
1013 			g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.75;
1014 			g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5;
1015 			g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25;
1016 		}
1017 	}
1018 
1019 	if ( ( hMenu = GetMenu( g_qeglobals.d_hwndMain ) ) != 0 )
1020 	{
1021 		/*
1022 		** by default all of these are checked because that's how they're defined in the menu editor
1023 		*/
1024 		if ( !g_qeglobals.d_savedinfo.show_names )
1025 			CheckMenuItem( hMenu, ID_VIEW_SHOWNAMES, MF_BYCOMMAND | MF_UNCHECKED );
1026 		if ( !g_qeglobals.d_savedinfo.show_coordinates )
1027 			CheckMenuItem( hMenu, ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | MF_UNCHECKED );
1028 
1029 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS )
1030 			CheckMenuItem( hMenu, ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED );
1031 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT )
1032 			CheckMenuItem( hMenu, ID_VIEW_ENTITY, MF_BYCOMMAND | MF_UNCHECKED );
1033 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS )
1034 			CheckMenuItem( hMenu, ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED );
1035 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER )
1036 			CheckMenuItem( hMenu, ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED );
1037 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD )
1038 			CheckMenuItem( hMenu, ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED );
1039 		if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP )
1040 			CheckMenuItem( hMenu, ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED );
1041 	}
1042 
1043 	ShowWindow (g_qeglobals.d_hwndMain, SW_SHOWDEFAULT);
1044 }
1045 
1046 
1047 /*
1048 =============================================================
1049 
1050 REGISTRY INFO
1051 
1052 =============================================================
1053 */
1054 
SaveRegistryInfo(const char * pszName,void * pvBuf,long lSize)1055 BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize)
1056 {
1057 	LONG lres;
1058 	DWORD dwDisp;
1059 	HKEY  hKeyId;
1060 
1061 	lres = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\id\\QuakeEd4", 0, NULL,
1062 			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp);
1063 
1064 	if (lres != ERROR_SUCCESS)
1065 		return FALSE;
1066 
1067 	lres = RegSetValueEx(hKeyId, pszName, 0, REG_BINARY, pvBuf, lSize);
1068 
1069 	RegCloseKey(hKeyId);
1070 
1071 	if (lres != ERROR_SUCCESS)
1072 		return FALSE;
1073 
1074 	return TRUE;
1075 }
1076 
LoadRegistryInfo(const char * pszName,void * pvBuf,long * plSize)1077 BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize)
1078 {
1079 	HKEY  hKey;
1080 	long lres, lType, lSize;
1081 
1082 	if (plSize == NULL)
1083 		plSize = &lSize;
1084 
1085 	lres = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\id\\QuakeEd4", 0, KEY_READ, &hKey);
1086 
1087 	if (lres != ERROR_SUCCESS)
1088 		return FALSE;
1089 
1090 	lres = RegQueryValueEx(hKey, pszName, NULL, &lType, pvBuf, plSize);
1091 
1092 	RegCloseKey(hKey);
1093 
1094 	if (lres != ERROR_SUCCESS)
1095 		return FALSE;
1096 
1097 	return TRUE;
1098 }
1099 
SaveWindowState(HWND hWnd,const char * pszName)1100 BOOL SaveWindowState(HWND hWnd, const char *pszName)
1101 {
1102 	RECT rc;
1103 
1104 	GetWindowRect(hWnd, &rc);
1105 	if (hWnd != g_qeglobals.d_hwndMain)
1106 		MapWindowPoints(NULL, g_qeglobals.d_hwndMain, (POINT *)&rc, 2);
1107 	return SaveRegistryInfo(pszName, &rc, sizeof(rc));
1108 }
1109 
1110 
LoadWindowState(HWND hWnd,const char * pszName)1111 BOOL LoadWindowState(HWND hWnd, const char *pszName)
1112 {
1113 	RECT rc;
1114 	LONG lSize = sizeof(rc);
1115 
1116 	if (LoadRegistryInfo(pszName, &rc, &lSize))
1117 	{
1118 		if (rc.left < 0)
1119 			rc.left = 0;
1120 		if (rc.top < 0)
1121 			rc.top = 0;
1122 		if (rc.right < rc.left + 16)
1123 			rc.right = rc.left + 16;
1124 		if (rc.bottom < rc.top + 16)
1125 			rc.bottom = rc.top + 16;
1126 
1127 		MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left,
1128 				rc.bottom - rc.top, FALSE);
1129 		return TRUE;
1130 	}
1131 
1132 	return FALSE;
1133 }
1134 
1135 /*
1136 ===============================================================
1137 
1138   STATUS WINDOW
1139 
1140 ===============================================================
1141 */
1142 
Sys_UpdateStatusBar(void)1143 void Sys_UpdateStatusBar( void )
1144 {
1145 	extern int   g_numbrushes, g_numentities;
1146 
1147 	char numbrushbuffer[100]="";
1148 
1149 	sprintf( numbrushbuffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities );
1150 
1151 	Sys_Status( numbrushbuffer, 2 );
1152 }
1153 
Sys_Status(const char * psz,int part)1154 void Sys_Status(const char *psz, int part )
1155 {
1156 	SendMessage(g_qeglobals.d_hwndStatus, SB_SETTEXT, part, (LPARAM)psz);
1157 }
1158 
CreateMyStatusWindow(HINSTANCE hInst)1159 static HWND CreateMyStatusWindow(HINSTANCE hInst)
1160 {
1161 	HWND hWnd;
1162 	int partsize[3] = { 300, 1100, -1 };
1163 
1164 	hWnd = CreateWindowEx( WS_EX_TOPMOST, // no extended styles
1165             STATUSCLASSNAME,                 // status bar
1166             "",                              // no text
1167             WS_CHILD | WS_BORDER | WS_VISIBLE,  // styles
1168             -100, -100, 10, 10,              // x, y, cx, cy
1169             g_qeglobals.d_hwndMain,          // parent window
1170             (HMENU)100,                      // window ID
1171             hInst,                           // instance
1172             NULL);							 // window data
1173 
1174 	SendMessage( hWnd, SB_SETPARTS, 3, ( long ) partsize );
1175 
1176 	return hWnd;
1177 }
1178 
1179 //==============================================================
1180 
1181 #define NUMBUTTONS 15
CreateToolBar(HINSTANCE hinst)1182 HWND CreateToolBar(HINSTANCE hinst)
1183 {
1184     HWND hwndTB;
1185     TBADDBITMAP tbab;
1186     TBBUTTON tbb[NUMBUTTONS];
1187 
1188      // Ensure that the common control DLL is loaded.
1189 
1190     InitCommonControls();
1191 
1192     // Create a toolbar that the user can customize and that has a
1193     // tooltip associated with it.
1194 
1195     hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, (LPSTR) NULL,
1196         WS_CHILD | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE | WS_BORDER,
1197         0, 0, 0, 0, g_qeglobals.d_hwndMain, (HMENU) IDR_TOOLBAR1, hinst, NULL);
1198 
1199     // Send the TB_BUTTONSTRUCTSIZE message, which is required for
1200     // backward compatibility.
1201 
1202     SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
1203 
1204     // Add the bitmap containing button images to the toolbar.
1205 
1206     tbab.hInst = hinst;
1207     tbab.nID   = IDR_TOOLBAR1;
1208     SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM)NUMBUTTONS, (WPARAM) &tbab);
1209 
1210     // Fill the TBBUTTON array with button information, and add the
1211     // buttons to the toolbar.
1212 
1213     tbb[0].iBitmap = 0;
1214     tbb[0].idCommand = ID_BRUSH_FLIPX;
1215     tbb[0].fsState = TBSTATE_ENABLED;
1216     tbb[0].fsStyle = TBSTYLE_BUTTON;
1217     tbb[0].dwData = 0;
1218     tbb[0].iString = 0;
1219 
1220     tbb[1].iBitmap = 2;
1221     tbb[1].idCommand = ID_BRUSH_FLIPY;
1222     tbb[1].fsState = TBSTATE_ENABLED;
1223     tbb[1].fsStyle = TBSTYLE_BUTTON;
1224     tbb[1].dwData = 0;
1225     tbb[1].iString = 0;
1226 
1227     tbb[2].iBitmap = 4;
1228     tbb[2].idCommand = ID_BRUSH_FLIPZ;
1229     tbb[2].fsState = TBSTATE_ENABLED;
1230     tbb[2].fsStyle = TBSTYLE_BUTTON;
1231     tbb[2].dwData = 0;
1232     tbb[2].iString = 0;
1233 
1234     tbb[3].iBitmap = 1;
1235     tbb[3].idCommand = ID_BRUSH_ROTATEX;
1236     tbb[3].fsState = TBSTATE_ENABLED;
1237     tbb[3].fsStyle = TBSTYLE_BUTTON;
1238     tbb[3].dwData = 0;
1239     tbb[3].iString = 0;
1240 
1241     tbb[4].iBitmap = 3;
1242     tbb[4].idCommand = ID_BRUSH_ROTATEY;
1243     tbb[4].fsState = TBSTATE_ENABLED;
1244     tbb[4].fsStyle = TBSTYLE_BUTTON;
1245     tbb[4].dwData = 0;
1246     tbb[4].iString = 0;
1247 
1248     tbb[5].iBitmap = 5;
1249     tbb[5].idCommand = ID_BRUSH_ROTATEZ;
1250     tbb[5].fsState = TBSTATE_ENABLED;
1251     tbb[5].fsStyle = TBSTYLE_BUTTON;
1252     tbb[5].dwData = 0;
1253     tbb[5].iString = 0;
1254 
1255     tbb[6].iBitmap = 6;
1256     tbb[6].idCommand = ID_SELECTION_SELECTCOMPLETETALL;
1257     tbb[6].fsState = TBSTATE_ENABLED;
1258     tbb[6].fsStyle = TBSTYLE_BUTTON;
1259     tbb[6].dwData = 0;
1260     tbb[6].iString = 0;
1261 
1262     tbb[7].iBitmap = 7;
1263     tbb[7].idCommand = ID_SELECTION_SELECTTOUCHING;
1264     tbb[7].fsState = TBSTATE_ENABLED;
1265     tbb[7].fsStyle = TBSTYLE_BUTTON;
1266     tbb[7].dwData = 0;
1267     tbb[7].iString = 0;
1268 
1269     tbb[8].iBitmap = 8;
1270     tbb[8].idCommand = ID_SELECTION_SELECTPARTIALTALL;
1271     tbb[8].fsState = TBSTATE_ENABLED;
1272     tbb[8].fsStyle = TBSTYLE_BUTTON;
1273     tbb[8].dwData = 0;
1274     tbb[8].iString = 0;
1275 
1276 
1277     tbb[9].iBitmap = 9;
1278     tbb[9].idCommand = ID_SELECTION_SELECTINSIDE;
1279     tbb[9].fsState = TBSTATE_ENABLED;
1280     tbb[9].fsStyle = TBSTYLE_BUTTON;
1281     tbb[9].dwData = 0;
1282     tbb[9].iString = 0;
1283 
1284     tbb[10].iBitmap = 10;
1285     tbb[10].idCommand = ID_SELECTION_CSGSUBTRACT;
1286     tbb[10].fsState = TBSTATE_ENABLED;
1287     tbb[10].fsStyle = TBSTYLE_BUTTON;
1288     tbb[10].dwData = 0;
1289     tbb[10].iString = 0;
1290 
1291 
1292     tbb[11].iBitmap = 11;
1293     tbb[11].idCommand = ID_SELECTION_MAKEHOLLOW;
1294     tbb[11].fsState = TBSTATE_ENABLED;
1295     tbb[11].fsStyle = TBSTYLE_BUTTON;
1296     tbb[11].dwData = 0;
1297     tbb[11].iString = 0;
1298 
1299     tbb[12].iBitmap = 12;
1300     tbb[12].idCommand = ID_TEXTURES_WIREFRAME;
1301     tbb[12].fsState = TBSTATE_ENABLED;
1302     tbb[12].fsStyle = TBSTYLE_BUTTON;
1303     tbb[12].dwData = 0;
1304     tbb[12].iString = 0;
1305 
1306     tbb[13].iBitmap = 13;
1307     tbb[13].idCommand = ID_TEXTURES_FLATSHADE;
1308     tbb[13].fsState = TBSTATE_ENABLED;
1309     tbb[13].fsStyle = TBSTYLE_BUTTON;
1310     tbb[13].dwData = 0;
1311     tbb[13].iString = 0;
1312 
1313     tbb[14].iBitmap = 14;
1314     tbb[14].idCommand = ID_VIEW_TRILINEAR;
1315     tbb[14].fsState = TBSTATE_ENABLED;
1316     tbb[14].fsStyle = TBSTYLE_BUTTON;
1317     tbb[14].dwData = 0;
1318     tbb[14].iString = 0;
1319 
1320     SendMessage(hwndTB, TB_ADDBUTTONS, (WPARAM)NUMBUTTONS,
1321         (LPARAM) (LPTBBUTTON) &tbb);
1322 
1323     ShowWindow(hwndTB, SW_SHOW);
1324 
1325     return hwndTB;
1326 }
1327 
1328