X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_init.c;h=5fabb611160817af7c06fe3283569ef862131bee;hb=074fe7a4ceb20811af83f735d5db74d69d11442c;hp=9949138ddb535d7bc341987903e6dcad08c1f9ea;hpb=e4aeaead5b7292e16223ed828b6ba4bc897e80c8;p=freeglut diff --git a/src/freeglut_init.c b/src/freeglut_init.c index 9949138..5fabb61 100644 --- a/src/freeglut_init.c +++ b/src/freeglut_init.c @@ -29,19 +29,19 @@ #include "config.h" #endif -#define G_LOG_DOMAIN "freeglut-init" - #include "../include/GL/freeglut.h" #include "freeglut_internal.h" /* * TODO BEFORE THE STABLE RELEASE: * - * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific deinitialization done + * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific + * deinitialization done * glutInitDisplayString() -- display mode string parsing * - * Wouldn't it be cool to use gettext() for error messages? I just love bash saying - * "nie znaleziono pliku" instead of "file not found" :) Is gettext easily portable? + * Wouldn't it be cool to use gettext() for error messages? I just love + * bash saying "nie znaleziono pliku" instead of "file not found" :) + * Is gettext easily portable? */ /* -- GLOBAL VARIABLES ----------------------------------------------------- */ @@ -55,35 +55,36 @@ SFG_Display fgDisplay; /* * The settings for the current freeglut session */ -SFG_State fgState = { { -1, -1, FALSE }, /* Position */ - { 300, 300, TRUE }, /* Size */ +SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ + { 300, 300, GL_TRUE }, /* Size */ GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */ - FALSE, /* ForceDirectContext */ - TRUE, /* TryDirectContext */ - FALSE, /* ForceIconic */ - FALSE, /* UseCurrentContext */ - FALSE, /* GLDebugSwitch */ - FALSE, /* XSyncSwitch */ - TRUE, /* IgnoreKeyRepeat */ - 0, /* FPSInterval */ - 0, /* SwapCount */ - 0, /* SwapTime */ + GL_FALSE, /* Initalized */ + GL_FALSE, /* ForceDirectContext */ + GL_TRUE, /* TryDirectContext */ + GL_FALSE, /* ForceIconic */ + GL_FALSE, /* UseCurrentContext */ + GL_FALSE, /* GLDebugSwitch */ + GL_FALSE, /* XSyncSwitch */ + GL_TRUE, /* IgnoreKeyRepeat */ + 0, /* FPSInterval */ + 0, /* SwapCount */ + 0, /* SwapTime */ #if TARGET_HOST_WIN32 - { 0, FALSE }, /* Time */ + { 0, GL_FALSE }, /* Time */ #else - { { 0, 0 }, FALSE }, + { { 0, 0 }, GL_FALSE }, #endif - { NULL, NULL }, /* Timers */ - NULL, /* IdleCallback */ - FALSE, /* BuildingAMenu */ - 0, /* ActiveMenus */ - NULL, /* MenuStateCallback */ - NULL, /* MenuStatusCallback */ - { 640, 480, TRUE }, /* GameModeSize */ - 16, /* GameModeDepth */ - 72, /* GameModeRefresh */ - GLUT_ACTION_EXIT, /* ActionOnWindowClose */ - GLUT_EXEC_STATE_INIT /* ExecState */ + { NULL, NULL }, /* Timers */ + NULL, /* IdleCallback */ + GL_FALSE, /* BuildingAMenu */ + 0, /* ActiveMenus */ + NULL, /* MenuStateCallback */ + NULL, /* MenuStatusCallback */ + { 640, 480, GL_TRUE }, /* GameModeSize */ + 16, /* GameModeDepth */ + 72, /* GameModeRefresh */ + GLUT_ACTION_EXIT, /* ActionOnWindowClose */ + GLUT_EXEC_STATE_INIT /* ExecState */ } ; @@ -95,72 +96,39 @@ SFG_State fgState = { { -1, -1, FALSE }, /* Position */ void fgInitialize( const char* displayName ) { #if TARGET_HOST_UNIX_X11 - /* - * Have the display created - */ fgDisplay.Display = XOpenDisplay( displayName ); if( fgDisplay.Display == NULL ) - { - /* - * Failed to open a display. That's no good. - */ fgError( "failed to open display '%s'", XDisplayName( displayName ) ); - } - /* - * Check for the OpenGL GLX extension availability: - */ if( !glXQueryExtension( fgDisplay.Display, NULL, NULL ) ) - { - /* - * GLX extensions have not been found... - */ - fgError( "OpenGL GLX extension not supported by display '%s'", XDisplayName( displayName ) ); - } + fgError( "OpenGL GLX extension not supported by display '%s'", + XDisplayName( displayName ) ); - /* - * Grab the default screen for the display we have just opened - */ fgDisplay.Screen = DefaultScreen( fgDisplay.Display ); - - /* - * The same applying to the root window - */ fgDisplay.RootWindow = RootWindow( fgDisplay.Display, fgDisplay.Screen ); - /* - * Grab the logical screen's geometry - */ fgDisplay.ScreenWidth = DisplayWidth( fgDisplay.Display, fgDisplay.Screen ); - fgDisplay.ScreenHeight = DisplayHeight( fgDisplay.Display, fgDisplay.Screen ); - /* - * Grab the physical screen's geometry - */ fgDisplay.ScreenWidthMM = DisplayWidthMM( fgDisplay.Display, fgDisplay.Screen ); - fgDisplay.ScreenHeightMM = DisplayHeightMM( fgDisplay.Display, fgDisplay.Screen ); - /* - * The display's connection number - */ fgDisplay.Connection = ConnectionNumber( fgDisplay.Display ); /* @@ -182,19 +150,9 @@ void fgInitialize( const char* displayName ) */ fgDisplay.Instance = GetModuleHandle( NULL ); - /* - * Check if the freeglut window class has been registered before... - */ atom = GetClassInfo( fgDisplay.Instance, "FREEGLUT", &wc ); - - /* - * ...nope, it has not, and we have to do it right now: - */ if( atom == 0 ) { - /* - * Make sure the unitialized fields are reset to zero - */ ZeroMemory( &wc, sizeof(WNDCLASS) ); /* @@ -218,7 +176,7 @@ void fgInitialize( const char* displayName ) * Register the window class */ atom = RegisterClass( &wc ); - assert( atom != 0 ); + assert( atom ); } /* @@ -228,30 +186,20 @@ void fgInitialize( const char* displayName ) fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN ); { - /* - * Checking the display's size in millimeters isn't too hard, too: - */ - HWND desktop = GetDesktopWindow(); + HWND desktop = GetDesktopWindow( ); HDC context = GetDC( desktop ); - /* - * Grab the appropriate values now (HORZSIZE and VERTSIZE respectably): - */ fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE ); fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE ); - /* - * Whoops, forgot to release the device context :) - */ ReleaseDC( desktop, context ); } #endif - /* - * Have the joystick device initialized now - */ fgJoystickInit( 0 ); + + fgState.Initalized = GL_TRUE; } /* @@ -261,106 +209,89 @@ void fgDeinitialize( void ) { SFG_Timer *timer; - /* - * Check if initialization has been performed before - */ - if( !fgState.Time.Set ) + if( !fgState.Initalized ) { - fgWarning( "fgDeinitialize(): fgState.Timer is null => no valid initialization has been performed" ); + fgWarning( "fgDeinitialize(): " + "no valid initialization has been performed" ); return; } + fgState.Initalized = GL_FALSE; + /* * If there was a menu created, destroy the rendering context */ - if ( fgStructure.MenuContext ) + if( fgStructure.MenuContext ) { - free ( fgStructure.MenuContext ) ; - fgStructure.MenuContext = NULL ; + free( fgStructure.MenuContext ); + fgStructure.MenuContext = NULL; } - /* - * Perform the freeglut structure deinitialization - */ - fgDestroyStructure(); + fgDestroyStructure( ); - /* - * Delete all the timers and their storage list - */ - while ( (timer = (SFG_Timer *)fgState.Timers.First) != NULL ) + while( timer = ( SFG_Timer * )fgState.Timers.First ) { - fgListRemove ( &fgState.Timers, &timer->Node ) ; - free ( timer ) ; + fgListRemove ( &fgState.Timers, &timer->Node ); + free( timer ); } - /* - * Deinitialize the joystick device - */ - fgJoystickClose(); - - /* - * Reset the state structure - */ + fgJoystickClose( ); - fgState.Position.X = -1 ; - fgState.Position.Y = -1 ; - fgState.Position.Use = FALSE ; + fgState.Position.X = -1; + fgState.Position.Y = -1; + fgState.Position.Use = GL_FALSE; - fgState.Size.X = 300 ; - fgState.Size.Y = 300 ; - fgState.Size.Use = TRUE ; + fgState.Size.X = 300; + fgState.Size.Y = 300; + fgState.Size.Use = GL_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.UseCurrentContext = FALSE; - fgState.GLDebugSwitch = FALSE; - fgState.XSyncSwitch = FALSE; + fgState.ForceDirectContext = GL_FALSE; + fgState.TryDirectContext = GL_TRUE; + fgState.ForceIconic = GL_FALSE; + fgState.UseCurrentContext = GL_FALSE; + fgState.GLDebugSwitch = GL_FALSE; + fgState.XSyncSwitch = GL_FALSE; fgState.ActionOnWindowClose = GLUT_ACTION_EXIT ; fgState.ExecState = GLUT_EXEC_STATE_INIT ; - /* - * Assume we want to ignore the automatic key repeat - */ - fgState.IgnoreKeyRepeat = TRUE; + fgState.IgnoreKeyRepeat = GL_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.Time.Set = GL_FALSE; - fgState.Timers.First = fgState.Timers.Last = NULL ; - fgState.IdleCallback = NULL ; - fgState.MenuStateCallback = (FGCBmenuState)NULL ; - fgState.MenuStatusCallback = (FGCBmenuStatus)NULL ; + fgState.Timers.First = fgState.Timers.Last = NULL; + fgState.IdleCallback = NULL; + fgState.MenuStateCallback = ( FGCBMenuState )NULL; + fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL; - /* - * FPS display - */ fgState.SwapCount = 0; fgState.SwapTime = 0; fgState.FPSInterval = 0; + if( fgState.ProgramName ) + { + free( fgState.ProgramName ); + fgState.ProgramName = NULL; + } + #if TARGET_HOST_UNIX_X11 /* - * Make sure all X-client data we have created will be destroyed on display closing + * Make sure all X-client data we have created will be destroyed on + * display closing */ XSetCloseDownMode( fgDisplay.Display, DestroyAll ); /* - * Close the display connection, destroying all windows we have created so far + * Close the display connection, destroying all windows we have + * created so far */ XCloseDisplay( fgDisplay.Display ); @@ -380,220 +311,159 @@ void FGAPIENTRY glutInit( int* pargc, char** argv ) int i, j, argc = *pargc; if (pargc && *pargc && argv && *argv && **argv) - fgState.ProgramName = strdup (*argv); + fgState.ProgramName = strdup (*argv); else - fgState.ProgramName = strdup (""); - /* - * Do not allow multiple initialization of the library - */ - if( fgState.Time.Set ) - { - /* - * We can't have multiple initialization performed - */ + fgState.ProgramName = strdup (""); + if( !fgState.ProgramName ) + fgError ("Could not allocate space for the program's name."); + + if( fgState.Initalized ) fgError( "illegal glutInit() reinitialization attemp" ); - } - /* - * Have the internal freeglut structure initialized now - */ - fgCreateStructure(); + fgCreateStructure( ); - /* - * Remember the function's call time - */ -#if TARGET_HOST_UNIX_X11 - gettimeofday(&fgState.Time.Value, NULL); -#elif TARGET_HOST_WIN32 - fgState.Time.Value = timeGetTime(); -#endif - fgState.Time.Set = TRUE; + fgElapsedTime( ); /* check if GLUT_FPS env var is set */ { - const char *fps = getenv ( "GLUT_FPS" ); - if ( fps ) - { - sscanf ( fps, "%d", &fgState.FPSInterval ) ; - if ( fgState.FPSInterval <= 0 ) - fgState.FPSInterval = 5000 ; /* 5000 milliseconds */ - } + const char *fps = getenv( "GLUT_FPS" ); + if( fps ) + { + sscanf( fps, "%d", &fgState.FPSInterval ); + if( fgState.FPSInterval <= 0 ) + fgState.FPSInterval = 5000; /* 5000 milliseconds */ + } } - /* - * Grab the environment variable indicating the X display to use. - * This is harmless under Win32, so let's let it stay here... - */ #if TARGET_HOST_WIN32 - if ( !getenv ( "DISPLAY" ) ) - displayName = strdup ( "" ) ; + if( !getenv( "DISPLAY" ) ) + displayName = strdup( "" ); else #endif - displayName = strdup( getenv( "DISPLAY" ) ); + displayName = strdup( getenv( "DISPLAY" ) ); + if( !displayName ) + fgError( "Could not allocate space for display name." ); - /* - * Have the program arguments parsed. - */ - for( i=1; i= argc ) fgError( "-display parameter must be followed by display name" ); - /* - * Release the previous display name (the one from app's environment) - */ - free( displayName ); - - /* - * Make a working copy of the name for us to use - */ + if( displayName ) + free( displayName ); displayName = strdup( argv[ i ] ); + if( !displayName ) + fgError( "Could not allocate space for display name (%s)", + argv [ i ] ); - /* - * Have both arguments removed - */ argv[ i - 1 ] = NULL; - argv[ i ] = NULL; - (* pargc) -= 2; + argv[ i ] = NULL; + ( *pargc ) -= 2; } - - /* - * The geometry settings - */ else if( strcmp( argv[ i ], "-geometry" ) == 0 ) { - int result, x, y; - unsigned int w, h; - - /* - * Again, check if there is at least one more argument - */ - if ( ++i >= argc ) - fgError( "-geometry parameter must be followed by window geometry settings" ); - - /* - * Otherwise scan the geometry settings... - */ - result = sscanf ( argv[i], "%dx%d+%d+%d", &x, &y, &w, &h ); - - /* - * 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; - } + int result, x, y; + unsigned int w, h; - /* - * The direct/indirect OpenGL contexts settings - */ + if( ++i >= argc ) + fgError( "-geometry parameter must be followed by window " + "geometry settings" ); + result = sscanf( argv[ i ], "%dx%d+%d+%d", &x, &y, &w, &h ); + + 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; + } + + argv[ i - 1 ] = NULL; + argv[ i ] = NULL; + ( *pargc ) -= 2; + } else if( strcmp( argv[ i ], "-direct" ) == 0) { - /* - * We try to force direct rendering... - */ - if( fgState.TryDirectContext == FALSE ) - fgError( "parameters ambiguity, -direct and -indirect cannot be both specified" ); + if( ! fgState.TryDirectContext ) + fgError( "parameters ambiguity, -direct and -indirect " + "cannot be both specified" ); - fgState.ForceDirectContext = TRUE; + fgState.ForceDirectContext = GL_TRUE; argv[ i ] = NULL; - (* pargc)--; + ( *pargc )--; } else if( strcmp( argv[ i ], "-indirect" ) == 0 ) { - /* - * We try to force indirect rendering... - */ - if( fgState.ForceDirectContext == TRUE ) - fgError( "parameters ambiguity, -direct and -indirect cannot be both specified" ); + if( fgState.ForceDirectContext ) + fgError( "parameters ambiguity, -direct and -indirect " + "cannot be both specified" ); - fgState.TryDirectContext = FALSE; + fgState.TryDirectContext = GL_FALSE; argv[ i ] = NULL; - (* pargc)--; + (*pargc)--; } - - /* - * The '-iconic' parameter makes all new top-level - * windows created in iconified state... - */ else if( strcmp( argv[ i ], "-iconic" ) == 0 ) { - fgState.ForceIconic = TRUE; + fgState.ForceIconic = GL_TRUE; argv[ i ] = NULL; - (* pargc)--; + ( *pargc )--; } - - /* - * The '-gldebug' option activates some OpenGL state debugging features - */ else if( strcmp( argv[ i ], "-gldebug" ) == 0 ) { - fgState.GLDebugSwitch = TRUE; + fgState.GLDebugSwitch = GL_TRUE; argv[ i ] = NULL; - (* pargc)--; + ( *pargc )--; } - - /* - * The '-sync' option activates X protocol synchronization (for debugging purposes) - */ else if( strcmp( argv[ i ], "-sync" ) == 0 ) { - fgState.XSyncSwitch = TRUE; + fgState.XSyncSwitch = GL_TRUE; argv[ i ] = NULL; - (* pargc)--; + ( *pargc )--; } } /* - * Have the arguments list compacted now + * Compact {argv}. */ j = 2 ; for( i = 1; i < *pargc; i++, j++ ) { - if( argv[ i ] == NULL ) - { - while ( argv[j] == NULL ) j++ ; /* Guaranteed to end because there are "*pargc" arguments left */ - argv[i] = argv[j] ; - } + if( argv[ i ] == NULL ) + { + /* Guaranteed to end because there are "*pargc" arguments left */ + while ( argv[ j ] == NULL ) + j++; + argv[ i ] = argv[ j ] ; + } } /* * Have the display created now. As I am too lazy to implement * the program arguments parsing, we will have the DISPLAY * environment variable used for opening the X display: + * + * XXX The above comment is rather unclear. We have just + * XXX completed parsing of the program arguments for GLUT + * XXX parameters. We obviously canNOT parse the application- + * XXX specific parameters. Can someone re-write the above + * XXX more clearly? */ fgInitialize( displayName ); @@ -601,15 +471,13 @@ void FGAPIENTRY glutInit( int* pargc, char** argv ) * Check for the minus one settings for both position and size... */ if( fgState.Position.X < 0 || fgState.Position.Y < 0 ) - fgState.Position.Use = FALSE; + fgState.Position.Use = GL_FALSE; if( fgState.Size.X < 0 || fgState.Size.Y < 0 ) - fgState.Size.Use = FALSE; + fgState.Size.Use = GL_FALSE; - /* - * Do not forget about releasing the display name string - */ - free( displayName ); + if( displayName ) + free( displayName ); } /* @@ -617,26 +485,17 @@ void FGAPIENTRY glutInit( int* pargc, char** argv ) */ void FGAPIENTRY glutInitWindowPosition( int x, int y ) { - /* - * The settings can be disables when both coordinates are negative - */ - if( (x >= 0) && (y >= 0) ) + if( ( x >= 0 ) && ( y >= 0 ) ) { - /* - * We want to specify the initial position of each of the windows - */ - fgState.Position.X = x; - fgState.Position.Y = y; - fgState.Position.Use = TRUE; + fgState.Position.X = x; + fgState.Position.Y = y; + fgState.Position.Use = GL_TRUE; } else { - /* - * The initial position of each of the windows is specified by the wm - */ - fgState.Position.X = -1; - fgState.Position.Y = -1; - fgState.Position.Use = FALSE; + fgState.Position.X = -1; + fgState.Position.Y = -1; + fgState.Position.Use = GL_FALSE; } } @@ -645,26 +504,17 @@ void FGAPIENTRY glutInitWindowPosition( int x, int y ) */ void FGAPIENTRY glutInitWindowSize( int width, int height ) { - /* - * 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 - */ - fgState.Size.X = width; - fgState.Size.Y = height; - fgState.Size.Use = TRUE; + fgState.Size.X = width; + fgState.Size.Y = height; + fgState.Size.Use = GL_TRUE; } else { - /* - * 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.Y = -1; - fgState.Size.Use = FALSE; + fgState.Size.X = -1; + fgState.Size.Y = -1; + fgState.Size.Use = GL_FALSE; } } @@ -734,7 +584,7 @@ static GScannerConfig fgInitDisplayStringScannerConfig = G_CSET_a_2_z "_" G_CSET_A_2_Z - ) /* cset_identifier_first */, + ) /* cset_identifier_first */, ( G_CSET_a_2_z "_0123456789" @@ -742,29 +592,29 @@ static GScannerConfig fgInitDisplayStringScannerConfig = G_CSET_LATINS G_CSET_LATINC "<>!=~" - ) /* cset_identifier_nth */, - ( "#\n" ) /* cpair_comment_single */, - FALSE /* case_sensitive */, - TRUE /* skip_comment_multi */, - TRUE /* skip_comment_single */, - TRUE /* scan_comment_multi */, - TRUE /* scan_identifier */, - FALSE /* scan_identifier_1char */, - FALSE /* scan_identifier_NULL */, - TRUE /* scan_symbols */, - FALSE /* scan_binary */, - TRUE /* scan_octal */, - TRUE /* scan_float */, - TRUE /* scan_hex */, - FALSE /* scan_hex_dollar */, - TRUE /* scan_string_sq */, - TRUE /* scan_string_dq */, - TRUE /* numbers_2_int */, - FALSE /* int_2_float */, - FALSE /* identifier_2_string */, - TRUE /* char_2_token */, - FALSE /* symbol_2_token */, - FALSE /* scope_0_fallback */, + ) /* cset_identifier_nth */, + ( "#\n" ) /* cpair_comment_single */, + FALSE /* case_sensitive */, + TRUE /* skip_comment_multi */, + TRUE /* skip_comment_single */, + TRUE /* scan_comment_multi */, + TRUE /* scan_identifier */, + FALSE /* scan_identifier_1char */, + FALSE /* scan_identifier_NULL */, + TRUE /* scan_symbols */, + FALSE /* scan_binary */, + TRUE /* scan_octal */, + TRUE /* scan_float */, + TRUE /* scan_hex */, + FALSE /* scan_hex_dollar */, + TRUE /* scan_string_sq */, + TRUE /* scan_string_dq */, + TRUE /* numbers_2_int */, + FALSE /* int_2_float */, + FALSE /* identifier_2_string */, + TRUE /* char_2_token */, + FALSE /* symbol_2_token */, + FALSE /* scope_0_fallback */, }; /* @@ -879,7 +729,11 @@ void FGAPIENTRY glutInitDisplayString( char* displayMode ) * Grab the value string that must follow the comparison operator... */ if( comparison != FG_NONE && i < (gint) strlen( scanner->value.v_identifier ) ) + { valueString = strdup( scanner->value.v_identifier + i ); + if (!valueString) + fgError ("Could not allocate an internal string."); + } /* * If there was a value string, convert it to integer...