/* * Changes the specified menu item in the current menu into a sub-menu trigger. */ void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int subMenuID ) { SFG_Menu* subMenu; SFG_MenuEntry* menuEntry; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToSubMenu" ); freeglut_return_if_fail( fgStructure.CurrentMenu ); if (fgGetActiveMenu()) fgError("Menu manipulation not allowed while menus in use."); /* Get handle to sub menu */ subMenu = fgMenuByID( subMenuID ); menuEntry = NULL; freeglut_return_if_fail( subMenu ); /* Get n-th menu entry in the current menu, starting from one: */ menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); freeglut_return_if_fail( menuEntry ); /* We want it to become a sub menu entry, so: */ if( menuEntry->Text ) free( menuEntry->Text ); menuEntry->Text = strdup( label ); menuEntry->SubMenu = subMenu; menuEntry->ID = -1; fghCalculateMenuBoxSize( ); }
/* * Draw a bitmap character */ void FGAPIENTRY glutBitmapCharacter( void* fontID, int character ) { const GLubyte* face; SFG_Font* font; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapCharacter" ); font = fghFontByID( fontID ); freeglut_return_if_fail( ( character >= 1 )&&( character < 256 ) ); freeglut_return_if_fail( font ); /* * Find the character we want to draw (???) */ face = font->Characters[ character ]; glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT ); 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 ); glBitmap( face[ 0 ], font->Height, /* The bitmap's width and height */ font->xorig, font->yorig, /* The origin in the font glyph */ ( float )( face[ 0 ] ), 0.0, /* The raster advance -- inc. x,y */ ( face + 1 ) /* The packed bitmap data... */ ); glPopClientAttrib( ); }
/* * Changes the specified menu item in the current menu into a sub-menu trigger. */ void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int subMenuID ) { SFG_Menu* subMenu = fgMenuByID( subMenuID ); SFG_MenuEntry* menuEntry = NULL; freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu ); freeglut_return_if_fail( subMenu ); /* * Get n-th menu entry in the current menu, starting from one: */ menuEntry = fghFindMenuEntry( fgStructure.Menu, item ); freeglut_return_if_fail( menuEntry ); /* * We want it to become a sub menu entry, so: */ if( menuEntry->Text ) free( menuEntry->Text ); menuEntry->Text = strdup( label ); menuEntry->SubMenu = subMenu; menuEntry->ID = -1; fghCalculateMenuBoxSize( ); }
/* * Draw a stroke character */ void FGAPIENTRY glutStrokeCharacter( void* fontID, int character ) { const SFG_StrokeChar *schar; const SFG_StrokeStrip *strip; int i, j; SFG_StrokeFont* font; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeCharacter" ); font = fghStrokeByID( fontID ); freeglut_return_if_fail( character >= 0 ); freeglut_return_if_fail( character < font->Quantity ); freeglut_return_if_fail( font ); 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( ); glBegin( GL_POINTS ); for( j = 0; j < strip->Number; j++ ) glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y ); glEnd( ); } glTranslatef( schar->Right, 0.0, 0.0 ); }
/* * Draw a stroke character */ void FGAPIENTRY glutStrokeCharacter( void* fontID, int character ) { const SFG_StrokeChar *schar; const SFG_StrokeStrip *strip; int i; SFG_StrokeFont* font; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeCharacter" ); font = fghStrokeByID( fontID ); if (!font) { fgWarning("glutStrokeCharacter: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n",fontID); return; } freeglut_return_if_fail( character >= 0 ); freeglut_return_if_fail( character < font->Quantity ); schar = font->Characters[ character ]; freeglut_return_if_fail( schar ); strip = schar->Strips; for( i = 0; i < schar->Number; i++, strip++ ) { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &strip->Vertices[0].X); glDrawArrays(GL_LINE_STRIP, 0, strip->Number); glDisableClientState(GL_VERTEX_ARRAY); } glTranslatef( schar->Right, 0.0, 0.0 ); }
/* * Forces the joystick callback to be executed */ void FGAPIENTRY glutForceJoystickFunc( void ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutForceJoystickFunc" ); #if !TARGET_HOST_WINCE freeglut_return_if_fail( fgStructure.CurrentWindow != NULL ); freeglut_return_if_fail( FETCH_WCB( *( fgStructure.CurrentWindow ), Joystick ) ); fgJoystickPollWindow( fgStructure.CurrentWindow ); #endif /* !TARGET_HOST_WINCE */ }
/* * Detaches a menu from the current window */ void FGAPIENTRY glutDetachMenu( int button ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDetachMenu" ); freeglut_return_if_fail( fgStructure.CurrentWindow ); freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( button >= 0 ); freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); fgStructure.CurrentWindow->Menu[ button ] = NULL; }
/* * Detaches a menu from the current window */ void FGAPIENTRY glutDetachMenu( int button ) { freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Window ); freeglut_return_if_fail( fgStructure.Menu ); freeglut_return_if_fail( button >= 0 ); freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); fgStructure.Window->Menu[ button ] = NULL; }
/* * Detaches a menu from the current window */ void FGAPIENTRY glutDetachMenu( int button ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDetachMenu" ); freeglut_return_if_fail( fgStructure.CurrentWindow ); freeglut_return_if_fail( fgStructure.CurrentMenu ); if (fgGetActiveMenu()) fgError("Menu manipulation not allowed while menus in use."); freeglut_return_if_fail( button >= 0 ); freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); fgStructure.CurrentWindow->Menu[ button ] = NULL; }
/* Gets the rect describing the client area (drawable area) of the * specified window. Output is position of corners of client area (drawable area) on the screen. * Returns an empty rect if window pointer or window handle is NULL. * If wantPosOutside is set to true, the output client Rect * will follow freeGLUT's window specification convention in which the * top-left corner is at the outside of the window, while the size * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable * area. */ void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside ) { POINT topLeftClient = {0,0}; POINT topLeftWindow = {0,0}; freeglut_return_if_fail((window && window->Window.Handle)); /* * call GetWindowRect() * (this returns the pixel coordinates of the outside of the window) * cannot use GetClientRect as it returns a rect relative to * the top-left point of the client area (.top and .left are thus always 0) * and is thus only useful for querying the size of the client area, not * its position. */ GetWindowRect( window->Window.Handle, clientRect ); topLeftWindow.x = clientRect->top; topLeftWindow.y = clientRect->left; /* Get size of client rect */ GetClientRect(window->Window.Handle, clientRect); /* Get position of top-left of client area on the screen */ ClientToScreen(window->Window.Handle,&topLeftClient); /* Add top-left offset */ OffsetRect(clientRect,topLeftClient.x,topLeftClient.y); /* replace top and left with top and left of window, if wanted */ if (wantPosOutside) { clientRect->left = topLeftWindow.x; clientRect->top = topLeftWindow.y; } }
/* * Attaches a menu to the current window */ void FGAPIENTRY glutAttachMenu( int button ) { freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Window ); freeglut_return_if_fail( fgStructure.Menu ); freeglut_return_if_fail( button >= 0 ); freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); fgStructure.Window->Menu[ button ] = fgStructure.Menu; /* * Make the parent window of the menu (and all submenus) the current window */ fghSetSubmenuParentWindow( fgStructure.Window, fgStructure.Menu ); }
/* * Mark appropriate window to be displayed */ void FGAPIENTRY glutPostWindowRedisplay( int windowID ) { SFG_Window* window; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPostWindowRedisplay" ); window = fgWindowByID( windowID ); freeglut_return_if_fail( window ); window->State.WorkMask |= GLUT_DISPLAY_WORK; }
/* * Sets the current menu given its menu ID */ void FGAPIENTRY glutSetMenu( int menuID ) { SFG_Menu* menu = fgMenuByID( menuID ); freeglut_assert_ready; freeglut_return_if_fail( menu ); fgStructure.Menu = menu; }
/* * Mark appropriate window to be displayed */ void FGAPIENTRY glutPostWindowRedisplay( int windowID ) { SFG_Window* window; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPostWindowRedisplay" ); window = fgWindowByID( windowID ); freeglut_return_if_fail( window ); window->State.Redisplay = GL_TRUE; }
/* * Calls a window's redraw method. This is used when * a redraw is forced by the incoming window messages. */ void fghRedrawWindow ( SFG_Window *window ) { SFG_Window *current_window = fgStructure.CurrentWindow; freeglut_return_if_fail( window ); if( window->State.NeedToInitContext ) { INVOKE_WCB( *window, InitContext, ()); window->State.NeedToInitContext = GL_FALSE; }
/* * Destroys a window and all of its subwindows */ void FGAPIENTRY glutDestroyWindow( int windowID ) { SFG_Window* window = fgWindowByID( windowID ); freeglut_return_if_fail( window != NULL ); { fgExecutionState ExecState = fgState.ExecState; fgAddToWindowDestroyList( window ); fgState.ExecState = ExecState; } }
/* * Add a sub menu to the bottom of the current menu */ void FGAPIENTRY glutAddSubMenu( const char *label, int subMenuID ) { SFG_MenuEntry *menuEntry; SFG_Menu *subMenu; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAddSubMenu" ); menuEntry = ( SFG_MenuEntry * )calloc( sizeof( SFG_MenuEntry ), 1 ); subMenu = fgMenuByID( subMenuID ); freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( subMenu ); menuEntry->Text = strdup( label ); menuEntry->SubMenu = subMenu; menuEntry->ID = -1; fgListAppend( &fgStructure.CurrentMenu->Entries, &menuEntry->Node ); fghCalculateMenuBoxSize( ); }
/* * Removes the specified menu item from the current menu */ void FGAPIENTRY glutRemoveMenuItem( int item ) { SFG_MenuEntry* menuEntry; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutRemoveMenuItem" ); freeglut_return_if_fail( fgStructure.CurrentMenu ); /* Get n-th menu entry in the current menu, starting from one: */ menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); freeglut_return_if_fail( menuEntry ); fgListRemove( &fgStructure.CurrentMenu->Entries, &menuEntry->Node ); if ( menuEntry->Text ) free( menuEntry->Text ); free( menuEntry ); fghCalculateMenuBoxSize( ); }
/* * Sets the current menu given its menu ID */ void FGAPIENTRY glutSetMenu( int menuID ) { SFG_Menu* menu; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetMenu" ); menu = fgMenuByID( menuID ); freeglut_return_if_fail( menu ); fgStructure.CurrentMenu = menu; }
/* * Sets the Visibility callback for the current window. */ static void fghVisibility( int status ) { int glut_status = GLUT_VISIBLE; FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" ); freeglut_return_if_fail( fgStructure.CurrentWindow ); if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) ) glut_status = GLUT_NOT_VISIBLE; INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( glut_status ) ); }
/* * Destroys a window and all of its subwindows */ void FGAPIENTRY glutDestroyWindow( int windowID ) { SFG_Window* window; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" ); window = fgWindowByID( windowID ); freeglut_return_if_fail( window != NULL ); { fgExecutionState ExecState = fgState.ExecState; fgAddToWindowDestroyList( window ); fgState.ExecState = ExecState; } }
/* * Destroys a menu object, removing all references to it */ void FGAPIENTRY glutDestroyMenu( int menuID ) { SFG_Menu* menu; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyMenu" ); menu = fgMenuByID( menuID ); freeglut_return_if_fail( menu ); /* The menu object destruction code resides in freeglut_structure.c */ fgDestroyMenu( menu ); }
/* * Destroys a menu object, removing all references to it */ void FGAPIENTRY glutDestroyMenu( int menuID ) { SFG_Menu* menu = fgMenuByID( menuID ); freeglut_assert_ready; freeglut_return_if_fail( menu ); /* * The menu object destruction code resides in freeglut_structure.c */ fgDestroyMenu( menu ); }
/* * Changes the specified menu item in the current menu into a menu entry */ void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value ) { SFG_MenuEntry* menuEntry = NULL; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToMenuEntry" ); freeglut_return_if_fail( fgStructure.CurrentMenu ); /* Get n-th menu entry in the current menu, starting from one: */ menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); freeglut_return_if_fail( menuEntry ); /* We want it to become a normal menu entry, so: */ if( menuEntry->Text ) free( menuEntry->Text ); menuEntry->Text = strdup( label ); menuEntry->ID = value; menuEntry->SubMenu = NULL; fghCalculateMenuBoxSize( ); }
/* * Removes the specified menu item from the current menu */ void FGAPIENTRY glutRemoveMenuItem( int item ) { SFG_MenuEntry* menuEntry; freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu ); /* * Get n-th menu entry in the current menu, starting from one: */ menuEntry = fghFindMenuEntry( fgStructure.Menu, item ); freeglut_return_if_fail( menuEntry ); fgListRemove( &fgStructure.Menu->Entries, &menuEntry->Node ); if ( menuEntry->Text ) free( menuEntry->Text ); free( menuEntry ); fghCalculateMenuBoxSize( ); }
/* * Add a sub menu to the bottom of the current menu */ void FGAPIENTRY glutAddSubMenu( const char *label, int subMenuID ) { SFG_MenuEntry *menuEntry = ( SFG_MenuEntry * )calloc( sizeof( SFG_MenuEntry ), 1 ); SFG_Menu *subMenu = fgMenuByID( subMenuID ); freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu ); freeglut_return_if_fail( subMenu ); menuEntry->Text = strdup( label ); menuEntry->SubMenu = subMenu; menuEntry->ID = -1; /* * Make the submenu's parent window be the menu's parent window */ fghSetSubmenuParentWindow( fgStructure.Menu->ParentWindow, subMenu ); fgListAppend( &fgStructure.Menu->Entries, &menuEntry->Node ); fghCalculateMenuBoxSize( ); }
/* Gets the rect describing the client area (drawable area) of the * specified window. Output is position of corners of client area (drawable area) on the screen. * Does not touch clientRect if window pointer or window handle is NULL. * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable area. */ void fghGetClientArea( RECT *clientRect, const SFG_Window *window ) { POINT topLeftClient = {0,0}; freeglut_return_if_fail((window && window->Window.Handle)); /* Get size of client rect */ GetClientRect(window->Window.Handle, clientRect); /* Get position of top-left of client area on the screen */ ClientToScreen(window->Window.Handle,&topLeftClient); /* Add top-left offset */ OffsetRect(clientRect,topLeftClient.x,topLeftClient.y); }
/* * Recalculates current menu's box size */ void fghCalculateMenuBoxSize( void ) { SFG_MenuEntry* menuEntry; int width = 0, height = 0; /* * Make sure there is a current menu set */ freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu ); /* * The menu's box size depends on the menu entries: */ for( menuEntry = ( SFG_MenuEntry * )fgStructure.Menu->Entries.First; menuEntry; menuEntry = ( SFG_MenuEntry * )menuEntry->Node.Next ) { /* * Update the menu entry's width value */ menuEntry->Width = glutBitmapLength( FREEGLUT_MENU_FONT, (unsigned char *)menuEntry->Text ); /* * If the entry is a submenu, then it needs to be wider to * accomodate the arrow. JCJ 31 July 2003 */ if (menuEntry->SubMenu ) menuEntry->Width += glutBitmapLength( FREEGLUT_MENU_FONT, (unsigned char *)"_" ); /* * Check if it's the biggest we've found */ if( menuEntry->Width > width ) width = menuEntry->Width; height += FREEGLUT_MENU_HEIGHT; } /* * Store the menu's box size now: */ fgStructure.Menu->Height = height + 2 * FREEGLUT_MENU_BORDER; fgStructure.Menu->Width = width + 4 * FREEGLUT_MENU_BORDER; }
/* * Displays the currently active menu for the current window */ void fgDisplayMenu( void ) { SFG_Window* window = fgStructure.Window; SFG_Menu* menu = NULL; freeglut_assert_window; /* * Check if there is an active menu attached to this window... */ menu = window->ActiveMenu; freeglut_return_if_fail( menu ); fgSetWindow( menu->Window ); glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT ); glDisable( GL_DEPTH_TEST ); glDisable( GL_TEXTURE_2D ); glDisable( GL_LIGHTING ); glDisable( GL_CULL_FACE ); glMatrixMode( GL_PROJECTION ); glPushMatrix( ); glLoadIdentity( ); glOrtho( 0, glutGet( GLUT_WINDOW_WIDTH ), glutGet( GLUT_WINDOW_HEIGHT ), 0, -1, 1 ); glMatrixMode( GL_MODELVIEW ); glPushMatrix( ); glLoadIdentity( ); fghCheckMenuStatus( window, menu ); fghDisplayMenuBox( menu ); glPopAttrib( ); glMatrixMode( GL_PROJECTION ); glPopMatrix( ); glMatrixMode( GL_MODELVIEW ); glPopMatrix( ); glutSwapBuffers( ); fgSetWindow ( window ); }
/* * Destroys a menu object, removing all references to it */ void FGAPIENTRY glutDestroyMenu( int menuID ) { SFG_Menu* menu; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyMenu" ); menu = fgMenuByID( menuID ); freeglut_return_if_fail( menu ); if (fgState.ActiveMenus) fgError("Menu manipulation not allowed while menus in use."); /* The menu object destruction code resides in freeglut_structure.c */ fgDestroyMenu( menu ); }