Many updates from John Fay.
git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@31 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
parent
c00890a4b5
commit
5e1ec95e4c
@ -182,8 +182,8 @@ void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int
|
|||||||
fgStructure.Window->State.JoystickLastPoll =
|
fgStructure.Window->State.JoystickLastPoll =
|
||||||
fgElapsedTime() - fgStructure.Window->State.JoystickPollRate;
|
fgElapsedTime() - fgStructure.Window->State.JoystickPollRate;
|
||||||
|
|
||||||
if( fgStructure.Window->State.JoystickLastPoll < 0.0 )
|
if( fgStructure.Window->State.JoystickLastPoll < 0 )
|
||||||
fgStructure.Window->State.JoystickLastPoll = 0.0;
|
fgStructure.Window->State.JoystickLastPoll = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -218,6 +218,19 @@ void FGAPIENTRY glutEntryFunc( void (* callback)( int ) )
|
|||||||
SET_CALLBACK( Entry );
|
SET_CALLBACK( Entry );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window destruction callbacks
|
||||||
|
*/
|
||||||
|
void FGAPIENTRY glutCloseFunc( void (* callback)( void ) )
|
||||||
|
{
|
||||||
|
SET_CALLBACK( Destroy );
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) )
|
||||||
|
{
|
||||||
|
glutCloseFunc( callback );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deprecated version of glutMenuStatusFunc callback setting method
|
* Deprecated version of glutMenuStatusFunc callback setting method
|
||||||
*/
|
*/
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
*
|
*
|
||||||
* fgDisplayCursor() -- this waits for better times
|
* fgDisplayCursor() -- this waits for better times
|
||||||
* glutSetCursor() -- both X and Win32 mappings are incomplete
|
* glutSetCursor() -- both X and Win32 mappings are incomplete
|
||||||
* glutWarpPointer() -- check the Win32 version
|
|
||||||
*
|
*
|
||||||
* It would be good to use custom mouse cursor shapes, and introduce
|
* It would be good to use custom mouse cursor shapes, and introduce
|
||||||
* an option to display them using glBitmap() and/or texture mapping,
|
* an option to display them using glBitmap() and/or texture mapping,
|
||||||
@ -112,7 +111,14 @@ void FGAPIENTRY glutSetCursor( int cursorID )
|
|||||||
/*
|
/*
|
||||||
* This is a temporary solution only...
|
* This is a temporary solution only...
|
||||||
*/
|
*/
|
||||||
# define MAP_CURSOR(a,b) case a: SetCursor( LoadCursor( NULL, b ) ); break;
|
// Set the cursor AND change it for this window class.
|
||||||
|
# define MAP_CURSOR(a,b) case a: SetCursor( LoadCursor( NULL, b ) ); \
|
||||||
|
SetClassLong(fgStructure.Window->Window.Handle,GCL_HCURSOR,(LONG)LoadCursor(NULL,b)); \
|
||||||
|
break;
|
||||||
|
// Nuke the cursor AND change it for this window class.
|
||||||
|
# define ZAP_CURSOR(a,b) case a: SetCursor( NULL ); \
|
||||||
|
SetClassLong(fgStructure.Window->Window.Handle,GCL_HCURSOR,(LONG)NULL); \
|
||||||
|
break;
|
||||||
|
|
||||||
switch( cursorID )
|
switch( cursorID )
|
||||||
{
|
{
|
||||||
@ -126,10 +132,11 @@ void FGAPIENTRY glutSetCursor( int cursorID )
|
|||||||
MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
|
MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
|
||||||
MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW );
|
MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW );
|
||||||
MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
|
MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
|
||||||
MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO );
|
//MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO );
|
||||||
|
ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_UPARROW );
|
MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,8 +37,7 @@
|
|||||||
/*
|
/*
|
||||||
* TODO BEFORE THE STABLE RELEASE:
|
* TODO BEFORE THE STABLE RELEASE:
|
||||||
*
|
*
|
||||||
* glutStrokeCharacter() -- stroke fonts not implemented, uses a bitmap font instead
|
* Test things out ...
|
||||||
* glutStrokeWidth() -- stroke fonts not implemented, uses a bitmap font instead
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- IMPORT DECLARATIONS -------------------------------------------------- */
|
/* -- IMPORT DECLARATIONS -------------------------------------------------- */
|
||||||
@ -60,15 +59,15 @@ extern SFG_StrokeFont fgStrokeMonoRoman;
|
|||||||
* This is for GLUT binary compatibility, as suggested by Steve Baker
|
* This is for GLUT binary compatibility, as suggested by Steve Baker
|
||||||
*/
|
*/
|
||||||
#if TARGET_HOST_UNIX_X11
|
#if TARGET_HOST_UNIX_X11
|
||||||
void* glutStrokeRoman;
|
void* glutStrokeRoman;
|
||||||
void* glutStrokeMonoRoman;
|
void* glutStrokeMonoRoman;
|
||||||
void* glutBitmap9By15;
|
void* glutBitmap9By15;
|
||||||
void* glutBitmap8By13;
|
void* glutBitmap8By13;
|
||||||
void* glutBitmapTimesRoman10;
|
void* glutBitmapTimesRoman10;
|
||||||
void* glutBitmapTimesRoman24;
|
void* glutBitmapTimesRoman24;
|
||||||
void* glutBitmapHelvetica10;
|
void* glutBitmapHelvetica10;
|
||||||
void* glutBitmapHelvetica12;
|
void* glutBitmapHelvetica12;
|
||||||
void* glutBitmapHelvetica18;
|
void* glutBitmapHelvetica18;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -80,23 +79,23 @@ extern SFG_StrokeFont fgStrokeMonoRoman;
|
|||||||
*/
|
*/
|
||||||
static SFG_Font* fghFontByID( void* font )
|
static SFG_Font* fghFontByID( void* font )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Try matching the font ID and the font data structure
|
* Try matching the font ID and the font data structure
|
||||||
*/
|
*/
|
||||||
if( font == GLUT_BITMAP_8_BY_13 ) return( &fgFontFixed8x13 );
|
if( font == GLUT_BITMAP_8_BY_13 ) return( &fgFontFixed8x13 );
|
||||||
if( font == GLUT_BITMAP_9_BY_15 ) return( &fgFontFixed9x15 );
|
if( font == GLUT_BITMAP_9_BY_15 ) return( &fgFontFixed9x15 );
|
||||||
if( font == GLUT_BITMAP_HELVETICA_10 ) return( &fgFontHelvetica10 );
|
if( font == GLUT_BITMAP_HELVETICA_10 ) return( &fgFontHelvetica10 );
|
||||||
if( font == GLUT_BITMAP_HELVETICA_12 ) return( &fgFontHelvetica12 );
|
if( font == GLUT_BITMAP_HELVETICA_12 ) return( &fgFontHelvetica12 );
|
||||||
if( font == GLUT_BITMAP_HELVETICA_18 ) return( &fgFontHelvetica18 );
|
if( font == GLUT_BITMAP_HELVETICA_18 ) return( &fgFontHelvetica18 );
|
||||||
if( font == GLUT_BITMAP_TIMES_ROMAN_10 ) return( &fgFontTimesRoman10 );
|
if( font == GLUT_BITMAP_TIMES_ROMAN_10 ) return( &fgFontTimesRoman10 );
|
||||||
if( font == GLUT_BITMAP_TIMES_ROMAN_24 ) return( &fgFontTimesRoman24 );
|
if( font == GLUT_BITMAP_TIMES_ROMAN_24 ) return( &fgFontTimesRoman24 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This probably is the library user's fault
|
* This probably is the library user's fault
|
||||||
*/
|
*/
|
||||||
fgError( "font 0x%08x not found", font );
|
fgError( "font 0x%08x not found", font );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -105,18 +104,18 @@ static SFG_Font* fghFontByID( void* font )
|
|||||||
*/
|
*/
|
||||||
static SFG_StrokeFont* fghStrokeByID( void* font )
|
static SFG_StrokeFont* fghStrokeByID( void* font )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Try matching the font ID and the font data structure
|
* Try matching the font ID and the font data structure
|
||||||
*/
|
*/
|
||||||
if( font == GLUT_STROKE_ROMAN ) return( &fgStrokeRoman );
|
if( font == GLUT_STROKE_ROMAN ) return( &fgStrokeRoman );
|
||||||
if( font == GLUT_STROKE_MONO_ROMAN ) return( &fgStrokeMonoRoman );
|
if( font == GLUT_STROKE_MONO_ROMAN ) return( &fgStrokeMonoRoman );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This probably is the library user's fault
|
* This probably is the library user's fault
|
||||||
*/
|
*/
|
||||||
fgError( "stroke font 0x%08x not found", font );
|
fgError( "stroke font 0x%08x not found", font );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -127,60 +126,117 @@ static SFG_StrokeFont* fghStrokeByID( void* font )
|
|||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutBitmapCharacter( void* fontID, int character )
|
void FGAPIENTRY glutBitmapCharacter( void* fontID, int character )
|
||||||
{
|
{
|
||||||
const GLubyte* face;
|
const GLubyte* face;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First of all we'll need a font to use
|
* First of all we'll need a font to use
|
||||||
*/
|
*/
|
||||||
SFG_Font* font = fghFontByID( fontID );
|
SFG_Font* font = fghFontByID( fontID );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure the character we want to output is valid
|
* Make sure the character we want to output is valid
|
||||||
*/
|
*/
|
||||||
freeglut_return_if_fail( character >= 0 && character < 256 );
|
freeglut_return_if_fail( character >= 0 && character < 256 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Then find the character we want to draw
|
* Then find the character we want to draw
|
||||||
*/
|
*/
|
||||||
face = font->Characters[ character - 1 ];
|
face = font->Characters[ character - 1 ];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the old pixel store settings
|
* Save the old pixel store settings
|
||||||
*/
|
*/
|
||||||
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
|
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the pixel unpacking ways
|
* Set up the pixel unpacking ways
|
||||||
*/
|
*/
|
||||||
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
|
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
|
||||||
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
|
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
|
||||||
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
|
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
|
||||||
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
|
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
|
||||||
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
|
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
|
||||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We'll use a glBitmap call to draw the font.
|
* We'll use a glBitmap call to draw the font.
|
||||||
*/
|
*/
|
||||||
glBitmap(
|
glBitmap(
|
||||||
face[ 0 ], font->Height, /* The bitmap's width and height */
|
face[ 0 ], font->Height, /* The bitmap's width and height */
|
||||||
0, 0, /* The origin -- what the hell? */
|
font->xorig, font->yorig, /* The origin -- what on earth? */
|
||||||
face[ 0 ] + 1, 0, /* The raster advance -- inc. x */
|
(float)(face[ 0 ] + 1), 0.0, /* The raster advance -- inc. x */
|
||||||
(face + 1) /* The packed bitmap data... */
|
(face + 1) /* The packed bitmap data... */
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore the old pixel store settings
|
* Restore the old pixel store settings
|
||||||
*/
|
*/
|
||||||
glPopClientAttrib();
|
glPopClientAttrib();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAPIENTRY glutBitmapString( void* fontID, const char *string )
|
void FGAPIENTRY glutBitmapString( void* fontID, const char *string )
|
||||||
{
|
{
|
||||||
int i;
|
int c;
|
||||||
|
int numchar = strlen ( string ) ;
|
||||||
|
|
||||||
for( i=0; i<strlen( string ); i++ )
|
/*
|
||||||
glutBitmapCharacter( fontID, string[ i ] );
|
* First of all we'll need a font to use
|
||||||
|
*/
|
||||||
|
SFG_Font* font = fghFontByID( fontID );
|
||||||
|
|
||||||
|
float raster_position[4] ;
|
||||||
|
glGetFloatv ( GL_CURRENT_RASTER_POSITION, raster_position ) ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the old pixel store settings
|
||||||
|
*/
|
||||||
|
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the pixel unpacking ways
|
||||||
|
*/
|
||||||
|
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
|
||||||
|
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
|
||||||
|
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
|
||||||
|
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
|
||||||
|
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
|
||||||
|
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step through the string, drawing each character.
|
||||||
|
* A carriage return will simply translate the next character's insertion point back to the
|
||||||
|
* start of the line and down one line.
|
||||||
|
*/
|
||||||
|
for( c = 0; c < numchar; c++ )
|
||||||
|
{
|
||||||
|
if ( ( string[ c ] >= 0 ) && ( string[ c ] < 256 ) )
|
||||||
|
{
|
||||||
|
if ( string[c] == '\n' )
|
||||||
|
{
|
||||||
|
raster_position[1] -= (float)font->Height ;
|
||||||
|
glRasterPos4fv ( raster_position ) ;
|
||||||
|
}
|
||||||
|
else /* Not a carriage return, draw the bitmap character */
|
||||||
|
{
|
||||||
|
const GLubyte* face = font->Characters[ string[ c ] - 1 ] ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We'll use a glBitmap call to draw the font.
|
||||||
|
*/
|
||||||
|
glBitmap(
|
||||||
|
face[ 0 ], font->Height, /* The bitmap's width and height */
|
||||||
|
font->xorig, font->yorig, /* The origin -- what on earth? */
|
||||||
|
(float)(face[ 0 ] + 1), 0.0, /* The raster advance -- inc. x */
|
||||||
|
(face + 1) /* The packed bitmap data... */
|
||||||
|
) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore the old pixel store settings
|
||||||
|
*/
|
||||||
|
glPopClientAttrib();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -188,80 +244,20 @@ void FGAPIENTRY glutBitmapString( void* fontID, const char *string )
|
|||||||
*/
|
*/
|
||||||
int FGAPIENTRY glutBitmapWidth( void* fontID, int character )
|
int FGAPIENTRY glutBitmapWidth( void* fontID, int character )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* First of all, grab the font we need
|
* First of all, grab the font we need
|
||||||
*/
|
*/
|
||||||
SFG_Font* font = fghFontByID( fontID );
|
SFG_Font* font = fghFontByID( fontID );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure the character we want to output is valid
|
* Make sure the character we want to output is valid
|
||||||
*/
|
*/
|
||||||
freeglut_return_val_if_fail( character > 0 && character < 256, 0 );
|
freeglut_return_val_if_fail( character > 0 && character < 256, 0 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the font looking for the specified character
|
* Scan the font looking for the specified character
|
||||||
*/
|
*/
|
||||||
return( *(font->Characters[ character - 1 ]) + 1 );
|
return( *(font->Characters[ character - 1 ]) + 1 );
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Draw a stroke character
|
|
||||||
*/
|
|
||||||
void FGAPIENTRY glutStrokeCharacter( void* fontID, int character )
|
|
||||||
{
|
|
||||||
const SFG_StrokeChar *schar;
|
|
||||||
const SFG_StrokeStrip *strip;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First of all we'll need a font to use
|
|
||||||
*/
|
|
||||||
SFG_StrokeFont* font = fghStrokeByID( fontID );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the character we want to output is valid
|
|
||||||
*/
|
|
||||||
freeglut_return_if_fail( character >= 0 && character < font->Quantity );
|
|
||||||
|
|
||||||
schar = font->Characters[character];
|
|
||||||
|
|
||||||
freeglut_return_if_fail( schar );
|
|
||||||
|
|
||||||
strip = schar->Strips;
|
|
||||||
|
|
||||||
for (i = 0; i < schar->Number; i++, strip++)
|
|
||||||
{
|
|
||||||
glBegin(GL_LINE_STRIP);
|
|
||||||
for(j = 0; j < strip->Number; j++)
|
|
||||||
{
|
|
||||||
glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
glTranslatef(schar->Right, 0.0, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the width in pixels of a stroke character
|
|
||||||
*/
|
|
||||||
int FGAPIENTRY glutStrokeWidth( void* fontID, int character )
|
|
||||||
{
|
|
||||||
const SFG_StrokeChar *schar;
|
|
||||||
/*
|
|
||||||
* First of all we'll need a font to use
|
|
||||||
*/
|
|
||||||
SFG_StrokeFont* font = fghStrokeByID( fontID );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the character we want to output is valid
|
|
||||||
*/
|
|
||||||
freeglut_return_if_fail( character >= 0 && character < font->Quantity );
|
|
||||||
|
|
||||||
schar = font->Characters[character];
|
|
||||||
|
|
||||||
freeglut_return_if_fail( schar );
|
|
||||||
|
|
||||||
return (schar->Right);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -269,37 +265,37 @@ int FGAPIENTRY glutStrokeWidth( void* fontID, int character )
|
|||||||
*/
|
*/
|
||||||
int FGAPIENTRY glutBitmapLength( void* fontID, const char* string )
|
int FGAPIENTRY glutBitmapLength( void* fontID, const char* string )
|
||||||
{
|
{
|
||||||
int i, length = 0;
|
int c, length = 0, this_line_length = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Using glutBitmapWidth() function to calculate the result
|
* First of all, grab the font we need
|
||||||
*/
|
*/
|
||||||
for( i=0; i<strlen( string ); i++ )
|
SFG_Font* font = fghFontByID( fontID );
|
||||||
length += glutBitmapWidth( fontID, string[ i ] );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the result now
|
* Step through the characters in the string, adding up the width of each one
|
||||||
*/
|
*/
|
||||||
return( length );
|
int numchar = strlen ( string ) ;
|
||||||
}
|
for( c = 0; c < numchar; c++ )
|
||||||
|
{
|
||||||
|
if ( ( string[ c ] >= 0 ) && ( string[ c ] < 256 ) )
|
||||||
|
{
|
||||||
|
if ( string[ c ] == '\n' ) /* Carriage return, reset the length of this line */
|
||||||
|
{
|
||||||
|
if ( length < this_line_length ) length = this_line_length ;
|
||||||
|
this_line_length = 0 ;
|
||||||
|
}
|
||||||
|
else /* Not a carriage return, increment the length of this line */
|
||||||
|
this_line_length += *(font->Characters[ string[ c ] - 1 ]) + 1 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
if ( length < this_line_length ) length = this_line_length ;
|
||||||
* Return the width of a string drawn using a stroke font
|
|
||||||
*/
|
|
||||||
int FGAPIENTRY glutStrokeLength( void* fontID, const char* string )
|
|
||||||
{
|
|
||||||
int i, length = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Using glutStrokeWidth() function to calculate the result
|
* Return the result now
|
||||||
*/
|
*/
|
||||||
for( i=0; i<strlen( string ); i++ )
|
return( length );
|
||||||
length += glutStrokeWidth( fontID, string[ i ] );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the result now
|
|
||||||
*/
|
|
||||||
return( length );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -307,15 +303,168 @@ int FGAPIENTRY glutStrokeLength( void* fontID, const char* string )
|
|||||||
*/
|
*/
|
||||||
int FGAPIENTRY glutBitmapHeight( void* fontID )
|
int FGAPIENTRY glutBitmapHeight( void* fontID )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* See which font are we queried about
|
* See which font are we queried about
|
||||||
*/
|
*/
|
||||||
SFG_Font* font = fghFontByID( fontID );
|
SFG_Font* font = fghFontByID( fontID );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the character set's height
|
* Return the character set's height
|
||||||
*/
|
*/
|
||||||
return( font->Height );
|
return( font->Height );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw a stroke character
|
||||||
|
*/
|
||||||
|
void FGAPIENTRY glutStrokeCharacter( void* fontID, int character )
|
||||||
|
{
|
||||||
|
const SFG_StrokeChar *schar;
|
||||||
|
const SFG_StrokeStrip *strip;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First of all we'll need a font to use
|
||||||
|
*/
|
||||||
|
SFG_StrokeFont* font = fghStrokeByID( fontID );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the character we want to output is valid
|
||||||
|
*/
|
||||||
|
freeglut_return_if_fail( character >= 0 && character < font->Quantity );
|
||||||
|
|
||||||
|
schar = font->Characters[character];
|
||||||
|
|
||||||
|
freeglut_return_if_fail( schar );
|
||||||
|
|
||||||
|
strip = schar->Strips;
|
||||||
|
|
||||||
|
for (i = 0; i < schar->Number; i++, strip++)
|
||||||
|
{
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
for(j = 0; j < strip->Number; j++)
|
||||||
|
{
|
||||||
|
glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
glTranslatef(schar->Right, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGAPIENTRY glutStrokeString( void* fontID, const char *string )
|
||||||
|
{
|
||||||
|
int c, i, j;
|
||||||
|
int numchar = strlen ( string ) ;
|
||||||
|
float length = 0.0 ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First of all we'll need a font to use
|
||||||
|
*/
|
||||||
|
SFG_StrokeFont* font = fghStrokeByID( fontID );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step through the string, drawing each character.
|
||||||
|
* A carriage return will simply translate the next character's insertion point back to the
|
||||||
|
* start of the line and down one line.
|
||||||
|
*/
|
||||||
|
for( c = 0; c < numchar; c++ )
|
||||||
|
{
|
||||||
|
if ( ( string[ c ] >= 0 ) && ( string[ c ] < font->Quantity ) )
|
||||||
|
{
|
||||||
|
if ( string[c] == '\n' )
|
||||||
|
{
|
||||||
|
glTranslatef ( -length, -(float)(font->Height), 0.0 ) ;
|
||||||
|
length = 0.0 ;
|
||||||
|
}
|
||||||
|
else /* Not a carriage return, draw the bitmap character */
|
||||||
|
{
|
||||||
|
const SFG_StrokeChar *schar = font->Characters[string[c]];
|
||||||
|
if ( schar != NULL )
|
||||||
|
{
|
||||||
|
const SFG_StrokeStrip *strip = schar->Strips;
|
||||||
|
|
||||||
|
for (i = 0; i < schar->Number; i++, strip++)
|
||||||
|
{
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
for(j = 0; j < strip->Number; j++)
|
||||||
|
glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y);
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
length += schar->Right ;
|
||||||
|
glTranslatef(schar->Right, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the width in pixels of a stroke character
|
||||||
|
*/
|
||||||
|
int FGAPIENTRY glutStrokeWidth( void* fontID, int character )
|
||||||
|
{
|
||||||
|
const SFG_StrokeChar *schar;
|
||||||
|
/*
|
||||||
|
* First of all we'll need a font to use
|
||||||
|
*/
|
||||||
|
SFG_StrokeFont* font = fghStrokeByID( fontID );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the character we want to output is valid
|
||||||
|
*/
|
||||||
|
freeglut_return_val_if_fail( character >= 0 && character < font->Quantity, 0 );
|
||||||
|
|
||||||
|
schar = font->Characters[character];
|
||||||
|
|
||||||
|
freeglut_return_val_if_fail( schar, 0 );
|
||||||
|
|
||||||
|
return ((int)(schar->Right + 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the width of a string drawn using a stroke font
|
||||||
|
*/
|
||||||
|
int FGAPIENTRY glutStrokeLength( void* fontID, const char* string )
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
float length = 0.0;
|
||||||
|
float this_line_length = 0.0 ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First of all we'll need a font to use
|
||||||
|
*/
|
||||||
|
SFG_StrokeFont* font = fghStrokeByID( fontID );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step through the characters in the string, adding up the width of each one
|
||||||
|
*/
|
||||||
|
int numchar = strlen ( string ) ;
|
||||||
|
for( c = 0; c < numchar; c++ )
|
||||||
|
{
|
||||||
|
if ( ( string[ c ] >= 0 ) && ( string[ c ] < font->Quantity ) )
|
||||||
|
{
|
||||||
|
if ( string[ c ] == '\n' ) /* Carriage return, reset the length of this line */
|
||||||
|
{
|
||||||
|
if ( length < this_line_length ) length = this_line_length ;
|
||||||
|
this_line_length = 0.0 ;
|
||||||
|
}
|
||||||
|
else /* Not a carriage return, increment the length of this line */
|
||||||
|
{
|
||||||
|
const SFG_StrokeChar *schar = font->Characters[string[c]];
|
||||||
|
if ( schar != NULL )
|
||||||
|
this_line_length += schar->Right ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( length < this_line_length ) length = this_line_length ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the result now
|
||||||
|
*/
|
||||||
|
return( (int)(length+0.5) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
File diff suppressed because one or more lines are too long
@ -82,9 +82,9 @@ void fghRememberState( void )
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* hack to get around my stupid cross-gcc headers */
|
/* hack to get around my stupid cross-gcc headers */
|
||||||
#define ENUM_CURRENT_SETTINGS -1
|
#define FREEGLUT_ENUM_CURRENT_SETTINGS -1
|
||||||
|
|
||||||
EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &fgDisplay.DisplayMode );
|
EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS, &fgDisplay.DisplayMode );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure we will be restoring all settings needed
|
* Make sure we will be restoring all settings needed
|
||||||
@ -254,7 +254,7 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
|
|||||||
devMode.dmBitsPerPel, fgState.GameModeRefresh ) )
|
devMode.dmBitsPerPel, fgState.GameModeRefresh ) )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* OKi, we've found a matching display mode, remember it's number and break
|
* OKi, we've found a matching display mode, remember its number and break
|
||||||
*/
|
*/
|
||||||
mode = displayModes;
|
mode = displayModes;
|
||||||
break;
|
break;
|
||||||
@ -355,7 +355,7 @@ int FGAPIENTRY glutEnterGameMode( void )
|
|||||||
/*
|
/*
|
||||||
* ...if so, delete it before proceeding...
|
* ...if so, delete it before proceeding...
|
||||||
*/
|
*/
|
||||||
fgDestroyWindow( fgStructure.GameMode, TRUE );
|
fgAddToWindowDestroyList( fgStructure.GameMode, TRUE );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -370,7 +370,7 @@ int FGAPIENTRY glutEnterGameMode( void )
|
|||||||
*/
|
*/
|
||||||
if( fghChangeDisplayMode( FALSE ) == FALSE )
|
if( fghChangeDisplayMode( FALSE ) == FALSE )
|
||||||
{
|
{
|
||||||
fgWarning( "failed to change screen settings" );
|
fgWarning( "failed to change screen settings" );
|
||||||
return( FALSE );
|
return( FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,9 +434,9 @@ void FGAPIENTRY glutLeaveGameMode( void )
|
|||||||
freeglut_return_if_fail( fgStructure.GameMode != NULL );
|
freeglut_return_if_fail( fgStructure.GameMode != NULL );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First of all, have the game mode window created
|
* First of all, have the game mode window destroyed
|
||||||
*/
|
*/
|
||||||
fgDestroyWindow( fgStructure.GameMode, TRUE );
|
fgAddToWindowDestroyList( fgStructure.GameMode, TRUE );
|
||||||
|
|
||||||
#if TARGET_HOST_UNIX_X11
|
#if TARGET_HOST_UNIX_X11
|
||||||
|
|
||||||
|
@ -55,7 +55,14 @@ SFG_Display fgDisplay;
|
|||||||
/*
|
/*
|
||||||
* The settings for the current freeglut session
|
* The settings for the current freeglut session
|
||||||
*/
|
*/
|
||||||
SFG_State fgState;
|
SFG_State fgState = { { -1, -1, FALSE }, { 300, 300, TRUE }, GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH,
|
||||||
|
FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
|
||||||
|
#ifdef TARGET_HOST_WIN32
|
||||||
|
{ 0, FALSE },
|
||||||
|
#else
|
||||||
|
{ { 0, 0 }, FALSE },
|
||||||
|
#endif
|
||||||
|
{ NULL, NULL }, NULL, NULL, NULL, { 640, 480, TRUE }, 16, 72, GLUT_ACTION_EXIT, GLUT_EXEC_STATE_INIT } ;
|
||||||
|
|
||||||
|
|
||||||
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||||
@ -163,15 +170,13 @@ void fgInitialize( const char* displayName )
|
|||||||
*/
|
*/
|
||||||
if( atom == 0 )
|
if( atom == 0 )
|
||||||
{
|
{
|
||||||
GLboolean retval;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure the unitialized fields are reset to zero
|
* Make sure the unitialized fields are reset to zero
|
||||||
*/
|
*/
|
||||||
ZeroMemory( &wc, sizeof(WNDCLASS) );
|
ZeroMemory( &wc, sizeof(WNDCLASS) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each of the windows should have it's own device context...
|
* Each of the windows should have its own device context...
|
||||||
*/
|
*/
|
||||||
wc.style = CS_OWNDC;
|
wc.style = CS_OWNDC;
|
||||||
wc.lpfnWndProc = fgWindowProc;
|
wc.lpfnWndProc = fgWindowProc;
|
||||||
@ -187,8 +192,8 @@ void fgInitialize( const char* displayName )
|
|||||||
/*
|
/*
|
||||||
* Register the window class
|
* Register the window class
|
||||||
*/
|
*/
|
||||||
retval = RegisterClass( &wc );
|
atom = RegisterClass( &wc );
|
||||||
assert( retval != FALSE );
|
assert( atom != 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -250,8 +255,8 @@ void fgDeinitialize( void )
|
|||||||
*/
|
*/
|
||||||
while ( (timer = fgState.Timers.First) != NULL )
|
while ( (timer = fgState.Timers.First) != NULL )
|
||||||
{
|
{
|
||||||
fgListRemove(&fgState.Timers, &timer->Node);
|
fgListRemove ( &fgState.Timers, &timer->Node ) ;
|
||||||
free(timer);
|
free ( timer ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -259,6 +264,51 @@ void fgDeinitialize( void )
|
|||||||
*/
|
*/
|
||||||
fgJoystickClose();
|
fgJoystickClose();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the state structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
fgState.Position.X = -1 ;
|
||||||
|
fgState.Position.Y = -1 ;
|
||||||
|
fgState.Position.Use = FALSE ;
|
||||||
|
|
||||||
|
fgState.Size.X = 300 ;
|
||||||
|
fgState.Size.Y = 300 ;
|
||||||
|
fgState.Size.Use = TRUE ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default display mode to be used
|
||||||
|
*/
|
||||||
|
fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
|
||||||
|
|
||||||
|
fgState.ForceDirectContext = FALSE;
|
||||||
|
fgState.TryDirectContext = TRUE;
|
||||||
|
fgState.ForceIconic = FALSE;
|
||||||
|
fgState.GLDebugSwitch = FALSE;
|
||||||
|
fgState.XSyncSwitch = FALSE;
|
||||||
|
fgState.ActionOnWindowClose = GLUT_ACTION_EXIT ;
|
||||||
|
fgState.ExecState = GLUT_EXEC_STATE_INIT ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assume we want to ignore the automatic key repeat
|
||||||
|
*/
|
||||||
|
fgState.IgnoreKeyRepeat = TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the default game mode settings
|
||||||
|
*/
|
||||||
|
fgState.GameModeSize.X = 640;
|
||||||
|
fgState.GameModeSize.Y = 480;
|
||||||
|
fgState.GameModeDepth = 16;
|
||||||
|
fgState.GameModeRefresh = 72;
|
||||||
|
|
||||||
|
fgState.Time.Set = FALSE ;
|
||||||
|
|
||||||
|
fgState.Timers.First = fgState.Timers.Last = NULL ;
|
||||||
|
fgState.IdleCallback = NULL ;
|
||||||
|
fgState.MenuStateCallback = (FGCBmenuState)NULL ;
|
||||||
|
fgState.MenuStatusCallback = (FGCBmenuStatus)NULL ;
|
||||||
|
|
||||||
#if TARGET_HOST_UNIX_X11
|
#if TARGET_HOST_UNIX_X11
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -283,7 +333,6 @@ void fgDeinitialize( void )
|
|||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutInit( int* pargc, char** argv )
|
void FGAPIENTRY glutInit( int* pargc, char** argv )
|
||||||
{
|
{
|
||||||
char* geometrySettings = NULL;
|
|
||||||
char* displayName = NULL;
|
char* displayName = NULL;
|
||||||
int i, j, argc = *pargc;
|
int i, j, argc = *pargc;
|
||||||
|
|
||||||
@ -303,55 +352,12 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
|
|||||||
*/
|
*/
|
||||||
fgCreateStructure();
|
fgCreateStructure();
|
||||||
|
|
||||||
/*
|
|
||||||
* Fill in the default values that have not been passed in yet.
|
|
||||||
*/
|
|
||||||
if( fgState.Position.Use == FALSE )
|
|
||||||
{
|
|
||||||
fgState.Position.X = -1;
|
|
||||||
fgState.Position.Y = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( fgState.Size.Use == FALSE )
|
|
||||||
{
|
|
||||||
fgState.Size.X = 300;
|
|
||||||
fgState.Size.Y = 300;
|
|
||||||
fgState.Size.Use = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some more settings to come
|
|
||||||
*/
|
|
||||||
fgState.ForceDirectContext = FALSE;
|
|
||||||
fgState.TryDirectContext = TRUE;
|
|
||||||
fgState.ForceIconic = FALSE;
|
|
||||||
fgState.GLDebugSwitch = FALSE;
|
|
||||||
fgState.XSyncSwitch = FALSE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Assume we want to ignore the automatic key repeat
|
|
||||||
*/
|
|
||||||
fgState.IgnoreKeyRepeat = TRUE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The default display mode to be used
|
|
||||||
*/
|
|
||||||
fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the default game mode settings
|
|
||||||
*/
|
|
||||||
fgState.GameModeSize.X = 640;
|
|
||||||
fgState.GameModeSize.Y = 480;
|
|
||||||
fgState.GameModeDepth = 16;
|
|
||||||
fgState.GameModeRefresh = 72;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remember the function's call time
|
* Remember the function's call time
|
||||||
*/
|
*/
|
||||||
#ifndef WIN32
|
#if TARGET_HOST_UNIX_X11
|
||||||
gettimeofday(&fgState.Time.Value, NULL);
|
gettimeofday(&fgState.Time.Value, NULL);
|
||||||
#else
|
#elif TARGET_HOST_WIN32
|
||||||
fgState.Time.Value = timeGetTime();
|
fgState.Time.Value = timeGetTime();
|
||||||
#endif
|
#endif
|
||||||
fgState.Time.Set = TRUE;
|
fgState.Time.Set = TRUE;
|
||||||
@ -401,23 +407,51 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
|
|||||||
*/
|
*/
|
||||||
else if( strcmp( argv[ i ], "-geometry" ) == 0 )
|
else if( strcmp( argv[ i ], "-geometry" ) == 0 )
|
||||||
{
|
{
|
||||||
/*
|
int result, x, y;
|
||||||
* Again, check if there is at least one more argument
|
unsigned int w, h;
|
||||||
*/
|
|
||||||
if( ++i >= argc )
|
|
||||||
fgError( "-geometry parameter must be followed by window geometry settings" );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise make a duplicate of the geometry settings...
|
* Again, check if there is at least one more argument
|
||||||
*/
|
*/
|
||||||
geometrySettings = strdup( argv[ i ] );
|
if ( ++i >= argc )
|
||||||
|
fgError( "-geometry parameter must be followed by window geometry settings" );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Have both arguments removed
|
* Otherwise scan the geometry settings...
|
||||||
*/
|
*/
|
||||||
argv[ i - 1 ] = NULL;
|
result = sscanf ( argv[i], "%dx%d+%d+%d", &x, &y, &w, &h );
|
||||||
argv[ i ] = NULL;
|
|
||||||
(* pargc) -= 2;
|
/*
|
||||||
|
* Check what we have been supplied with...
|
||||||
|
*/
|
||||||
|
if ( result > 3 )
|
||||||
|
fgState.Size.Y = h ;
|
||||||
|
|
||||||
|
if ( result > 2 )
|
||||||
|
fgState.Size.X = w ;
|
||||||
|
|
||||||
|
if( result > 1 )
|
||||||
|
{
|
||||||
|
if( y < 0 )
|
||||||
|
fgState.Position.Y = fgDisplay.ScreenHeight + y - fgState.Size.Y;
|
||||||
|
else
|
||||||
|
fgState.Position.Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( result > 0 )
|
||||||
|
{
|
||||||
|
if( x < 0 )
|
||||||
|
fgState.Position.X = fgDisplay.ScreenWidth + x - fgState.Size.X;
|
||||||
|
else
|
||||||
|
fgState.Position.X = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have both arguments removed
|
||||||
|
*/
|
||||||
|
argv[ i - 1 ] = NULL;
|
||||||
|
argv[ i ] = NULL;
|
||||||
|
(* pargc) -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -483,19 +517,14 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
|
|||||||
/*
|
/*
|
||||||
* Have the arguments list compacted now
|
* Have the arguments list compacted now
|
||||||
*/
|
*/
|
||||||
for( i=1; i<argc; i++ )
|
j = 2 ;
|
||||||
|
for( i = 1; i < *pargc; i++, j++ )
|
||||||
{
|
{
|
||||||
if( argv[ i ] == NULL )
|
if( argv[ i ] == NULL )
|
||||||
{
|
{
|
||||||
for( j=i; j<argc; j++ )
|
while ( argv[j] == NULL ) j++ ; /* Guaranteed to end because there are "*pargc" arguments left */
|
||||||
{
|
argv[i] = argv[j] ;
|
||||||
if( argv[ j ] != NULL )
|
}
|
||||||
{
|
|
||||||
argv[ i ] = argv[ j ];
|
|
||||||
argv[ j ] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -505,55 +534,6 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
|
|||||||
*/
|
*/
|
||||||
fgInitialize( displayName );
|
fgInitialize( displayName );
|
||||||
|
|
||||||
#if TARGET_HOST_UNIX_X11
|
|
||||||
/*
|
|
||||||
* We can process the default window geometry settings safely now
|
|
||||||
*
|
|
||||||
* WARNING: have this rewritten to be portable. That won't be hard.
|
|
||||||
*/
|
|
||||||
if( geometrySettings != NULL )
|
|
||||||
{
|
|
||||||
int result, x, y;
|
|
||||||
unsigned int w, h;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Have the settings parsed now. This is easy.
|
|
||||||
* We will use the XParseGeometry function.
|
|
||||||
*/
|
|
||||||
result = XParseGeometry( geometrySettings, &x, &y, &w, &h );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check what we have been supplied with...
|
|
||||||
*/
|
|
||||||
if( (result & WidthValue) && (w >= 0) )
|
|
||||||
fgState.Size.X = w;
|
|
||||||
|
|
||||||
if( (result & HeightValue) && (h >= 0) )
|
|
||||||
fgState.Size.Y = h;
|
|
||||||
|
|
||||||
if( result & XValue )
|
|
||||||
{
|
|
||||||
if( result & XNegative )
|
|
||||||
fgState.Position.X = fgDisplay.ScreenWidth + x - fgState.Size.X;
|
|
||||||
else
|
|
||||||
fgState.Position.X = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( result & YValue )
|
|
||||||
{
|
|
||||||
if( result & YNegative )
|
|
||||||
fgState.Position.Y = fgDisplay.ScreenHeight + y - fgState.Size.Y;
|
|
||||||
else
|
|
||||||
fgState.Position.Y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free the geometry settings string
|
|
||||||
*/
|
|
||||||
free( geometrySettings );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for the minus one settings for both position and size...
|
* Check for the minus one settings for both position and size...
|
||||||
*/
|
*/
|
||||||
@ -605,7 +585,7 @@ void FGAPIENTRY glutInitWindowSize( int width, int height )
|
|||||||
/*
|
/*
|
||||||
* The settings can be disables when both values are negative
|
* The settings can be disables when both values are negative
|
||||||
*/
|
*/
|
||||||
if( (width >= 0) && (height >= 0) )
|
if( (width > 0) && (height > 0) )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We want to specify the initial size of each of the windows
|
* We want to specify the initial size of each of the windows
|
||||||
@ -617,7 +597,7 @@ void FGAPIENTRY glutInitWindowSize( int width, int height )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The initial size of each of the windows is specified by the wm
|
* The initial size of each of the windows is specified by the wm (officially this is an error condition)
|
||||||
*/
|
*/
|
||||||
fgState.Size.X = -1;
|
fgState.Size.X = -1;
|
||||||
fgState.Size.Y = -1;
|
fgState.Size.Y = -1;
|
||||||
@ -845,7 +825,7 @@ void FGAPIENTRY glutInitDisplayString( char* displayMode )
|
|||||||
value = strtol( valueString, NULL, 0 );
|
value = strtol( valueString, NULL, 0 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we need to match the capability string and it's ID
|
* Now we need to match the capability string and its ID
|
||||||
*/
|
*/
|
||||||
for( i=0; g_Tokens[ i ]!=NULL; i++ )
|
for( i=0; g_Tokens[ i ]!=NULL; i++ )
|
||||||
{
|
{
|
||||||
@ -921,8 +901,175 @@ void FGAPIENTRY glutInitDisplayString( char* displayMode )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NUM_TOKENS 28
|
||||||
|
static char* Tokens[] =
|
||||||
|
{
|
||||||
|
"alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double", "green",
|
||||||
|
"index", "num", "red", "rgba", "rgb", "luminance", "stencil", "single", "stereo", "samples",
|
||||||
|
"slow", "win32pdf", "xvisual", "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
|
||||||
|
"xtruecolor", "xdirectcolor"
|
||||||
|
};
|
||||||
|
|
||||||
|
static int TokenLengths[] =
|
||||||
|
{
|
||||||
|
5, 4, 3, 4, 6, 10, 5, 6, 5,
|
||||||
|
5, 3, 3, 4, 3, 9, 7, 6, 6, 7,
|
||||||
|
4, 8, 7, 11, 10, 12, 12,
|
||||||
|
10, 12
|
||||||
|
};
|
||||||
|
|
||||||
void FGAPIENTRY glutInitDisplayString( char* displayMode )
|
void FGAPIENTRY glutInitDisplayString( char* displayMode )
|
||||||
{
|
{
|
||||||
|
int glut_state_flag = 0 ;
|
||||||
|
/*
|
||||||
|
* Unpack a lot of options from a character string. The options are delimited by blanks or tabs.
|
||||||
|
*/
|
||||||
|
char *token ;
|
||||||
|
int len = strlen ( displayMode ) ;
|
||||||
|
char *buffer = malloc ( (len+1) * sizeof(char) ) ;
|
||||||
|
memcpy ( buffer, displayMode, len ) ;
|
||||||
|
buffer[len] = '\0' ;
|
||||||
|
|
||||||
|
token = strtok ( buffer, " \t" ) ;
|
||||||
|
while ( token )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Process this token
|
||||||
|
*/
|
||||||
|
int i ;
|
||||||
|
for ( i = 0; i < NUM_TOKENS; i++ )
|
||||||
|
{
|
||||||
|
if ( strncmp ( token, Tokens[i], TokenLengths[i] ) == 0 ) break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( i )
|
||||||
|
{
|
||||||
|
case 0 : /* "alpha": Alpha color buffer precision in bits */
|
||||||
|
glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer precision in bits */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 2 : /* "acc": Red, green, and blue accumulation buffer precision in bits with zero bits alpha */
|
||||||
|
glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 3 : /* "blue": Blue color buffer precision in bits */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 4 : /* "buffer": Number of bits in the color index color buffer */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 5 : /* "conformant": Boolean indicating if the frame buffer configuration is conformant or not */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 6 : /* "depth": Number of bits of precsion in the depth buffer */
|
||||||
|
glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 7 : /* "double": Boolean indicating if the color buffer is double buffered */
|
||||||
|
glut_state_flag |= GLUT_DOUBLE ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 8 : /* "green": Green color buffer precision in bits */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 9 : /* "index": Boolean if the color model is color index or not */
|
||||||
|
glut_state_flag |= GLUT_INDEX ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 10 : /* "num": A special capability name indicating where the value represents the Nth frame buffer configuration matching the description string */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 11 : /* "red": Red color buffer precision in bits */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in the RGBA color buffer */
|
||||||
|
glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 13 : /* "rgb": Number of bits of red, green, and blue in the RGBA color buffer with zero bits alpha */
|
||||||
|
glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 14 : /* "luminance": Number of bits of red in the RGBA and zero bits of green, blue (alpha not specified) of color buffer precision */
|
||||||
|
glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 15 : /* "stencil": Number of bits in the stencil buffer */
|
||||||
|
glut_state_flag |= GLUT_STENCIL ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 16 : /* "single": Boolean indicate the color buffer is single buffered */
|
||||||
|
glut_state_flag |= GLUT_SINGLE ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 17 : /* "stereo": Boolean indicating the color buffer supports OpenGL-style stereo */
|
||||||
|
glut_state_flag |= GLUT_STEREO ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 18 : /* "samples": Indicates the number of multisamples to use based on GLX's SGIS_multisample extension (for antialiasing) */
|
||||||
|
glut_state_flag |= GLUT_MULTISAMPLE ; /* Somebody fix this for me! */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 19 : /* "slow": Boolean indicating if the frame buffer configuration is slow or not */
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 20 : /* "win32pdf": matches the Win32 Pixel Format Descriptor by number */
|
||||||
|
#ifdef TARGET_HOST_WIN32
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 21 : /* "xvisual": matches the X visual ID by number */
|
||||||
|
#ifdef TARGET_HOST_UNIX_X11
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 22 : /* "xstaticgray": boolean indicating if the frame buffer configuration's X visual is of type StaticGray */
|
||||||
|
#ifdef TARGET_HOST_UNIX_X11
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 23 : /* "xgrayscale": boolean indicating if the frame buffer configuration's X visual is of type GrayScale */
|
||||||
|
#ifdef TARGET_HOST_UNIX_X11
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 24 : /* "xstaticcolor": boolean indicating if the frame buffer configuration's X visual is of type StaticColor */
|
||||||
|
#ifdef TARGET_HOST_UNIX_X11
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 25 : /* "xpseudocolor": boolean indicating if the frame buffer configuration's X visual is of type PseudoColor */
|
||||||
|
#ifdef TARGET_HOST_UNIX_X11
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 26 : /* "xtruecolor": boolean indicating if the frame buffer configuration's X visual is of type TrueColor */
|
||||||
|
#ifdef TARGET_HOST_UNIX_X11
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 27 : /* "xdirectcolor": boolean indicating if the frame buffer configuration's X visual is of type DirectColor */
|
||||||
|
#ifdef TARGET_HOST_UNIX_X11
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case 28 : /* Unrecognized */
|
||||||
|
printf ( "WARNING - Display string token not recognized: %s\n", token ) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = strtok ( NULL, " \t" ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
free ( buffer ) ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We will make use of this value when creating a new OpenGL context...
|
||||||
|
*/
|
||||||
|
fgState.DisplayMode = glut_state_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** END OF FILE ***/
|
/*** END OF FILE ***/
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,7 @@
|
|||||||
*/
|
*/
|
||||||
#define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13
|
#define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13
|
||||||
#define FREEGLUT_MENU_HEIGHT 15
|
#define FREEGLUT_MENU_HEIGHT 15
|
||||||
|
#define FREEGLUT_MENU_BORDER 8
|
||||||
|
|
||||||
|
|
||||||
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||||
@ -74,215 +75,247 @@ static SFG_MenuEntry *fghFindMenuEntry( SFG_Menu* menu, int index )
|
|||||||
/*
|
/*
|
||||||
* Private static function to check for the current menu/sub menu activity state
|
* Private static function to check for the current menu/sub menu activity state
|
||||||
*/
|
*/
|
||||||
static GLboolean fghCheckMenuStatus( SFG_Menu* menu )
|
static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
|
||||||
{
|
{
|
||||||
SFG_Window* window = fgStructure.Window;
|
SFG_MenuEntry* menuEntry;
|
||||||
SFG_MenuEntry* menuEntry;
|
int x, y;
|
||||||
int x, y;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First of all check any of the active sub menus...
|
||||||
|
*/
|
||||||
|
for( menuEntry = menu->Entries.First; menuEntry;
|
||||||
|
menuEntry = menuEntry->Node.Next )
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* First of all check any of the active sub menus...
|
* Is that an active sub menu by any case?
|
||||||
*/
|
*/
|
||||||
for( menuEntry = menu->Entries.First; menuEntry;
|
if( menuEntry->SubMenu != NULL && menuEntry->IsActive == TRUE )
|
||||||
menuEntry = menuEntry->Node.Next )
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Is that an active sub menu by any case?
|
* OK, have the sub-menu checked, too. If it returns TRUE, it will mean
|
||||||
*/
|
* that it caught the mouse cursor and we do not need to regenerate
|
||||||
if( menuEntry->SubMenu != NULL && menuEntry->IsActive == TRUE )
|
* the activity list, and so our parents do...
|
||||||
{
|
*/
|
||||||
/*
|
if( fghCheckMenuStatus( window, menuEntry->SubMenu ) == TRUE )
|
||||||
* OKi, have the sub-menu checked, too. If it returns TRUE, it will mean
|
|
||||||
* that it caught the mouse cursor and we do not need to regenerate
|
|
||||||
* the activity list, and so our parents do...
|
|
||||||
*/
|
|
||||||
if( fghCheckMenuStatus( menuEntry->SubMenu ) == TRUE )
|
|
||||||
return( TRUE );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* That much about our sub menus, let's get to checking the current menu:
|
|
||||||
*/
|
|
||||||
x = window->State.MouseX - menu->X;
|
|
||||||
y = window->State.MouseY - menu->Y;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark all menu entries inactive...
|
|
||||||
*/
|
|
||||||
for( menuEntry = menu->Entries.First; menuEntry;
|
|
||||||
menuEntry = menuEntry->Node.Next )
|
|
||||||
{
|
|
||||||
menuEntry->IsActive = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu->IsActive = FALSE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the mouse cursor is contained within the current menu box
|
|
||||||
*/
|
|
||||||
if( x >= 0 && x < menu->Width && y >= 0 && y < menu->Height )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Calculation of the highlighted menu item is easy enough now:
|
|
||||||
*/
|
|
||||||
int menuID = y / FREEGLUT_MENU_HEIGHT;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The mouse cursor is somewhere over our box, check it out.
|
|
||||||
*/
|
|
||||||
menuEntry = fghFindMenuEntry( menu, menuID + 1 );
|
|
||||||
assert( menuEntry != NULL );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark the menu as active...
|
|
||||||
*/
|
|
||||||
menuEntry->IsActive = TRUE;
|
|
||||||
menuEntry->Ordinal = menuID;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't forget about marking the current menu as active, too:
|
|
||||||
*/
|
|
||||||
menu->IsActive = TRUE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OKi, we have marked that entry as active, but it would be also
|
|
||||||
* nice to have it's contents updated, in case it's a sub menu.
|
|
||||||
* Also, ignore the return value of the check function:
|
|
||||||
*/
|
|
||||||
if( menuEntry->SubMenu != NULL )
|
|
||||||
{
|
|
||||||
int x = window->State.MouseX;
|
|
||||||
int y = window->State.MouseY;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set up the initial menu position now...
|
|
||||||
*/
|
|
||||||
|
|
||||||
if( x > 15 ) menuEntry->SubMenu->X = x - 15; else menuEntry->SubMenu->X = 15;
|
|
||||||
if( y > 15 ) menuEntry->SubMenu->Y = y - 15; else menuEntry->SubMenu->Y = 15;
|
|
||||||
|
|
||||||
if( x > (glutGet( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width - 15) )
|
|
||||||
menuEntry->SubMenu->X = glutGet( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width - 15;
|
|
||||||
if( y > (glutGet( GLUT_WINDOW_HEIGHT ) - menuEntry->SubMenu->Height - 15) )
|
|
||||||
menuEntry->SubMenu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menuEntry->SubMenu->Height - 15;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ...then check the submenu's state:
|
|
||||||
*/
|
|
||||||
fghCheckMenuStatus( menuEntry->SubMenu );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Report back that we have caught the menu cursor
|
|
||||||
*/
|
|
||||||
return( TRUE );
|
return( TRUE );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* That much about our sub menus, let's get to checking the current menu:
|
||||||
|
*/
|
||||||
|
x = window->State.MouseX - menu->X;
|
||||||
|
y = window->State.MouseY - menu->Y;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark all menu entries inactive...
|
||||||
|
*/
|
||||||
|
for( menuEntry = menu->Entries.First; menuEntry;
|
||||||
|
menuEntry = menuEntry->Node.Next )
|
||||||
|
{
|
||||||
|
menuEntry->IsActive = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu->IsActive = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the mouse cursor is contained within the current menu box
|
||||||
|
*/
|
||||||
|
if( x >= 0 && x < menu->Width && y >= 0 && y < menu->Height )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Calculation of the highlighted menu item is easy enough now:
|
||||||
|
*/
|
||||||
|
int menuID = y / FREEGLUT_MENU_HEIGHT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Looks like the menu cursor is somewhere else...
|
* The mouse cursor is somewhere over our box, check it out.
|
||||||
*/
|
*/
|
||||||
return( FALSE );
|
menuEntry = fghFindMenuEntry( menu, menuID + 1 );
|
||||||
|
assert( menuEntry != NULL );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark the menu as active...
|
||||||
|
*/
|
||||||
|
menuEntry->IsActive = TRUE;
|
||||||
|
menuEntry->Ordinal = menuID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't forget about marking the current menu as active, too:
|
||||||
|
*/
|
||||||
|
menu->IsActive = TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OKi, we have marked that entry as active, but it would be also
|
||||||
|
* nice to have its contents updated, in case it's a sub menu.
|
||||||
|
* Also, ignore the return value of the check function:
|
||||||
|
*/
|
||||||
|
if( menuEntry->SubMenu != NULL )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set up the initial menu position now...
|
||||||
|
*/
|
||||||
|
|
||||||
|
menuEntry->SubMenu->X = menu->X + menu->Width ;
|
||||||
|
menuEntry->SubMenu->Y = menu->Y + menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the submenu stays within the window
|
||||||
|
*/
|
||||||
|
if ( menuEntry->SubMenu->X + menuEntry->SubMenu->Width > glutGet ( GLUT_WINDOW_WIDTH ) )
|
||||||
|
{
|
||||||
|
menuEntry->SubMenu->X = menu->X - menuEntry->SubMenu->Width ;
|
||||||
|
if ( menuEntry->SubMenu->X < 0 )
|
||||||
|
menuEntry->SubMenu->X = glutGet ( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ...then check the submenu's state:
|
||||||
|
*/
|
||||||
|
fghCheckMenuStatus( window, menuEntry->SubMenu );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Even if the submenu turned up inactive, activate it because its parent entry is active
|
||||||
|
*/
|
||||||
|
menuEntry->SubMenu->IsActive = TRUE ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Report back that we have caught the menu cursor
|
||||||
|
*/
|
||||||
|
return( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Looks like the menu cursor is somewhere else...
|
||||||
|
*/
|
||||||
|
return( FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Displays a menu box and all of it's submenus (if they are active)
|
* Displays a menu box and all of its submenus (if they are active)
|
||||||
*/
|
*/
|
||||||
static void fghDisplayMenuBox( SFG_Menu* menu )
|
static void fghDisplayMenuBox( SFG_Menu* menu )
|
||||||
{
|
{
|
||||||
SFG_MenuEntry *menuEntry;
|
SFG_MenuEntry *menuEntry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have the menu box drawn first. The +- values are
|
||||||
|
* here just to make it more nice-looking...
|
||||||
|
*/
|
||||||
|
glColor4f( 0.0, 0.0, 0.0, 1.0 );
|
||||||
|
glBegin( GL_QUADS );
|
||||||
|
glVertex2f( menu->X , menu->Y - 1 );
|
||||||
|
glVertex2f( menu->X + menu->Width, menu->Y - 1 );
|
||||||
|
glVertex2f( menu->X + menu->Width, menu->Y + 4 + menu->Height );
|
||||||
|
glVertex2f( menu->X , menu->Y + 4 + menu->Height );
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glColor4f( 0.3, 0.4, 0.5, 1.0 );
|
||||||
|
glBegin( GL_QUADS );
|
||||||
|
glVertex2f( menu->X - 2 , menu->Y + 1 );
|
||||||
|
glVertex2f( menu->X - 2 + menu->Width, menu->Y + 1 );
|
||||||
|
glVertex2f( menu->X - 2 + menu->Width, menu->Y + 2 + menu->Height );
|
||||||
|
glVertex2f( menu->X - 2 , menu->Y + 2 + menu->Height );
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if any of the submenus is currently active...
|
||||||
|
*/
|
||||||
|
for( menuEntry = menu->Entries.First; menuEntry;
|
||||||
|
menuEntry = menuEntry->Node.Next )
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Have the menu box drawn first. The +- values are
|
* Has the menu been marked as active, maybe?
|
||||||
* here just to make it more nice-looking...
|
|
||||||
*/
|
*/
|
||||||
glColor4f( 0.0, 0.0, 0.0, 1.0 );
|
if( menuEntry->IsActive == TRUE )
|
||||||
glBegin( GL_QUADS );
|
|
||||||
glVertex2f( menu->X - 8 , menu->Y - 1 );
|
|
||||||
glVertex2f( menu->X + 8 + menu->Width, menu->Y - 1 );
|
|
||||||
glVertex2f( menu->X + 8 + menu->Width, menu->Y + 4 + menu->Height );
|
|
||||||
glVertex2f( menu->X - 8 , menu->Y + 4 + menu->Height );
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glColor4f( 0.3, 0.4, 0.5, 1.0 );
|
|
||||||
glBegin( GL_QUADS );
|
|
||||||
glVertex2f( menu->X - 6 , menu->Y + 1 );
|
|
||||||
glVertex2f( menu->X + 6 + menu->Width, menu->Y + 1 );
|
|
||||||
glVertex2f( menu->X + 6 + menu->Width, menu->Y + 2 + menu->Height );
|
|
||||||
glVertex2f( menu->X - 6 , menu->Y + 2 + menu->Height );
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if any of the submenus is currently active...
|
|
||||||
*/
|
|
||||||
for( menuEntry = menu->Entries.First; menuEntry;
|
|
||||||
menuEntry = menuEntry->Node.Next )
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Has the menu been marked as active, maybe?
|
* That's truly right, and we need to have it highlighted.
|
||||||
*/
|
* There is an assumption that mouse cursor didn't move
|
||||||
if( menuEntry->IsActive == TRUE )
|
* since the last check of menu activity state:
|
||||||
{
|
*/
|
||||||
/*
|
int menuID = menuEntry->Ordinal;
|
||||||
* That's truly right, and we need to have it highlighted.
|
|
||||||
* There is an assumption that mouse cursor didn't move
|
|
||||||
* since the last check of menu activity state:
|
|
||||||
*/
|
|
||||||
int menuID = menuEntry->Ordinal;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* So have the highlight drawn...
|
* So have the highlight drawn...
|
||||||
*/
|
*/
|
||||||
glColor4f( 0.2, 0.3, 0.4, 1.0 );
|
glColor4f( 0.2, 0.3, 0.4, 1.0 );
|
||||||
glBegin( GL_QUADS );
|
glBegin( GL_QUADS );
|
||||||
glVertex2f( menu->X - 6 , menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
|
glVertex2f( menu->X - 2 , menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
|
||||||
glVertex2f( menu->X + 6 + menu->Width, menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
|
glVertex2f( menu->X - 2 + menu->Width, menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
|
||||||
glVertex2f( menu->X + 6 + menu->Width, menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
|
glVertex2f( menu->X - 2 + menu->Width, menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
|
||||||
glVertex2f( menu->X - 6 , menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
|
glVertex2f( menu->X - 2 , menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print the menu entries now...
|
||||||
|
*/
|
||||||
|
glColor4f( 1, 1, 1, 1 );
|
||||||
|
|
||||||
|
for( menuEntry = menu->Entries.First, i=0; menuEntry;
|
||||||
|
menuEntry = menuEntry->Node.Next, ++i )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Move the raster into position...
|
||||||
|
*/
|
||||||
|
glRasterPos2i(
|
||||||
|
menu->X + FREEGLUT_MENU_BORDER,
|
||||||
|
menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print the menu entries now...
|
* Have the label drawn, character after character:
|
||||||
*/
|
*/
|
||||||
glColor4f( 1, 1, 1, 1 );
|
glutBitmapString( FREEGLUT_MENU_FONT, menuEntry->Text);
|
||||||
|
|
||||||
for( menuEntry = menu->Entries.First, i=0; menuEntry;
|
|
||||||
menuEntry = menuEntry->Node.Next, ++i )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Move the raster into position...
|
|
||||||
*/
|
|
||||||
glRasterPos2i(
|
|
||||||
menu->X,
|
|
||||||
menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Have the label drawn, character after character:
|
|
||||||
*/
|
|
||||||
glutBitmapString( FREEGLUT_MENU_FONT, menuEntry->Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we are ready to check if any of our children needs to be redrawn:
|
* If it's a submenu, draw a right arrow
|
||||||
*/
|
*/
|
||||||
for( menuEntry = menu->Entries.First; menuEntry;
|
if ( menuEntry->SubMenu != NULL )
|
||||||
menuEntry = menuEntry->Node.Next )
|
|
||||||
{
|
{
|
||||||
/*
|
GLubyte arrow_char [] = { 0, 0, 32, 48, 56, 60, 62, 63, 62, 60, 56, 48, 32, 0, 0 } ;
|
||||||
* Is that an active sub menu by any case?
|
int width = glutBitmapWidth ( FREEGLUT_MENU_FONT, ' ' ) ;
|
||||||
*/
|
|
||||||
if( menuEntry->SubMenu != NULL && menuEntry->IsActive == TRUE )
|
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* Yeah, indeed. Have it redrawn now:
|
* Set up the pixel unpacking ways
|
||||||
*/
|
*/
|
||||||
fghDisplayMenuBox( menuEntry->SubMenu );
|
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
|
||||||
}
|
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
|
||||||
|
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
|
||||||
|
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
|
||||||
|
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
|
||||||
|
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||||
|
|
||||||
|
glRasterPos2i ( menu->X + menu->Width - 2 - width,
|
||||||
|
menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT ) ;
|
||||||
|
glBitmap ( width, FREEGLUT_MENU_HEIGHT, 0, 0, 0.0, 0.0, arrow_char ) ;
|
||||||
|
glPopClientAttrib();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we are ready to check if any of our children needs to be redrawn:
|
||||||
|
*/
|
||||||
|
for( menuEntry = menu->Entries.First; menuEntry;
|
||||||
|
menuEntry = menuEntry->Node.Next )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Is that an active sub menu by any case?
|
||||||
|
*/
|
||||||
|
if( menuEntry->SubMenu != NULL && menuEntry->IsActive == TRUE )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Yeah, indeed. Have it redrawn now:
|
||||||
|
*/
|
||||||
|
fghDisplayMenuBox( menuEntry->SubMenu );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -292,7 +325,6 @@ void fgDisplayMenu( void )
|
|||||||
{
|
{
|
||||||
SFG_Window* window = fgStructure.Window;
|
SFG_Window* window = fgStructure.Window;
|
||||||
SFG_Menu* menu = NULL;
|
SFG_Menu* menu = NULL;
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure there is a current window available
|
* Make sure there is a current window available
|
||||||
@ -302,17 +334,12 @@ void fgDisplayMenu( void )
|
|||||||
/*
|
/*
|
||||||
* Check if there is an active menu attached to this window...
|
* Check if there is an active menu attached to this window...
|
||||||
*/
|
*/
|
||||||
for( i=0; i<FREEGLUT_MAX_MENUS; i++ )
|
menu = window->ActiveMenu;
|
||||||
{
|
|
||||||
if( window->Menu[ i ] != NULL && window->MenuActive[ i ] == TRUE )
|
|
||||||
menu = window->Menu[ i ];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Did we find an active window?
|
* Did we find an active window?
|
||||||
*/
|
*/
|
||||||
freeglut_return_if_fail( menu != NULL );
|
freeglut_return_if_fail( menu != NULL );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the OpenGL state to do the rendering first:
|
* Prepare the OpenGL state to do the rendering first:
|
||||||
*/
|
*/
|
||||||
@ -345,7 +372,7 @@ void fgDisplayMenu( void )
|
|||||||
/*
|
/*
|
||||||
* First of all, have the exact menu status check:
|
* First of all, have the exact menu status check:
|
||||||
*/
|
*/
|
||||||
fghCheckMenuStatus( menu );
|
fghCheckMenuStatus( window, menu );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The status has been updated and we're ready to have the menu drawn now:
|
* The status has been updated and we're ready to have the menu drawn now:
|
||||||
@ -357,134 +384,130 @@ void fgDisplayMenu( void )
|
|||||||
*/
|
*/
|
||||||
glPopAttrib();
|
glPopAttrib();
|
||||||
|
|
||||||
glMatrixMode( GL_MODELVIEW );
|
|
||||||
glPopMatrix();
|
|
||||||
glMatrixMode( GL_PROJECTION );
|
glMatrixMode( GL_PROJECTION );
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Activates a menu pointed by the function argument
|
* Activates a menu pointed by the function argument
|
||||||
*/
|
*/
|
||||||
void fgActivateMenu( int button )
|
void fgActivateMenu( SFG_Window* window, int button )
|
||||||
{
|
{
|
||||||
SFG_Window* window = fgStructure.Window;
|
int x, y;
|
||||||
SFG_Menu* menu = NULL;
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
freeglut_assert_window;
|
/*
|
||||||
|
* We'll be referencing this menu a lot, so remember its address:
|
||||||
|
*/
|
||||||
|
SFG_Menu* menu = window->Menu[ button ];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark the menu as active, so that it gets displayed:
|
* Mark the menu as active, so that it gets displayed:
|
||||||
*/
|
*/
|
||||||
window->MenuActive[ button ] = TRUE;
|
window->ActiveMenu = menu;
|
||||||
|
menu->IsActive = TRUE ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We'll be referencing this menu a lot, so remember it's address:
|
* Grab the mouse cursor position respective to the current window
|
||||||
*/
|
*/
|
||||||
menu = window->Menu[ button ];
|
x = window->State.MouseX;
|
||||||
|
y = window->State.MouseY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Grab the mouse cursor position respective to the current window
|
* Set up the initial menu position now:
|
||||||
*/
|
*/
|
||||||
x = window->State.MouseX;
|
menu->X = x ;
|
||||||
y = window->State.MouseY;
|
menu->Y = y ;
|
||||||
|
|
||||||
/*
|
glutSetWindow ( window->ID ) ;
|
||||||
* Set up the initial menu position now:
|
|
||||||
*/
|
|
||||||
if( x > 10 ) menu->X = x - 10; else menu->X = 5;
|
|
||||||
if( y > 10 ) menu->Y = y - 10; else menu->Y = 5;
|
|
||||||
|
|
||||||
if( x > (glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
|
if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
|
||||||
menu->X = glutGet( GLUT_WINDOW_WIDTH ) - menu->Width;
|
menu->X = glutGet( GLUT_WINDOW_WIDTH ) - menu->Width;
|
||||||
if( y > (glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height) )
|
if( y > ( glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height) )
|
||||||
menu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height;
|
menu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private static function to check for menu entry selection on menu deactivation
|
* Check whether an active menu absorbs a mouse click
|
||||||
*/
|
*/
|
||||||
static void fghCheckMenuSelect( SFG_Menu* menu )
|
GLboolean fgCheckActiveMenu ( SFG_Window *window, SFG_Menu *menu )
|
||||||
{
|
{
|
||||||
SFG_MenuEntry *menuEntry;
|
/*
|
||||||
|
* Near as I can tell, this is the active menu behaviour:
|
||||||
|
* - Down-click any button outside the menu, menu active: deactivate the menu
|
||||||
|
* - Down-click any button inside the menu, menu active: select the menu entry and deactivate the menu
|
||||||
|
* - Up-click the menu button outside the menu, menu active: nothing happens
|
||||||
|
* - Up-click the menu button inside the menu, menu active: select the menu entry and deactivate the menu
|
||||||
|
* Since menus can have submenus, we need to check this recursively.
|
||||||
|
*/
|
||||||
|
return fghCheckMenuStatus ( window, menu ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to check for menu entry selection on menu deactivation
|
||||||
|
*/
|
||||||
|
void fgExecuteMenuCallback( SFG_Menu* menu )
|
||||||
|
{
|
||||||
|
SFG_MenuEntry *menuEntry;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First of all check any of the active sub menus...
|
||||||
|
*/
|
||||||
|
for( menuEntry = menu->Entries.First; menuEntry; menuEntry = menuEntry->Node.Next)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* First of all check any of the active sub menus...
|
* Is this menu entry active?
|
||||||
*/
|
*/
|
||||||
for( menuEntry = menu->Entries.First; menuEntry;
|
if( menuEntry->IsActive == TRUE )
|
||||||
menuEntry = menuEntry->Node.Next)
|
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* If there is not a sub menu, execute the menu callback and return...
|
||||||
|
*/
|
||||||
|
if( menuEntry->SubMenu == NULL )
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Is this menu entry active?
|
* ...certainly given that there is one...
|
||||||
*/
|
*/
|
||||||
if( menuEntry->IsActive == TRUE )
|
if( menu->Callback != NULL )
|
||||||
{
|
menu->Callback( menuEntry->ID );
|
||||||
/*
|
|
||||||
* If this is not a sub menu, execute the menu callback and return...
|
|
||||||
*/
|
|
||||||
if( menuEntry->SubMenu == NULL )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* ...certainly given that there is one...
|
|
||||||
*/
|
|
||||||
if( menu->Callback != NULL )
|
|
||||||
menu->Callback( menuEntry->ID );
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise recurse into the submenu.
|
* Otherwise recurse into the submenu.
|
||||||
*/
|
*/
|
||||||
fghCheckMenuSelect( menuEntry->SubMenu );
|
fgExecuteMenuCallback( menuEntry->SubMenu );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is little sense in dwelling the search on
|
* There is little sense in dwelling the search on
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deactivates a menu pointed by the function argument.
|
* Deactivates a menu pointed by the function argument.
|
||||||
*/
|
*/
|
||||||
void fgDeactivateMenu( int button )
|
void fgDeactivateMenu( SFG_Window *window )
|
||||||
{
|
{
|
||||||
SFG_Window* window = fgStructure.Window;
|
|
||||||
SFG_Menu* menu = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure there is a current window available...
|
|
||||||
*/
|
|
||||||
freeglut_assert_window;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if there is an active menu attached to this window...
|
* Check if there is an active menu attached to this window...
|
||||||
*/
|
*/
|
||||||
for( i=0; i<FREEGLUT_MAX_MENUS; i++ )
|
SFG_Menu* menu = window->ActiveMenu;
|
||||||
{
|
|
||||||
if( window->Menu[ i ] != NULL && window->MenuActive[ i ] == TRUE )
|
|
||||||
menu = window->Menu[ i ];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Did we find an active window?
|
* Did we find an active window?
|
||||||
*/
|
*/
|
||||||
freeglut_return_if_fail( menu != NULL );
|
freeglut_return_if_fail( menu != NULL );
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if there was any menu entry active. This would
|
|
||||||
* mean the user has selected a menu entry...
|
|
||||||
*/
|
|
||||||
fghCheckMenuSelect( menu );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forget about having that menu active anymore, now:
|
* Forget about having that menu active anymore, now:
|
||||||
*/
|
*/
|
||||||
fgStructure.Window->MenuActive[ button ] = FALSE;
|
window->ActiveMenu = NULL;
|
||||||
|
menu->IsActive = FALSE ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -492,39 +515,39 @@ void fgDeactivateMenu( int button )
|
|||||||
*/
|
*/
|
||||||
void fghCalculateMenuBoxSize( void )
|
void fghCalculateMenuBoxSize( void )
|
||||||
{
|
{
|
||||||
SFG_MenuEntry* menuEntry;
|
SFG_MenuEntry* menuEntry;
|
||||||
int width = 0, height = 0;
|
int width = 0, height = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure there is a current menu set
|
||||||
|
*/
|
||||||
|
freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu != NULL );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The menu's box size depends on the menu entries:
|
||||||
|
*/
|
||||||
|
for( menuEntry = fgStructure.Menu->Entries.First; menuEntry;
|
||||||
|
menuEntry = menuEntry->Node.Next)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Update the menu entry's width value
|
||||||
|
*/
|
||||||
|
menuEntry->Width = glutBitmapLength( FREEGLUT_MENU_FONT, menuEntry->Text );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure there is a current menu set
|
* Check if it's the biggest we've found
|
||||||
*/
|
*/
|
||||||
freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu != NULL );
|
if( menuEntry->Width > width )
|
||||||
|
width = menuEntry->Width;
|
||||||
|
|
||||||
/*
|
height += FREEGLUT_MENU_HEIGHT;
|
||||||
* The menu's box size depends on the menu entries:
|
}
|
||||||
*/
|
|
||||||
for( menuEntry = fgStructure.Menu->Entries.First; menuEntry;
|
|
||||||
menuEntry = menuEntry->Node.Next)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Update the menu entry's width value
|
|
||||||
*/
|
|
||||||
menuEntry->Width = glutBitmapLength( FREEGLUT_MENU_FONT, menuEntry->Text );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if it's the biggest we've found
|
* Store the menu's box size now:
|
||||||
*/
|
*/
|
||||||
if( menuEntry->Width > width )
|
fgStructure.Menu->Height = height;
|
||||||
width = menuEntry->Width;
|
fgStructure.Menu->Width = width + 2 * FREEGLUT_MENU_BORDER ;
|
||||||
|
|
||||||
height += FREEGLUT_MENU_HEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Store the menu's box size now:
|
|
||||||
*/
|
|
||||||
fgStructure.Menu->Height = height;
|
|
||||||
fgStructure.Menu->Width = width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -581,7 +604,7 @@ int FGAPIENTRY glutGetMenu( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets the current menu given it's menu ID
|
* Sets the current menu given its menu ID
|
||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutSetMenu( int menuID )
|
void FGAPIENTRY glutSetMenu( int menuID )
|
||||||
{
|
{
|
||||||
@ -629,32 +652,32 @@ void FGAPIENTRY glutAddMenuEntry( const char* label, int value )
|
|||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutAddSubMenu( const char* label, int subMenuID )
|
void FGAPIENTRY glutAddSubMenu( const char* label, int subMenuID )
|
||||||
{
|
{
|
||||||
SFG_MenuEntry* menuEntry = calloc( sizeof(SFG_MenuEntry), 1 );
|
SFG_MenuEntry* menuEntry = calloc( sizeof(SFG_MenuEntry), 1 );
|
||||||
SFG_Menu* subMenu = fgMenuByID( subMenuID );
|
SFG_Menu* subMenu = fgMenuByID( subMenuID );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure there is a current menu and the sub menu
|
* Make sure there is a current menu and the sub menu
|
||||||
* we want to attach actually exists...
|
* we want to attach actually exists...
|
||||||
*/
|
*/
|
||||||
freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu != NULL );
|
freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu != NULL );
|
||||||
freeglut_return_if_fail( subMenu != NULL );
|
freeglut_return_if_fail( subMenu != NULL );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill in the appropriate values
|
* Fill in the appropriate values
|
||||||
*/
|
*/
|
||||||
menuEntry->Text = strdup( label );
|
menuEntry->Text = strdup( label );
|
||||||
menuEntry->SubMenu = subMenu;
|
menuEntry->SubMenu = subMenu;
|
||||||
menuEntry->ID = -1;
|
menuEntry->ID = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Have the new menu entry attached to the current menu
|
* Have the new menu entry attached to the current menu
|
||||||
*/
|
*/
|
||||||
fgListAppend( &fgStructure.Menu->Entries, &menuEntry->Node );
|
fgListAppend( &fgStructure.Menu->Entries, &menuEntry->Node );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the menu's dimensions now
|
* Update the menu's dimensions now
|
||||||
*/
|
*/
|
||||||
fghCalculateMenuBoxSize();
|
fghCalculateMenuBoxSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -50,58 +50,59 @@
|
|||||||
*/
|
*/
|
||||||
int FGAPIENTRY glutExtensionSupported( const char* extension )
|
int FGAPIENTRY glutExtensionSupported( const char* extension )
|
||||||
{
|
{
|
||||||
const char *extensions;
|
const char *extensions;
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
int i;
|
int len = strlen ( extension ) ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure there is a current window, and thus -- a current context available
|
||||||
|
*/
|
||||||
|
freeglut_assert_ready;
|
||||||
|
freeglut_return_val_if_fail( fgStructure.Window != NULL, 0 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note it is safe to query the extensions
|
||||||
|
*/
|
||||||
|
extensions = glGetString(GL_EXTENSIONS);
|
||||||
|
|
||||||
|
freeglut_return_val_if_fail( extensions != NULL, 0 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the extension itself looks valid
|
||||||
|
*/
|
||||||
|
if ( strchr ( extension, ' ' ) != NULL )
|
||||||
|
return( 0 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for our extension
|
||||||
|
*/
|
||||||
|
for (ptr = extensions; *ptr;)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Is it the current extension?
|
||||||
|
*/
|
||||||
|
if ( strncmp ( extension, extensions, len ) == 0 )
|
||||||
|
return 1 ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure there is a current window, and thus -- a current context available
|
* No, go find the next extension. They are separated from each other by one or more blank spaces.
|
||||||
*/
|
*/
|
||||||
freeglut_assert_ready;
|
ptr = strchr ( ptr + len, ' ' ) ;
|
||||||
freeglut_return_val_if_fail( fgStructure.Window != NULL, 0 );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not it is safe to query the extenstions
|
* If we ran off the end of the "extensions" character string, we didn't find it. Return failure.
|
||||||
*/
|
*/
|
||||||
extensions = glGetString(GL_EXTENSIONS);
|
if ( !ptr ) return 0 ;
|
||||||
|
|
||||||
freeglut_return_val_if_fail( extensions != NULL, 0 );
|
while ( *ptr == ' ' )
|
||||||
|
ptr++ ;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
return 0 ;
|
||||||
* Check if the extension itself looks valid
|
|
||||||
*/
|
|
||||||
for( i=0; i<strlen( extension ); i++ )
|
|
||||||
if( extension[ i ] == ' ' )
|
|
||||||
return( 0 );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look for our extension
|
|
||||||
*/
|
|
||||||
for (ptr = extensions; *ptr;)
|
|
||||||
{
|
|
||||||
const char *str = extension;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
while ( (c = *(str++)) )
|
|
||||||
{
|
|
||||||
if (*ptr != c)
|
|
||||||
goto next;
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
if ( !(c = *ptr) || c == ' ' )
|
|
||||||
return 1;
|
|
||||||
next:
|
|
||||||
while ( (c = *ptr) && c != ' ' )
|
|
||||||
ptr++;
|
|
||||||
while (*ptr == ' ')
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function reports all the errors that happened till now
|
* This function reports all the OpenGL errors that happened till now
|
||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutReportErrors( void )
|
void FGAPIENTRY glutReportErrors( void )
|
||||||
{
|
{
|
||||||
@ -133,10 +134,10 @@ void FGAPIENTRY glutReportErrors( void )
|
|||||||
/*
|
/*
|
||||||
* Turns the ignore key auto repeat feature on and off
|
* Turns the ignore key auto repeat feature on and off
|
||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutIgnoreKeyRepeat( int ignore )
|
void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ) /* DEPRECATED 11/4/02 - Do not use */
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This is simple and not demanging...
|
* This is simple and not damaging...
|
||||||
*/
|
*/
|
||||||
fgState.IgnoreKeyRepeat = ignore ? TRUE : FALSE;
|
fgState.IgnoreKeyRepeat = ignore ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
@ -47,96 +47,83 @@
|
|||||||
|
|
||||||
/* -- LOCAL DEFINITIONS ---------------------------------------------------- */
|
/* -- LOCAL DEFINITIONS ---------------------------------------------------- */
|
||||||
|
|
||||||
/*
|
|
||||||
* Those are definitions introduced to make the glutGet() more easy,
|
|
||||||
* however they might introduce errors if someone ports GLX to Win32 :)
|
|
||||||
*
|
|
||||||
* Btw. this is not that a bad idea (wrapping WGL around GLX)...
|
|
||||||
*/
|
|
||||||
#if TARGET_HOST_WIN32
|
|
||||||
# define GLX_RGBA 0x01
|
|
||||||
# define GLX_DOUBLEBUFFER 0x02
|
|
||||||
# define GLX_BUFFER_SIZE 0x03
|
|
||||||
# define GLX_STENCIL_SIZE 0x04
|
|
||||||
# define GLX_DEPTH_SIZE 0x05
|
|
||||||
# define GLX_RED_SIZE 0x06
|
|
||||||
# define GLX_GREEN_SIZE 0x07
|
|
||||||
# define GLX_BLUE_SIZE 0x08
|
|
||||||
# define GLX_ALPHA_SIZE 0x09
|
|
||||||
# define GLX_ACCUM_RED_SIZE 0x0A
|
|
||||||
# define GLX_ACCUM_GREEN_SIZE 0x0B
|
|
||||||
# define GLX_ACCUM_BLUE_SIZE 0x0C
|
|
||||||
# define GLX_ACCUM_ALPHA_SIZE 0x0D
|
|
||||||
# define GLX_STEREO 0x0E
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||||
|
|
||||||
|
#if TARGET_HOST_UNIX_X11
|
||||||
/*
|
/*
|
||||||
* Queries the GL context about some attributes
|
* Queries the GL context about some attributes
|
||||||
*/
|
*/
|
||||||
static int fghGetConfig( int attribute )
|
static int fghGetConfig( int attribute )
|
||||||
{
|
{
|
||||||
int returnValue;
|
int returnValue ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return nothing if there is no current window set
|
* Return nothing if there is no current window set
|
||||||
*/
|
*/
|
||||||
if( fgStructure.Window == NULL )
|
if( fgStructure.Window == NULL )
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
|
||||||
#if TARGET_HOST_UNIX_X11
|
/*
|
||||||
/*
|
* glXGetConfig should work fine
|
||||||
* glXGetConfig should work fine
|
*/
|
||||||
*/
|
glXGetConfig( fgDisplay.Display, fgStructure.Window->Window.VisualInfo, attribute, &returnValue );
|
||||||
glXGetConfig( fgDisplay.Display, fgStructure.Window->Window.VisualInfo, attribute, &returnValue );
|
|
||||||
|
|
||||||
#elif TARGET_HOST_WIN32
|
|
||||||
/*
|
|
||||||
* This is going to be a bit harder than the X11 version...
|
|
||||||
*/
|
|
||||||
# pragma message( "freeglut_state.c::fghGetConfig() says hello world my name is not implemented!" )
|
|
||||||
switch( attribute )
|
|
||||||
{
|
|
||||||
case GLX_RGBA:
|
|
||||||
case GLX_DOUBLEBUFFER:
|
|
||||||
case GLX_BUFFER_SIZE:
|
|
||||||
case GLX_RED_SIZE:
|
|
||||||
case GLX_GREEN_SIZE:
|
|
||||||
case GLX_BLUE_SIZE:
|
|
||||||
case GLX_DEPTH_SIZE:
|
|
||||||
return( 1 );
|
|
||||||
|
|
||||||
case GLX_STENCIL_SIZE:
|
|
||||||
case GLX_ALPHA_SIZE:
|
|
||||||
case GLX_ACCUM_RED_SIZE:
|
|
||||||
case GLX_ACCUM_GREEN_SIZE:
|
|
||||||
case GLX_ACCUM_BLUE_SIZE:
|
|
||||||
case GLX_ACCUM_ALPHA_SIZE:
|
|
||||||
case GLX_STEREO:
|
|
||||||
default:
|
|
||||||
/*
|
|
||||||
* Well, this looks like not implemented to me :)
|
|
||||||
*/
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have the query results returned
|
||||||
|
*/
|
||||||
|
return ( returnValue ) ;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Have the query results returned
|
|
||||||
*/
|
|
||||||
return( returnValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
|
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* General settings assignment method
|
||||||
|
*/
|
||||||
|
void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
|
||||||
|
{
|
||||||
|
freeglut_assert_ready;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check what is the caller querying for. In chronological code add order.
|
||||||
|
*/
|
||||||
|
switch( eWhat )
|
||||||
|
{
|
||||||
|
case GLUT_INIT_WINDOW_X: fgState.Position.X = (GLint)value ;
|
||||||
|
break ;
|
||||||
|
case GLUT_INIT_WINDOW_Y: fgState.Position.Y = (GLint)value ;
|
||||||
|
break ;
|
||||||
|
case GLUT_INIT_WINDOW_WIDTH: fgState.Size.X = (GLint)value ;
|
||||||
|
break ;
|
||||||
|
case GLUT_INIT_WINDOW_HEIGHT: fgState.Size.Y = (GLint)value ;
|
||||||
|
break ;
|
||||||
|
case GLUT_INIT_DISPLAY_MODE: fgState.DisplayMode = (unsigned int)value ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_ACTION_ON_WINDOW_CLOSE: fgState.ActionOnWindowClose = value ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case GLUT_WINDOW_CURSOR:
|
||||||
|
if( fgStructure.Window != NULL ) fgStructure.Window->State.Cursor = value ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* Just have it reported, so that we can see what needs to be implemented
|
||||||
|
*/
|
||||||
|
fgWarning( "glutSetOption(): missing enum handle %i\n", eWhat );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* General settings query method
|
* General settings query method
|
||||||
*/
|
*/
|
||||||
int FGAPIENTRY glutGet( GLenum eWhat )
|
int FGAPIENTRY glutGet( GLenum eWhat )
|
||||||
{
|
{
|
||||||
|
int returnValue ;
|
||||||
|
GLboolean boolValue ;
|
||||||
freeglut_assert_ready;
|
freeglut_assert_ready;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -172,8 +159,9 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||||||
*/
|
*/
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
|
||||||
|
#if TARGET_HOST_UNIX_X11
|
||||||
/*
|
/*
|
||||||
* The rest of GLX queries is general enough to use a macro to check them
|
* The rest of GLX queries under X are general enough to use a macro to check them
|
||||||
*/
|
*/
|
||||||
# define GLX_QUERY(a,b) case a: return( fghGetConfig( b ) );
|
# define GLX_QUERY(a,b) case a: return( fghGetConfig( b ) );
|
||||||
|
|
||||||
@ -194,7 +182,6 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||||||
|
|
||||||
# undef GLX_QUERY
|
# undef GLX_QUERY
|
||||||
|
|
||||||
#if TARGET_HOST_UNIX_X11
|
|
||||||
/*
|
/*
|
||||||
* Colormap size is handled in a bit different way than all the rest
|
* Colormap size is handled in a bit different way than all the rest
|
||||||
*/
|
*/
|
||||||
@ -314,6 +301,60 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||||||
|
|
||||||
#elif TARGET_HOST_WIN32
|
#elif TARGET_HOST_WIN32
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the OpenGL inquiries
|
||||||
|
*/
|
||||||
|
case GLUT_WINDOW_RGBA:
|
||||||
|
glGetBooleanv ( GL_RGBA_MODE, &boolValue ) ; /* True if color buffers store RGBA */
|
||||||
|
returnValue = boolValue ? 1 : 0 ;
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_DOUBLEBUFFER:
|
||||||
|
glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue ) ; /* True if front and back buffers exist */
|
||||||
|
returnValue = boolValue ? 1 : 0 ;
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_STEREO:
|
||||||
|
glGetBooleanv ( GL_STEREO, &boolValue ) ; /* True if left and right buffers exist */
|
||||||
|
returnValue = boolValue ? 1 : 0 ;
|
||||||
|
return ( returnValue ) ;
|
||||||
|
|
||||||
|
case GLUT_WINDOW_RED_SIZE:
|
||||||
|
glGetIntegerv ( GL_RED_BITS, &returnValue ) ; /* Number of bits per red component in color buffers */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_GREEN_SIZE:
|
||||||
|
glGetIntegerv ( GL_GREEN_BITS, &returnValue ) ; /* Number of bits per green component in color buffers */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_BLUE_SIZE:
|
||||||
|
glGetIntegerv ( GL_BLUE_BITS, &returnValue ) ; /* Number of bits per blue component in color buffers */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_ALPHA_SIZE:
|
||||||
|
glGetIntegerv ( GL_ALPHA_BITS, &returnValue ) ; /* Number of bits per alpha component in color buffers */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_ACCUM_RED_SIZE:
|
||||||
|
glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue ) ; /* Number of bits per red component in the accumulation buffer */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_ACCUM_GREEN_SIZE:
|
||||||
|
glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue ) ; /* Number of bits per green component in the accumulation buffer */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_ACCUM_BLUE_SIZE:
|
||||||
|
glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue ) ; /* Number of bits per blue component in the accumulation buffer */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
|
||||||
|
glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue ) ; /* Number of bits per alpha component in the accumulation buffer */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_DEPTH_SIZE:
|
||||||
|
glGetIntegerv ( GL_DEPTH_BITS, &returnValue ) ; /* Number of depth-buffer bitplanes */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
|
||||||
|
case GLUT_WINDOW_BUFFER_SIZE:
|
||||||
|
returnValue = 1 ; /* ????? */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
case GLUT_WINDOW_STENCIL_SIZE:
|
||||||
|
returnValue = 0 ; /* ????? */
|
||||||
|
return ( returnValue ) ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window position and size
|
||||||
|
*/
|
||||||
case GLUT_WINDOW_X:
|
case GLUT_WINDOW_X:
|
||||||
case GLUT_WINDOW_Y:
|
case GLUT_WINDOW_Y:
|
||||||
case GLUT_WINDOW_WIDTH:
|
case GLUT_WINDOW_WIDTH:
|
||||||
@ -411,6 +452,8 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||||||
|
|
||||||
return( fgListLength( &fgStructure.Menu->Entries ) );
|
return( fgListLength( &fgStructure.Menu->Entries ) );
|
||||||
|
|
||||||
|
case GLUT_ACTION_ON_WINDOW_CLOSE: return ( fgState.ActionOnWindowClose ) ;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* Just have it reported, so that we can see what needs to be implemented
|
* Just have it reported, so that we can see what needs to be implemented
|
||||||
|
@ -2,11 +2,14 @@
|
|||||||
/* This file has been automatically generated by the genstroke utility. */
|
/* This file has been automatically generated by the genstroke utility. */
|
||||||
|
|
||||||
#include "../include/GL/freeglut_internal.h"
|
#include "../include/GL/freeglut_internal.h"
|
||||||
|
#ifdef TARGET_HOST_WIN32
|
||||||
|
#pragma warning ( once:4305 )
|
||||||
|
#endif
|
||||||
/* char: 0x20 */
|
/* char: 0x20 */
|
||||||
|
|
||||||
static const SFG_StrokeStrip ch32st[] =
|
static const SFG_StrokeStrip ch32st[] =
|
||||||
{
|
{
|
||||||
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const SFG_StrokeChar ch32 = {104.762,0,ch32st};
|
static const SFG_StrokeChar ch32 = {104.762,0,ch32st};
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
/* This file has been automatically generated by the genstroke utility. */
|
/* This file has been automatically generated by the genstroke utility. */
|
||||||
|
|
||||||
#include "../include/GL/freeglut_internal.h"
|
#include "../include/GL/freeglut_internal.h"
|
||||||
|
#ifdef TARGET_HOST_WIN32
|
||||||
|
#pragma warning ( once:4305 )
|
||||||
|
#endif
|
||||||
|
|
||||||
/* char: 0x20 */
|
/* char: 0x20 */
|
||||||
|
|
||||||
static const SFG_StrokeStrip ch32st[] =
|
static const SFG_StrokeStrip ch32st[] =
|
||||||
{
|
{
|
||||||
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const SFG_StrokeChar ch32 = {104.762,0,ch32st};
|
static const SFG_StrokeChar ch32 = {104.762,0,ch32st};
|
||||||
|
@ -106,7 +106,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
|
|||||||
* Open the window now. The fgOpenWindow() function is system
|
* Open the window now. The fgOpenWindow() function is system
|
||||||
* dependant, and resides in freeglut_window.c. Uses fgState.
|
* dependant, and resides in freeglut_window.c. Uses fgState.
|
||||||
*/
|
*/
|
||||||
fgOpenWindow( window, title, x, y, w, h, gameMode );
|
fgOpenWindow( window, title, x, y, w, h, gameMode, (parent != NULL) ? TRUE : FALSE );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a pointer to the newly created window
|
* Return a pointer to the newly created window
|
||||||
@ -160,7 +160,67 @@ SFG_Menu* fgCreateMenu( FGCBmenu menuCallback )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function destroys a window and all of it's subwindows. Actually,
|
* Linked list of windows to destroy ... this is so we don't destroy a window from the middle of
|
||||||
|
* its callback. Some C compilers take an extremely dim view of this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static SFG_WindowList* WindowsToDestroy = (SFG_WindowList*)NULL ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to add a window to the linked list of windows to destroy. Subwindows are automatically
|
||||||
|
* added because they hang from the window structure.
|
||||||
|
*/
|
||||||
|
void fgAddToWindowDestroyList ( SFG_Window* window, GLboolean needToClose )
|
||||||
|
{
|
||||||
|
SFG_WindowList *new_list_entry = (SFG_WindowList*)malloc ( sizeof(SFG_WindowList) ) ;
|
||||||
|
new_list_entry->window = window ;
|
||||||
|
new_list_entry->needToClose = needToClose ;
|
||||||
|
new_list_entry->next = WindowsToDestroy ;
|
||||||
|
WindowsToDestroy = new_list_entry ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the execution state. If this has been called from "glutDestroyWindow",
|
||||||
|
* a statement in that function will reset the "ExecState" after this function returns.
|
||||||
|
*/
|
||||||
|
if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set the execution state flag to drop out of the main loop.
|
||||||
|
*/
|
||||||
|
if ( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
|
||||||
|
fgState.ExecState = GLUT_EXEC_STATE_STOP ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to close down all the windows in the "WindowsToDestroy" list
|
||||||
|
*/
|
||||||
|
void fgCloseWindows ()
|
||||||
|
{
|
||||||
|
fgExecutionState ExecState = fgState.ExecState ;
|
||||||
|
|
||||||
|
SFG_WindowList *window_ptr = WindowsToDestroy ;
|
||||||
|
WindowsToDestroy = (SFG_WindowList*)NULL ; // In case the destroy callbacks cause more windows to be closed
|
||||||
|
|
||||||
|
while ( window_ptr )
|
||||||
|
{
|
||||||
|
SFG_WindowList *next = window_ptr->next ;
|
||||||
|
fgDestroyWindow ( window_ptr->window, window_ptr->needToClose ) ;
|
||||||
|
free ( window_ptr ) ;
|
||||||
|
window_ptr = next ;
|
||||||
|
|
||||||
|
if ( !window_ptr ) window_ptr = WindowsToDestroy ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since the "fgDestroyWindow" function could easily have set the "ExecState" to stop,
|
||||||
|
* let's set it back to what it was.
|
||||||
|
*/
|
||||||
|
fgState.ExecState = ExecState ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function destroys a window and all of its subwindows. Actually,
|
||||||
* another function, defined in freeglut_window.c is called, but this is
|
* another function, defined in freeglut_window.c is called, but this is
|
||||||
* a whole different story...
|
* a whole different story...
|
||||||
*/
|
*/
|
||||||
@ -174,19 +234,25 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
|
|||||||
/*
|
/*
|
||||||
* Does this window have any subwindows?
|
* Does this window have any subwindows?
|
||||||
*/
|
*/
|
||||||
if( (subWindow = window->Children.First) != NULL )
|
while ( (subWindow = window->Children.First) != NULL )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Destroy the first window in the list (possibly destroying
|
* Destroy the first window in the list (possibly destroying
|
||||||
* it's subwindows too). This is not very effective, but works
|
* its subwindows too). This is not very effective, but works
|
||||||
*/
|
*/
|
||||||
fgDestroyWindow( subWindow, TRUE );
|
fgDestroyWindow( subWindow, needToClose );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we should remove the reference to this window from it's parent
|
* If the programmer defined a destroy callback, call it
|
||||||
*/
|
*/
|
||||||
if( window->Parent != NULL )
|
if ( window->Callbacks.Destroy != NULL )
|
||||||
|
window->Callbacks.Destroy () ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we should remove the reference to this window from its parent
|
||||||
|
*/
|
||||||
|
if ( window->Parent != NULL )
|
||||||
fgListRemove( &window->Parent->Children, &window->Node );
|
fgListRemove( &window->Parent->Children, &window->Node );
|
||||||
else
|
else
|
||||||
fgListRemove( &fgStructure.Windows, &window->Node );
|
fgListRemove( &fgStructure.Windows, &window->Node );
|
||||||
@ -212,7 +278,7 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a helper static function that removes a menu (given it's pointer)
|
* This is a helper static function that removes a menu (given its pointer)
|
||||||
* from any windows that can be accessed from a given parent...
|
* from any windows that can be accessed from a given parent...
|
||||||
*/
|
*/
|
||||||
static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu )
|
static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu )
|
||||||
@ -246,15 +312,15 @@ static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu )
|
|||||||
*/
|
*/
|
||||||
static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu )
|
static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu )
|
||||||
{
|
{
|
||||||
SFG_MenuEntry *entry;
|
SFG_MenuEntry *entry;
|
||||||
|
|
||||||
for( entry = from->Entries.First; entry; entry = entry->Node.Next )
|
for( entry = from->Entries.First; entry; entry = entry->Node.Next )
|
||||||
|
{
|
||||||
|
if (entry->SubMenu == menu)
|
||||||
{
|
{
|
||||||
if (entry->SubMenu == menu)
|
entry->SubMenu = NULL;
|
||||||
{
|
|
||||||
entry->SubMenu = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -263,64 +329,63 @@ static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu )
|
|||||||
*/
|
*/
|
||||||
void fgDestroyMenu( SFG_Menu* menu )
|
void fgDestroyMenu( SFG_Menu* menu )
|
||||||
{
|
{
|
||||||
SFG_Window *window;
|
SFG_Window *window;
|
||||||
SFG_Menu *from;
|
SFG_Menu *from;
|
||||||
SFG_MenuEntry *entry;
|
SFG_MenuEntry *entry;
|
||||||
|
|
||||||
assert( menu != NULL );
|
assert( menu != NULL );
|
||||||
freeglut_assert_ready;
|
freeglut_assert_ready;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First of all, have all references to this menu removed from all windows:
|
||||||
|
*/
|
||||||
|
for( window = fgStructure.Windows.First; window; window = window->Node.Next )
|
||||||
|
{
|
||||||
|
fghRemoveMenuFromWindow( window, menu );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now proceed with removing menu entries that lead to this menu
|
||||||
|
*/
|
||||||
|
for( from = fgStructure.Menus.First; from; from = from->Node.Next )
|
||||||
|
{
|
||||||
|
fghRemoveMenuFromMenu( from, menu );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we are pretty sure the menu is not used anywhere
|
||||||
|
* and that we can remove all of its entries
|
||||||
|
*/
|
||||||
|
while( (entry = menu->Entries.First) != NULL )
|
||||||
|
{
|
||||||
|
fgListRemove(&menu->Entries, &entry->Node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First of all, have all references to this menu removed from all windows:
|
* There might be a string allocated, have it freed:
|
||||||
*/
|
*/
|
||||||
for( window = fgStructure.Windows.First; window;
|
free( entry->Text );
|
||||||
window = window->Node.Next )
|
|
||||||
{
|
|
||||||
fghRemoveMenuFromWindow( window, menu );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now proceed with removing menu entries that lead to this menu
|
* Deallocate the entry itself:
|
||||||
*/
|
*/
|
||||||
for( from = fgStructure.Menus.First; from; from = from->Node.Next )
|
free( entry );
|
||||||
{
|
}
|
||||||
fghRemoveMenuFromMenu( from, menu );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we are pretty sure the menu is not used anywhere
|
* Remove the menu from the menus list
|
||||||
* and that we can remove all of it's entries
|
*/
|
||||||
*/
|
fgListRemove( &fgStructure.Menus, &menu->Node );
|
||||||
while( (entry = menu->Entries.First) != NULL )
|
|
||||||
{
|
|
||||||
fgListRemove(&menu->Entries, &entry->Node);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There might be a string allocated, have it freed:
|
* If that menu was the current one...
|
||||||
*/
|
*/
|
||||||
free( entry->Text );
|
if( fgStructure.Menu == menu )
|
||||||
|
fgStructure.Menu = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocate the entry itself:
|
* Have the menu structure freed
|
||||||
*/
|
*/
|
||||||
free( entry );
|
free( menu );
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove the menu from the menus list
|
|
||||||
*/
|
|
||||||
fgListRemove( &fgStructure.Menus, &menu->Node );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If that menu was the current one...
|
|
||||||
*/
|
|
||||||
if( fgStructure.Menu == menu )
|
|
||||||
fgStructure.Menu = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Have the menu structure freed
|
|
||||||
*/
|
|
||||||
free( menu );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -331,14 +396,14 @@ void fgDestroyMenu( SFG_Menu* menu )
|
|||||||
*/
|
*/
|
||||||
void fgCreateStructure( void )
|
void fgCreateStructure( void )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We will be needing two lists: the first containing windows,
|
* We will be needing two lists: the first containing windows,
|
||||||
* and the second containing the user-defined menus.
|
* and the second containing the user-defined menus.
|
||||||
* Also, no current window/menu is set, as none has been created yet.
|
* Also, no current window/menu is set, as none has been created yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fgListInit(&fgStructure.Windows);
|
fgListInit(&fgStructure.Windows);
|
||||||
fgListInit(&fgStructure.Menus);
|
fgListInit(&fgStructure.Menus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -347,22 +412,22 @@ void fgCreateStructure( void )
|
|||||||
*/
|
*/
|
||||||
void fgDestroyStructure( void )
|
void fgDestroyStructure( void )
|
||||||
{
|
{
|
||||||
SFG_Window *window;
|
SFG_Window *window;
|
||||||
SFG_Menu *menu;
|
SFG_Menu *menu;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Just make sure we are not called in vain...
|
* Just make sure we are not called in vain...
|
||||||
*/
|
*/
|
||||||
freeglut_assert_ready;
|
freeglut_assert_ready;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure all windows and menus have been deallocated
|
* Make sure all windows and menus have been deallocated
|
||||||
*/
|
*/
|
||||||
while( (window = fgStructure.Windows.First) != NULL )
|
while( (window = fgStructure.Windows.First) != NULL )
|
||||||
fgDestroyWindow( window, TRUE );
|
fgDestroyWindow( window, TRUE );
|
||||||
|
|
||||||
while( (menu = fgStructure.Menus.First) != NULL )
|
while( (menu = fgStructure.Menus.First) != NULL )
|
||||||
fgDestroyMenu( menu );
|
fgDestroyMenu( menu );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -370,28 +435,28 @@ void fgDestroyStructure( void )
|
|||||||
*/
|
*/
|
||||||
void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
|
void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
|
||||||
{
|
{
|
||||||
SFG_Window *window;
|
SFG_Window *window;
|
||||||
|
|
||||||
assert( (enumCallback != NULL) && (enumerator != NULL) );
|
assert( (enumCallback != NULL) && (enumerator != NULL) );
|
||||||
freeglut_assert_ready;
|
freeglut_assert_ready;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check every of the top-level windows
|
||||||
|
*/
|
||||||
|
for( window = fgStructure.Windows.First; window;
|
||||||
|
window = window->Node.Next )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Execute the callback...
|
||||||
|
*/
|
||||||
|
enumCallback( window, enumerator );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check every of the top-level windows
|
* If it has been marked as 'found', stop searching
|
||||||
*/
|
*/
|
||||||
for( window = fgStructure.Windows.First; window;
|
if( enumerator->found == TRUE )
|
||||||
window = window->Node.Next )
|
return;
|
||||||
{
|
}
|
||||||
/*
|
|
||||||
* Execute the callback...
|
|
||||||
*/
|
|
||||||
enumCallback( window, enumerator );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If it has been marked as 'found', stop searching
|
|
||||||
*/
|
|
||||||
if( enumerator->found == TRUE )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -399,31 +464,31 @@ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
|
|||||||
*/
|
*/
|
||||||
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
|
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
|
||||||
{
|
{
|
||||||
SFG_Window *child;
|
SFG_Window *child;
|
||||||
|
|
||||||
assert( (enumCallback != NULL) && (enumerator != NULL) );
|
assert( (enumCallback != NULL) && (enumerator != NULL) );
|
||||||
freeglut_assert_ready;
|
freeglut_assert_ready;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check every of the window's children:
|
||||||
|
*/
|
||||||
|
for( child = window->Children.First; child; child = child->Node.Next )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Execute the callback...
|
||||||
|
*/
|
||||||
|
enumCallback( child, enumerator );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check every of the window's children:
|
* If it has been marked as 'found', stop searching
|
||||||
*/
|
*/
|
||||||
for( child = window->Children.First; child; child = child->Node.Next )
|
if( enumerator->found == TRUE )
|
||||||
{
|
return;
|
||||||
/*
|
}
|
||||||
* Execute the callback...
|
|
||||||
*/
|
|
||||||
enumCallback( child, enumerator );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If it has been marked as 'found', stop searching
|
|
||||||
*/
|
|
||||||
if( enumerator->found == TRUE )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A static helper function to look for a window given it's handle
|
* A static helper function to look for a window given its handle
|
||||||
*/
|
*/
|
||||||
static void fghcbWindowByHandle( SFG_Window *window, SFG_Enumerator *enumerator )
|
static void fghcbWindowByHandle( SFG_Window *window, SFG_Enumerator *enumerator )
|
||||||
{
|
{
|
||||||
@ -495,7 +560,7 @@ SFG_Window* fgWindowByHandle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A static helper function to look for a window given it's ID
|
* A static helper function to look for a window given its ID
|
||||||
*/
|
*/
|
||||||
static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator )
|
static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator )
|
||||||
{
|
{
|
||||||
@ -554,7 +619,7 @@ SFG_Window* fgWindowByID( int windowID )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Looks up a menu given it's ID. This is easier that fgWindowByXXX
|
* Looks up a menu given its ID. This is easier that fgWindowByXXX
|
||||||
* as all menus are placed in a single doubly linked list...
|
* as all menus are placed in a single doubly linked list...
|
||||||
*/
|
*/
|
||||||
SFG_Menu* fgMenuByID( int menuID )
|
SFG_Menu* fgMenuByID( int menuID )
|
||||||
|
@ -258,8 +258,13 @@ GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly )
|
|||||||
pfd.cAccumGreenBits = 0;
|
pfd.cAccumGreenBits = 0;
|
||||||
pfd.cAccumBlueBits = 0;
|
pfd.cAccumBlueBits = 0;
|
||||||
pfd.cAccumAlphaBits = 0;
|
pfd.cAccumAlphaBits = 0;
|
||||||
|
#if 0
|
||||||
pfd.cDepthBits = 32;
|
pfd.cDepthBits = 32;
|
||||||
pfd.cStencilBits = 0;
|
pfd.cStencilBits = 0;
|
||||||
|
#else
|
||||||
|
pfd.cDepthBits = 24;
|
||||||
|
pfd.cStencilBits = 8;
|
||||||
|
#endif
|
||||||
pfd.cAuxBuffers = 0;
|
pfd.cAuxBuffers = 0;
|
||||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||||
pfd.bReserved = 0;
|
pfd.bReserved = 0;
|
||||||
@ -300,7 +305,7 @@ GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly )
|
|||||||
* Opens a window. Requires a SFG_Window object created and attached
|
* Opens a window. Requires a SFG_Window object created and attached
|
||||||
* to the freeglut structure. OpenGL context is created here.
|
* to the freeglut structure. OpenGL context is created here.
|
||||||
*/
|
*/
|
||||||
void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, int h, GLboolean gameMode )
|
void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, int h, GLboolean gameMode, int isSubWindow )
|
||||||
{
|
{
|
||||||
#if TARGET_HOST_UNIX_X11
|
#if TARGET_HOST_UNIX_X11
|
||||||
XSetWindowAttributes winAttr;
|
XSetWindowAttributes winAttr;
|
||||||
@ -471,7 +476,6 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
|
|||||||
WNDCLASS wc;
|
WNDCLASS wc;
|
||||||
int flags;
|
int flags;
|
||||||
ATOM atom;
|
ATOM atom;
|
||||||
HWND hWnd;
|
|
||||||
|
|
||||||
freeglut_assert_ready;
|
freeglut_assert_ready;
|
||||||
|
|
||||||
@ -483,15 +487,20 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
|
|||||||
|
|
||||||
if( gameMode == FALSE )
|
if( gameMode == FALSE )
|
||||||
{
|
{
|
||||||
|
if ( !isSubWindow )
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Update the window position and dimensions, taking account of window decorations
|
* Update the window position and dimensions, taking account of window decorations
|
||||||
*/
|
*/
|
||||||
x -= (GetSystemMetrics( SM_CXSIZEFRAME ) - 1);
|
|
||||||
y -= (GetSystemMetrics( SM_CYSIZEFRAME ) - 1);
|
|
||||||
w += (GetSystemMetrics( SM_CXSIZEFRAME ) - 1)*2;
|
|
||||||
h += (GetSystemMetrics( SM_CYSIZEFRAME ) - 1)*2 + GetSystemMetrics( SM_CYCAPTION );
|
|
||||||
|
|
||||||
/*
|
x -= (GetSystemMetrics( SM_CXSIZEFRAME ) );
|
||||||
|
y -= (GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) );
|
||||||
|
if ( y < 0 ) y = 0 ;
|
||||||
|
w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
|
||||||
|
h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 + GetSystemMetrics( SM_CYCAPTION );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
* Check if the user wants us to use the default position/size
|
* Check if the user wants us to use the default position/size
|
||||||
*/
|
*/
|
||||||
if( fgState.Position.Use == FALSE ) { x = CW_USEDEFAULT; y = CW_USEDEFAULT; }
|
if( fgState.Position.Use == FALSE ) { x = CW_USEDEFAULT; y = CW_USEDEFAULT; }
|
||||||
@ -600,7 +609,7 @@ void fgCloseWindow( SFG_Window* window )
|
|||||||
int FGAPIENTRY glutCreateWindow( const char* title )
|
int FGAPIENTRY glutCreateWindow( const char* title )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Create a new window and return it's unique ID number
|
* Create a new window and return its unique ID number
|
||||||
*/
|
*/
|
||||||
return( fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y,
|
return( fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y,
|
||||||
fgState.Size.X, fgState.Size.Y, FALSE )->ID );
|
fgState.Size.X, fgState.Size.Y, FALSE )->ID );
|
||||||
@ -638,7 +647,7 @@ int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Destroys a window and all of it's subwindows
|
* Destroys a window and all of its subwindows
|
||||||
*/
|
*/
|
||||||
void FGAPIENTRY glutDestroyWindow( int windowID )
|
void FGAPIENTRY glutDestroyWindow( int windowID )
|
||||||
{
|
{
|
||||||
@ -652,7 +661,7 @@ void FGAPIENTRY glutDestroyWindow( int windowID )
|
|||||||
* There is a function that performs all needed steps
|
* There is a function that performs all needed steps
|
||||||
* defined in freeglut_structure.c. Let's use it:
|
* defined in freeglut_structure.c. Let's use it:
|
||||||
*/
|
*/
|
||||||
fgDestroyWindow( window, TRUE );
|
fgAddToWindowDestroyList( window, TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -955,19 +964,37 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
|
|||||||
#elif TARGET_HOST_WIN32
|
#elif TARGET_HOST_WIN32
|
||||||
{
|
{
|
||||||
RECT winRect;
|
RECT winRect;
|
||||||
|
int x, y ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First off, grab the current window's position
|
* First off, grab the current window's position
|
||||||
*/
|
*/
|
||||||
GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
|
GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
|
||||||
|
x = winRect.left ;
|
||||||
|
y = winRect.top ;
|
||||||
|
|
||||||
|
if ( fgStructure.Window->Parent == NULL ) /* If this is not a subwindow ... */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Adjust the size of the window to allow for the size of the frame
|
||||||
|
*/
|
||||||
|
width += (GetSystemMetrics( SM_CXSIZEFRAME ) - 1)*2;
|
||||||
|
height += (GetSystemMetrics( SM_CYSIZEFRAME ) - 1)*2 + GetSystemMetrics( SM_CYCAPTION );
|
||||||
|
}
|
||||||
|
else /* This is a subwindow, get the parent window's position and subtract it off */
|
||||||
|
{
|
||||||
|
GetWindowRect ( fgStructure.Window->Parent->Window.Handle, &winRect ) ;
|
||||||
|
x -= winRect.left + GetSystemMetrics( SM_CXSIZEFRAME ) ;
|
||||||
|
y -= winRect.top + GetSystemMetrics( SM_CXSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) ;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resize the window, forcing a redraw to happen
|
* Resize the window, forcing a redraw to happen
|
||||||
*/
|
*/
|
||||||
MoveWindow(
|
MoveWindow(
|
||||||
fgStructure.Window->Window.Handle,
|
fgStructure.Window->Window.Handle,
|
||||||
winRect.left,
|
x,
|
||||||
winRect.top,
|
y,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
TRUE
|
TRUE
|
||||||
@ -999,7 +1026,17 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
|
|||||||
*/
|
*/
|
||||||
GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
|
GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
|
||||||
|
|
||||||
/*
|
if ( fgStructure.Window->Parent == NULL ) /* If this is not a subwindow ... */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Adjust the position of the window to allow for the size of the frame
|
||||||
|
*/
|
||||||
|
x -= (GetSystemMetrics( SM_CXSIZEFRAME ) - 1);
|
||||||
|
y -= (GetSystemMetrics( SM_CYSIZEFRAME ) - 1 + GetSystemMetrics( SM_CYCAPTION ));
|
||||||
|
if ( y < 0 ) y = 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
* Reposition the window, forcing a redraw to happen
|
* Reposition the window, forcing a redraw to happen
|
||||||
*/
|
*/
|
||||||
MoveWindow(
|
MoveWindow(
|
||||||
|
Reference in New Issue
Block a user