1 #include "EgOSUtils.h"
2 
3 #include "CEgFileSpec.h"
4 #include "CEgErr.h"
5 #include "UtilStr.h"
6 
7 #include <stdlib.h>
8 #include <time.h>
9 #include <math.h>
10 
11 #ifdef EG_MAC
12 #include <Resources.h>
13 #include <Sound.h>
14 #include <Fonts.h>
15 #endif
16 
17 
18 #ifdef EG_WIN
19 #include <windows.h>
20 #endif
21 
22 #ifdef UNIX_X
23 #include <stdio.h>
24 #include <sys/stat.h>
25 #include <sys/time.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <dirent.h>
29 #endif
30 
31 
32 int				EgOSUtils::sXdpi				= 72;
33 int				EgOSUtils::sYdpi				= 72;
34 long			EgOSUtils::sLastCursor			= -1;
35 long			EgOSUtils::sLastCursorChange 	= -1;
36 CEgFileSpec 	EgOSUtils::sAppSpec;
37 char			EgOSUtils::sInitialDir[ INITAL_DIR_STRLEN + 2 ];
38 XStrList		EgOSUtils::sFontList( cDuplicatesAllowed );
39 
40 
41 
42 
ShowFileErr(const UtilStr * inName,char * inErrMsg,bool wasReading)43 void EgOSUtils::ShowFileErr( const UtilStr* inName, char* inErrMsg, bool wasReading ) {
44 	UtilStr	s;
45 
46 	if ( wasReading )
47 		s.Assign( "Error reading : " );
48 	else
49 		s.Assign( "Error writing : " );
50 	s.Append( inErrMsg );
51 
52 	#ifdef EG_MAC
53 	s.Insert( 14, "��" );
54 	#else
55 	s.Insert( 14, "\"\"" );
56 	#endif
57 
58 	s.Insert( 15, inName );
59 	ShowMsg( s );
60 }
61 
62 
ShowFileErr(const UtilStr * inName,CEgErr & inErr,bool wasReading)63 void EgOSUtils::ShowFileErr( const UtilStr* inName, CEgErr& inErr, bool wasReading ) {
64 	UtilStr	msg;
65 
66 	inErr.GetErrStr( msg );
67 	ShowFileErr( inName, msg.getCStr(), wasReading );
68 }
69 
70 
71 
ShowFileErr(const CEgFileSpec & inFileSpec,CEgErr & inErr,bool wasReading)72 void EgOSUtils::ShowFileErr( const CEgFileSpec& inFileSpec, CEgErr& inErr, bool wasReading ) {
73 	UtilStr	msg, fileName;
74 
75 	inFileSpec.GetFileName( fileName  );
76 	inErr.GetErrStr( msg );
77 	ShowFileErr( &fileName, msg.getCStr(), wasReading );
78 }
79 
80 
81 
82 
83 
Initialize(void * inModuleInstance)84 void EgOSUtils::Initialize( void* inModuleInstance ) {
85 
86 	srand( clock() );
87 
88 	#if EG_MAC
89 
90 	#pragma unused( inModuleInstance )
91 	OSStatus	status;
92 	FCBPBRec	fcbPBRec;
93 	Str255		appName;
94 	FSSpec		spec;
95 
96 	fcbPBRec.ioCompletion	= nil;
97 	fcbPBRec.ioFCBIndx		= 0;
98 	fcbPBRec.ioVRefNum		= 0;
99 	fcbPBRec.ioRefNum		= ::CurResFile();
100 	fcbPBRec.ioNamePtr		= appName;
101 
102 	status = ::PBGetFCBInfoSync(&fcbPBRec);
103 
104 	::FSMakeFSSpec(fcbPBRec.ioFCBVRefNum, fcbPBRec.ioFCBParID, appName, &spec );
105 	sAppSpec.Assign( &spec, 0 );
106 	#endif
107 
108 	#ifdef EG_WIN
109 	HDC	hDC = ::CreateDC( "DISPLAY", 0, 0, 0 );
110 	if ( hDC ) {
111 		sXdpi = ::GetDeviceCaps( hDC, LOGPIXELSX );
112 		sYdpi = ::GetDeviceCaps( hDC, LOGPIXELSY );
113 		::DeleteDC( hDC );
114 	}
115 
116 	char path[ 700 ];
117 	long len = ::GetModuleFileName( (HINSTANCE) inModuleInstance, path, 699 );
118 	if ( len ) {
119 		UtilStr fdir( path, len );
120 		fdir.Keep( fdir.FindLastInstanceOf( '\\' ) );
121 		sAppSpec.Assign( fdir.getCStr(), 0 );
122 	}
123 
124 
125 	// Init timer accuracy...
126 	///::timeBeginPeriod( 1 );
127 
128 	// Remember the initial dir
129 	::GetCurrentDirectory( INITAL_DIR_STRLEN, sInitialDir );
130 	#endif
131 
132 	// For mac, sXspi and sYdpi are already correct by default
133 	#ifdef UNIX_X
134 
135 	unsigned char pal[256*3];
136 	for (int pp = 0; pp < 256 ; pp++) {
137 	  pal[pp*3] = pp;
138 	  pal[pp*3+1] = pp;
139 	  pal[pp*3+2] = pp;
140 	}
141 
142         sXdpi = sYdpi = 75;
143 	#endif
144 }
145 
146 
147 
148 
149 
Shutdown()150 void EgOSUtils::Shutdown() {
151 	#ifdef UNIX_X
152 //        xpce_CloseGraph();
153  	#endif
154 	#if EG_WIN
155 
156 	// Restore the initial dir
157 	::SetCurrentDirectory( sInitialDir );
158 
159 	// Init timer accuracy...
160 	//::timeEndPeriod( 1 );
161 
162 	#endif
163 
164 }
165 
166 
167 
168 
169 
170 
171 
AskSaveAs(const char * inPrompt,const char * inDefaultName,CEgFileSpec & outSpec,long inFileType)172 bool EgOSUtils::AskSaveAs( const char* inPrompt, const char* inDefaultName, CEgFileSpec& outSpec, long inFileType ) {
173 	UtilStr inName( inDefaultName );
174 
175 	return AskSaveAs( inPrompt, inName, outSpec, inFileType );
176 }
177 
178 
179 #ifdef EG_ZINC
180 #include <z_fildlg.hpp>
181 #endif
182 
183 
184 
185 
AskSaveAs(const char * inPrompt,const UtilStr & inDefaultName,CEgFileSpec & outSpec,long inFileType)186 bool EgOSUtils::AskSaveAs( const char* inPrompt, const UtilStr& inDefaultName, CEgFileSpec& outSpec, long inFileType ) {
187 	int	doSave = false;
188 	UtilStr prompt( inPrompt );
189 
190 	#ifdef EG_MAC
191 	StandardFileReply	reply;
192 
193 	//::UDesktop::Deactivate();
194 	::StandardPutFile( prompt.getPasStr(), inDefaultName.getPasStr(), &reply );
195 	//::UDesktop::Activate();
196 
197 	if (reply.sfGood) {
198 		outSpec.Assign( &reply.sfFile, inFileType );
199 		doSave = true;
200 	}
201 	#endif
202 
203 	#if EG_WIN && EG_ZINC
204 	UtilStr defName( inDefaultName );
205 
206 	ZafFileDialog	fileDialog( 20, 5, 60, 14 );
207 
208 	if ( inFileType )
209 		CEgFileSpec::TypeToExt( defName, inFileType );
210 
211 	fileDialog.SetFile( defName.getCStr()  );
212 
213 	if ( fileDialog.GetFile( ZAF_FILE_DIALOG_SAVEAS ) == S_DLG_OK ) {
214 		doSave = true;
215 		outSpec.Assign( fileDialog.File(), inFileType );
216 	}
217 	/*
218 	unsigned char	c;
219 	UtilStr		winFilter;
220 	OPENFILENAME 	paramBlk;
221 	char			pathName[ 601 ];
222 
223 	inDefaultName.copyTo( pathName, 600 );
224 
225 	// See page 519 of Vol 5 in Win32 Ref for descrip of the lpstrFilter scheme.
226 	winFilter.Append( "/0*" );
227 
228 	// Append the ext mask...
229 	for ( int d = 0; d <= 24; d += 8 ) {			// Go thru each byte in ID num
230 		c = ((inFileType << d) >> 24 );
231 		winFilter.Append( (char) c );
232 	}
233 	winFilter.Append( (char) 0 );					// Windows exptects an extra NUL to end the filter
234 
235 	visual_mem_set( &paramBlk, 0, sizeof(OPENFILENAME) );
236 	paramBlk.lStructSize = sizeof(OPENFILENAME);
237 	paramBlk.lpstrFilter		= winFilter.getCStr();
238 	paramBlk.lpstrFile			= pathName;
239 	paramBlk.nMaxFile			= 600;
240 	paramBlk.lpstrTitle			= prompt.getCStr();
241 	if ( ::GetSaveFileName( &paramBlk ) ) {
242 		outSpec.Assign( pathName );
243 		doSave = true;
244 	}*/
245 	#endif
246 
247 	return doSave;
248 }
249 
250 
251 
252 
AskOpen(const char * inPrompt,CEgFileSpec & outSpec,long inTypeMask)253 bool EgOSUtils::AskOpen( const char* inPrompt, CEgFileSpec& outSpec, long inTypeMask ) {
254 	bool didOpen = false;
255 	UtilStr prompt( inPrompt );
256 
257 	#ifdef EG_MAC
258 	StandardFileReply	macFileReply;
259 	SFTypeList			typeList;
260 
261 	// clear the rec
262 	for ( int i = 0; i < sizeof( macFileReply ); i++ )
263 		( (char*) &macFileReply )[ i ] = 0;
264 
265 	//UDesktop::Deactivate();
266 	typeList[0] = inTypeMask;
267 	::StandardGetFile( 0, inTypeMask ? 1 : 0, typeList, &macFileReply );
268 	//UDesktop::Activate();
269 
270 	if ( macFileReply.sfGood ) {
271 		outSpec.Assign( &macFileReply.sfFile );
272 		didOpen = true;
273 	}
274 	#endif
275 
276 	#if EG_WIN && EG_ZINC
277 	ZafFileDialog	fileDialog( 5, 5, 60, 14 );
278 	UtilStr		str( "*" );
279 
280 	if ( inTypeMask ) {
281 		CEgFileSpec::TypeToExt( str, inTypeMask );
282 		fileDialog.SetFilter( str.getCStr() );
283 	}
284 
285 	if ( fileDialog.GetFile( ZAF_FILE_DIALOG_OPEN ) == S_DLG_OK ) {
286 		char path[ 401 ];
287 		didOpen = true;
288 
289 		fileDialog.FullPath( path, 400 );
290 		outSpec.Assign( path );
291 	}
292 	/*
293 	unsigned char	c;
294 	UtilStr		winFilter;
295 	OPENFILENAME 	paramBlk;
296 	char			pathName[ 601 ];
297 
298 	// See page 519 of Vol 5 in Win32 Ref for descrip of the lpstrFilter scheme.
299 	winFilter.Append( "/0*" );
300 
301 	// Append the ext mask...
302 	for ( int d = 0; d <= 24; d += 8 ) {			// Go thru each byte in ID num
303 		c = ((inTypeMask << d) >> 24 );
304 		winFilter.Append( (char) c );
305 	}
306 	winFilter.Append( (char) 0 );					// Windows exptects an extra NUL to end the filter
307 
308 	visual_mem_set( &paramBlk, 0, sizeof(OPENFILENAME) );
309 	paramBlk.lStructSize = sizeof(OPENFILENAME);
310 	paramBlk.lpstrFilter		= winFilter.getCStr();
311 	paramBlk.lpstrFile			= pathName;
312 	paramBlk.nMaxFile			= 600;
313 	paramBlk.lpstrTitle			= prompt.getCStr();
314 	if ( ::GetOpenFileName( &paramBlk ) ) {
315 		outSpec.Assign( pathName );
316 		didOpen = true;
317 	}*/
318 	#endif
319 
320 	return didOpen;
321 }
322 
323 
324 
325 
326 
327 
328 
329 
AreYouSure(const UtilStr & inMsg)330 bool EgOSUtils::AreYouSure( const UtilStr& inMsg ) {
331 	int ans;
332 
333 	#ifdef EG_MAC
334 	::ParamText( inMsg.getPasStr(), "\p", "\p", "\p");
335 	//UDesktop::Deactivate();
336 	ans = ::CautionAlert( 2000, 0 );
337 	//UDesktop::Activate();
338 
339 	return ans == 1; //answer_Save;
340 	#endif
341 
342 	#ifdef EG_WIN
343 	ans = ::MessageBox( 0, inMsg.getCStr(), "Examgen Message", MB_ICONEXCLAMATION | MB_YESNO | MB_SETFOREGROUND | MB_TASKMODAL );
344 	return ans == IDYES;
345 	#endif
346 }
347 
348 
AreYouSure(const char * inMsg)349 bool EgOSUtils::AreYouSure( const char* inMsg ) {
350 	UtilStr	msg( inMsg );
351 
352 	return AreYouSure( msg );
353 }
354 
355 
356 
AskSaveChanges(const char * inName)357 int EgOSUtils::AskSaveChanges( const char* inName ) {
358 	UtilStr name( inName );
359 	return AskSaveChanges( name );
360 }
361 
362 
363 
AskSaveChanges(const UtilStr & inName)364 int EgOSUtils::AskSaveChanges( const UtilStr& inName ) {
365 	int ans;
366 
367 	#ifdef EG_MAC
368 	::ParamText( inName.getPasStr(), "\p", "\p", "\p" );
369 	//UDesktop::Deactivate();
370 	ans = ::CautionAlert( 2001, 0 );
371 	//UDesktop::Activate();
372 
373 	return 2 - ans;
374 	#endif
375 
376 	#ifdef EG_WIN
377 	UtilStr	msg( "Save changes to \"" );
378 	msg.Append( inName );
379 	msg.Append( "\" before closing?" );
380 	ans = ::MessageBox( 0, msg.getCStr(), "Examgen Message", MB_ICONEXCLAMATION | MB_YESNOCANCEL | MB_SETFOREGROUND | MB_TASKMODAL );
381 	if ( ans == IDYES )
382 		return 1;
383 	else if ( ans == IDNO )
384 		return -1;
385 	else
386 		return 0;
387 	#endif
388 }
389 
390 
SpinCursor()391 void EgOSUtils::SpinCursor() {
392 	long time = clock();
393 
394 	if ( sLastCursorChange == -1 )
395 		sLastCursorChange = time;
396 	else if ( time - CLOCKS_PER_SEC / 3 > sLastCursorChange ) {					// Every 1/3 second...
397 		#ifdef EG_MAC
398 		Handle cursHndl;
399 		sLastCursor			= ( sLastCursor + 1 ) % 8;							// 8 Cursors
400 		cursHndl			= ::GetResource( 'CURS', 6500 + sLastCursor );		// 6500 = Base ID
401 		sLastCursorChange	= time;
402 		if ( cursHndl )
403 			::SetCursor( (Cursor*) *cursHndl );
404 		#endif
405 
406 		#ifdef EG_WIN
407 		SetCursor( ::LoadCursor( 0, IDC_WAIT ) );
408 		sLastCursor = 1;
409 		#endif
410 	}
411 }
412 
413 
414 
415 
416 
417 
418 
419 
ShowCursor()420 void EgOSUtils::ShowCursor() {
421 
422 	#ifdef EG_MAC
423 	::ShowCursor();
424 	::InitCursor();
425 	#endif
426 
427 	#ifdef EG_WIN
428 	::SetCursor( ::LoadCursor( 0, IDC_ARROW ) );
429 	while ( ::ShowCursor( true ) < 0 ) { }
430 	#endif
431 
432 	sLastCursor			= -1;
433 	sLastCursorChange	= -1;
434 }
435 
436 
HideCursor()437 void EgOSUtils::HideCursor() {
438 
439 	#ifdef EG_MAC
440 	::HideCursor();
441 	#endif
442 
443 	#ifdef EG_WIN
444 	while ( ::ShowCursor( false ) >= 0 ) { }
445 	#endif
446 
447 	sLastCursor			= -1;
448 	sLastCursorChange	= -1;
449 }
450 
451 
452 
GetNextFile(const CEgFileSpec & folderSpec,CEgFileSpec & outSpec,bool inStartOver,bool inFolders)453 bool EgOSUtils::GetNextFile( const CEgFileSpec& folderSpec, CEgFileSpec& outSpec, bool inStartOver, bool inFolders ) {
454 	bool ok;
455 
456 	#ifdef EG_MAC
457 	static int			sLastIndex;
458 	OSErr				err;
459 	HFileInfo			pb;
460 	FSSpec				spec;
461 	long				parID;
462 	Str255				str;
463 
464 	parID			= ( (FSSpec*) folderSpec.OSSpec() ) -> parID;
465 	pb.ioVRefNum	= ( (FSSpec*) folderSpec.OSSpec() ) -> vRefNum;
466 	pb.ioNamePtr 	= str;
467 
468 	if ( inStartOver )
469 		pb.ioFDirIndex = 1;
470 	else
471 		pb.ioFDirIndex = sLastIndex;
472 
473 	ok = false;
474 	do {
475 		pb.ioDirID 	= parID;
476 		err = PBGetCatInfoSync( (CInfoPBRec*) &pb );
477 
478 		if ( err == noErr && ( (pb.ioFlFndrInfo.fdFlags & fInvisible) == 0)  /*&& pb.ioFlFndrInfo.fdCreator == cEGCreator*/ ) {
479 			ok = ( (pb.ioFlAttrib & ioDirMask ) == 0 );
480 			if ( inFolders )
481 				ok = ! ok;
482 			if ( ok ) {
483 				if ( inFolders )
484 					pb.ioFlParID = pb.ioDirID;
485 				::FSMakeFSSpec( pb.ioVRefNum, pb.ioFlParID, str, &spec );
486 				outSpec.Assign( &spec, pb.ioFlFndrInfo.fdType );
487 			}
488 		}
489 
490 		pb.ioFDirIndex++;
491 		sLastIndex = pb.ioFDirIndex;
492 	} while ( err == noErr && ! ok );
493 
494 	#endif
495 
496 
497 
498 	#ifdef EG_WIN
499 	WIN32_FIND_DATA		fileData;
500 	static HANDLE		hSearch;
501 	UtilStr				name;
502 	bool				isDir, tryAgain;
503 
504 	do {
505 		if ( inStartOver ) {
506 			inStartOver = false;
507 			if ( name.getChar( name.length() ) == '\\' )
508 				name.Trunc( 1 );
509 			ok = SetCurrentDirectory( name.getCStr() );
510 			if ( ok ) {
511 				hSearch = ::FindFirstFile( "*.*", &fileData );
512 				ok = hSearch != INVALID_HANDLE_VALUE;
513 			} }
514 		else
515 			ok = ::FindNextFile( hSearch, &fileData );
516 		if ( ok ) {
517 			name.Assign( fileData.cFileName );
518 			isDir = ::GetFileAttributes( fileData.cFileName ) & FILE_ATTRIBUTE_DIRECTORY;
519 			if ( isDir == inFolders ) {
520 				tryAgain = name.compareTo( "." ) == 0 || name.compareTo( ".." ) == 0;
521 				outSpec.Assign( folderSpec );
522 				if ( isDir )
523 					name.Append( "\\" );
524 				outSpec.Rename( name ); }
525 			else
526 				tryAgain = true;
527 		}
528 	} while ( ok && tryAgain );
529 
530 	#endif
531 
532 	#ifdef UNIX_X
533 
534 	UtilStr				name;
535 	bool				isDir, tryAgain;
536 	UtilStr                         fullname;
537 
538 	static DIR *d = 0;
539 	struct dirent *de;
540 
541 	ok = true;
542 	do {
543 	  if ( inStartOver ) {
544 	    if (d != 0) {
545 	      closedir(d);
546 	      d = 0;
547 	    }
548 	    inStartOver = false;
549 	    name.Assign( (char*) folderSpec.OSSpec() );
550 	    if ( name.getChar( name.length() ) == '/' )
551 	      name.Trunc( 1 );
552 	    d = opendir(name.getCStr());
553 	    if (d == 0) return 0;
554 	  }
555 	  de = readdir(d);
556 	  if (de == 0) return 0;
557 	  name.Assign(de->d_name);
558 	  struct stat statdata;
559 	  fullname.Assign( (char*) folderSpec.OSSpec() );
560 	  if ( fullname.getChar( name.length() ) != '/' )
561 	      fullname.Append( '/' );
562 	  fullname.Append(de->d_name);
563 	  if (stat(fullname.getCStr(), &statdata) != 0)
564 	    return 0;
565 	  if (S_ISDIR(statdata.st_mode))
566 	    isDir = 1;
567 	  else
568 	    isDir = 0;
569 
570 	  if ( isDir == inFolders ) {
571 
572 	    tryAgain = name.compareTo( "." ) == 0 || name.compareTo( ".." ) == 0;
573 	    outSpec.Assign( folderSpec );
574 	    if ( isDir )
575 	      name.Append( "\\" );
576 	    outSpec.Rename( name ); }
577 	  else
578 	    tryAgain = true;
579 	} while ( ok && tryAgain );
580 
581 	#endif
582 
583 	return ok;
584 }
585 
586 
587 
588 
589 
590 
591 
592 
593 
594 
Beep()595 void EgOSUtils::Beep() {
596 
597 	#ifdef EG_MAC
598 	::SysBeep( 200 );
599 	#endif
600 
601 	#ifdef EG_WIN
602 	MessageBeep(0);
603 	#endif
604 }
605 
606 
607 #ifdef UNIX_X
608 
609 	#include <sys/times.h>
610 #endif
CurTimeMS()611 long EgOSUtils::CurTimeMS() {
612 	#if EG_WIN
613 	return ::timeGetTime();
614 	#elif EG_MAC
615 	return ::TickCount() * 16;
616         #else
617 	struct timeval tv;
618 	struct timezone tz;
619 	tz.tz_minuteswest = 0;
620 	tz.tz_dsttime = 0;
621 	gettimeofday(&tv, &tz);
622 	return ((tv.tv_sec * 1000) & 0x7fffffff) + tv.tv_usec / 1000;
623         #endif
624 }
625 
626 
GetMouse(Point & outPt)627 void EgOSUtils::GetMouse( Point& outPt ) {
628 
629 	#if EG_MAC
630 	::GetMouse( &outPt );
631 	::LocalToGlobal( &outPt );
632 	#endif
633 
634 	#if EG_WIN
635 	POINT p;
636 	::GetCursorPos( &p );
637 	outPt.h = p.x;
638 	outPt.v = p.y;
639 	#endif
640 
641 	#ifdef UNIX_X
642 	int x, y;
643 
644 //	xpce_QueryMouse(&x, &y); // FIXME replace this
645 	x = 0;
646 	y = 0;
647 	outPt.h = x;
648 	outPt.v = y;
649 	#endif
650 }
651 
652 
ShowMsg(const UtilStr & inMsg)653 void EgOSUtils::ShowMsg( const UtilStr& inMsg ) {
654 
655 	#ifdef EG_MAC
656 	//UDesktop::Deactivate();
657 	::ParamText( inMsg.getPasStr(), "\p", "\p", "\p");
658 	::StopAlert( 2002, 0 );
659 	//#pragma rem back in!
660 	//UDesktop::Activate();
661 	#endif
662 
663 	#ifdef WIN32
664 	::MessageBox( 0, inMsg.getCStr(), "Examgen Message", MB_ICONEXCLAMATION | MB_OK | MB_SETFOREGROUND | MB_APPLMODAL );
665 	//ZafMessageWindow* w = new ZafMessageWindow( "Message", ZAF_EXCLAMATION_ICON, ZAF_DIALOG_OK, ZAF_DIALOG_OK, inMsg.getCStr() );
666 	//zafWindowManager -> Add( w );
667 	//w -> Control();
668 	#endif
669 
670 }
671 
672 
673 
ShowMsg(const char * inMsg)674 void EgOSUtils::ShowMsg( const char* inMsg ) {
675 	UtilStr msg( inMsg );
676 
677 	ShowMsg( msg );
678 }
679 
680 
681 
Rnd(long min,long max)682 long EgOSUtils::Rnd( long min, long max ) {
683 	long maxRnd 	= RAND_MAX;
684 	long retNum 	= rand() * ( max - min + 1 ) / maxRnd + min;
685 
686 	if ( retNum >= max )
687 		return max;
688 	else
689 		return retNum;
690 }
691 
692 
693 
694 
RevBytes(unsigned long inNum)695 unsigned long EgOSUtils::RevBytes( unsigned long inNum ) {
696 
697 
698 	return ( inNum << 24 ) | ( ( inNum & 0xFF00 ) << 8 ) | ( ( inNum & 0xFF0000 ) >> 8 ) | ( inNum >> 24 );
699 }
700 
701 
702 
703 #define __SET_RGB( R, G, B ) 	\
704 	if ( R < 0 )				\
705 		outRGB.red = 0;			\
706 	else if ( R <= 0xFFFF )		\
707 		outRGB.red = R;			\
708 	else						\
709 		outRGB.red = 0xFFFF;	\
710 	if ( G < 0 )				\
711 		outRGB.green = 0;		\
712 	else if ( G <= 0xFFFF )		\
713 		outRGB.green = G;		\
714 	else						\
715 		outRGB.green = 0xFFFF;	\
716 	if ( B < 0 )				\
717 		outRGB.blue = 0;		\
718 	else if ( B <= 0xFFFF )		\
719 		outRGB.blue = B;		\
720 	else						\
721 		outRGB.blue = 0xFFFF;	\
722 	break;
723 
724 
725 
726 
727 
HSV2RGB(float H,float S,float V,RGBColor & outRGB)728 void EgOSUtils::HSV2RGB( float H, float S, float V, RGBColor& outRGB ) {
729 
730 
731 	// H is given on [0, 1] or WRAPPED. S and V are given on [0, 1].
732 	// RGB are each returned on [0, 1].
733 	long hexQuadrant, m, n, v;
734 	H = ( H - floor( H ) ) * 6;  // Wrap the Hue angle around 1.0, then find quadrant
735 
736 	hexQuadrant = H;
737 	float f = H - hexQuadrant;
738 
739 	// Check sat bounds
740 	if ( S < 0 )
741 		S = 0;
742 	if ( S > 1 )
743 		S = 1;
744 
745 	// Check val bounds
746 	if ( V < 0 )
747 		V = 0;
748 	if ( V > 1 )
749 		V = 1;
750 
751 	if ( ! ( hexQuadrant & 1 ) )
752 		f = 1 - f; // hexQuadrant i is even
753 
754 	V *= 65535.0;
755 	v = V;
756 	m = V * (1 - S);
757 	n = V * (1 - S * f);
758 
759 	switch ( hexQuadrant ) {
760 		case 1: __SET_RGB( n, v, m );
761 		case 2: __SET_RGB( m, v, n );
762 		case 3: __SET_RGB( m, n, v );
763 		case 4: __SET_RGB( n, m, v );
764 		case 5: __SET_RGB( v, m, n );
765 		default:
766 			__SET_RGB( v, n, m );
767 	}
768 }
769 
770 
771 
772 /*
773 #define RETURN_HSV(h, w, b) {HSV.H = h; HSV.S = s; HSV.V = v; return HSV;}
774 
775 #define RETURN_RGB(r, g, b) {RGB.R = r; RGB.G = g; RGB.B = b; return RGB;}
776 
777 #define UNDEFINED -1
778 
779 // Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms. Pure
780 
781 // red always maps to 6 in this implementation. Therefore UNDEFINED can be
782 
783 // defined as 0 in situations where only unsigned numbers are desired.
784 
785 typedef struct {float R, G, B;} RGBType;
786 
787 typedef struct {float H, S, V;} HSVType;
788 
789 HSVType
790 
791 RGB_to_HSV( RGBType RGB ) {
792 
793             // RGB are each on [0, 1]. S and V are returned on [0, 1] and H is
794             // returned on [0, 6]. Exception: H is returned UNDEFINED if S==0.
795             float R = RGB.R, G = RGB.G, B = RGB.B, v, x, f;
796             int i;
797             HSVType HSV;
798             x = min(R, G, B);
799             v = max(R, G, B);
800             if(v == x) RETURN_HSV(UNDEFINED, 0, v);
801             f = (R == x) ? G - B : ((G == x) ? B - R : R - G);
802             i = (R == x) ? 3 : ((G == x) ? 5 : 1);
803             RETURN_HSV(i - f /(v - x), (v - x)/v, v);
804 
805 
806 }
807 
808 
809 RGBType
810 
811 HSV_to_RGB( HSVType HSV ) {
812 
813            // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1].
814            // RGB are each returned on [0, 1].
815            float h = HSV.H, s = HSV.S, v = HSV.V, m, n, f;
816            int i;
817            RGBType RGB;
818            if(h == UNDEFINED) RETURN_RGB(v, v, v);
819            i = floor(h);
820            f = h - i;
821            if(!(i & 1)) f = 1 - f; // if i is even
822            m = v * (1 - s);
823            n = v * (1 - s * f);
824            switch (i) {
825                      case 6:
826                      case 0: RETURN_RGB(v, n, m);
827                      case 1: RETURN_RGB(n, v, m);
828                      case 2: RETURN_RGB(m, v, n)
829                      case 3: RETURN_RGB(m, n, v);
830                      case 4: RETURN_RGB(n, m, v);
831                      case 5: RETURN_RGB(v, m, n);
832            }
833 
834 
835 }
836 */
837 
838