primrose-6+dfsg1.orig/0000755000175000017500000000000011201637730013454 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/0000755000175000017500000000000011201640002015376 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/network/0000755000175000017500000000000011201637531017104 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/network/HostAddress.h0000644000175000017500000002154007554101513021504 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2001-December-12 Jason Rohrer * Made serializable. * Changed the constructor signature. * * 2001-December-14 Jason Rohrer * Added a method for getting the local address. * Fixed several typos. * Added functions for testing equality and making copies. * Fixed a comment. * * 2002-February-25 Jason Rohrer * Made destructor virtual. * * 2002-March-25 Jason Rohrer * Added function for conversion to numerical addresses. * Changed equality function to resolve both addresses to * their numerical form first. * Changed equality function to be localhost savvy. * * 2002-March-26 Jason Rohrer * Added some print statements for testing. * Removed testing print statements. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-April-8 Jason Rohrer * Added an isNumerical function because hostname lookups on * numerical addresses are slow on Win32. * * 2002-April-11 Jason Rohrer * Fixed a bug in equals when both lookups fail. * * 2002-July-23 Jason Rohrer * Fixed a bug in equals when our local lookup fails. */ #include "minorGems/common.h" #ifndef HOST_ADDRESS_CLASS_INCLUDED #define HOST_ADDRESS_CLASS_INCLUDED #include #include #include "minorGems/io/Serializable.h" #include "minorGems/util/stringUtils.h" #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Address of a network host. * * @author Jason Rohrer */ class HostAddress : public Serializable { public: /** * Constructs an uninitialized address. * * Note that all other functions (besides deserialize and the * destructor) assume that the HostAddress is initialized. * * Useful prior to deserialization. */ HostAddress(); /** * Constructs an address. * * @param inAddressString a \0-terminated string containing the * host address. This string will be destroyed when this class * is destroyed, so it cannot be const. * @param inPort the port of the host. */ HostAddress( char *inAddressString, int inPort ); virtual ~HostAddress(); /** * Gets the address of the local host. * * @return the address of the local host. * Note that the mPort field in the returned HostAddress is * set to 0. * Must be destroyed by caller. */ static HostAddress *getLocalAddress(); /** * Gets the address of the local host in numerical format. * * @return the address of the local host. * Note that the mPort field in the returned HostAddress is * set to 0. * Must be destroyed by caller. */ static HostAddress *getNumericalLocalAddress(); /** * Gets a numerical version of this host address. * * For example, if we are using IPv4, this will generate a * HostAddress containing an aaa.bbb.ccc.ddd style address. * * @return a numerical version of this address, or NULL * if address resolution fails. * Must be destroyed by caller if non-NULL. */ HostAddress *getNumericalAddress(); /** * Gets whether this address is in numerical format. * For IpV4, this is xxx.xxx.xxx.xxx * * @return true if this address is numerical. */ char isNumerical(); /** * Gets whether another address is equivalent to this address. * * @param inAddress the address to compare to this address. * * @return true iff inAddress is equivalent to this address. */ char equals( HostAddress *inAddress ); /** * Makes a copy of this host address. * * @return the copy of this address. */ HostAddress *copy(); /** * Prints this address to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); char *mAddressString; int mAddressLength; int mPort; }; inline HostAddress::HostAddress( char *inAddressString, int inPort ) : mAddressString( inAddressString ), mPort( inPort ) { mAddressLength = strlen( mAddressString ); } inline HostAddress::HostAddress() : mAddressString( NULL ) { mAddressLength = 0; mPort = 0; } inline HostAddress::~HostAddress() { if( mAddressString != NULL ) { delete [] mAddressString; } } inline HostAddress *HostAddress::getNumericalLocalAddress() { HostAddress *address = getLocalAddress(); HostAddress *numAddress = address->getNumericalAddress(); delete address; return numAddress; } inline char HostAddress::equals( HostAddress *inAddress ) { // if the port numbers are not equal, we can return // right away if( mPort != inAddress->mPort ) { return false; } // otherwise, the port numbers are equal, // so we need to compare the addresses // first, try to compare numercally looked-up addresses HostAddress *numericalThis = this->getNumericalAddress(); if( numericalThis != NULL ) { HostAddress *numericalOther = inAddress->getNumericalAddress(); if( numericalOther != NULL ) { char returnVal = false; // watch out for localhost loopbacks if( !strcmp( numericalThis->mAddressString, "127.0.0.1" ) ) { // this address is localhost // make sure other address is not our external local address HostAddress *localAddress = getNumericalLocalAddress(); if( localAddress != NULL ) { if( !strcmp( localAddress->mAddressString, numericalOther->mAddressString ) ) { returnVal = true; } delete localAddress; } else { // numerical lookup failed for one but not the // other, so assume addresses are different returnVal = false; } } else if( !strcmp( numericalOther->mAddressString, "127.0.0.1" ) ) { // other address is localhost // make sure this address is not our external local address HostAddress *localAddress = getNumericalLocalAddress(); if( localAddress != NULL ) { if( !strcmp( localAddress->mAddressString, numericalThis->mAddressString ) ) { returnVal = true; } delete localAddress; } else { // numerical lookup failed for one but not the // other, so assume addresses are different returnVal = false; } } // if numerical addresses are identical, // then hosts are equal if( !strcmp( numericalThis->mAddressString, numericalOther->mAddressString ) ) { returnVal = true; } delete numericalOther; delete numericalThis; return returnVal; } delete numericalThis; } // otherwise, if lookup fails, compare raw adddresses if( !strcmp( inAddress->mAddressString, mAddressString ) ) { return true; } else { return false; } } inline HostAddress *HostAddress::copy() { char *stringCopy = new char[ strlen( mAddressString ) + 1 ]; strcpy( stringCopy, mAddressString ); return new HostAddress( stringCopy, mPort ); } inline void HostAddress::print() { printf( "%s:%d", mAddressString, mPort ); } inline int HostAddress::serialize( OutputStream *inOutputStream ) { int numTransmitted = 0; numTransmitted += inOutputStream->writeLong( (long)mAddressLength ); numTransmitted +=inOutputStream->write( (unsigned char *)mAddressString, mAddressLength ); numTransmitted += inOutputStream->writeLong( (long)mPort ); return numTransmitted; } inline int HostAddress::deserialize( InputStream *inInputStream ) { int numTransmitted = 0; long readLong; numTransmitted += inInputStream->readLong( &readLong ); mAddressLength = (int)readLong; if( mAddressString != NULL ) { delete [] mAddressString; } mAddressString = new char[ mAddressLength ]; numTransmitted +=inInputStream->read( (unsigned char *)mAddressString, mAddressLength ); numTransmitted += inInputStream->readLong( &readLong ); mPort = readLong; return numTransmitted; } #endif primrose-6+dfsg1.orig/minorGems/network/unix/0000755000175000017500000000000011201637531020067 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/network/unix/SocketUDPUnix.cpp0000644000175000017500000001453710155050216023246 0ustar pabspabs/* * Modification History * * 2004-November-3 Jason Rohrer * Created. * * 2004-November-4 Jason Rohrer * Added code for win32 compatibility. * Fixed a memcpy bug. * * 2004-December-7 Jason Rohrer * Fixed a bug in the evaluation of wait return codes. */ /* * The following changes were needed for win32 compatibility: * -- Winsock.h included * -- socklen_t defined * -- closesocket instead of close * -- inet_aton does not exist on win32 (switched to the linux-obsolete * inet_addr) */ #include "minorGems/network/SocketUDP.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/util/stringUtils.h" #ifndef WIN_32 // standard unix includes #include #include #include #include #include #include #include #else // special includes for win32 #include // windows does not define socklen_t typedef int socklen_t; // windows does not have a close function for sockets #define close( inSocketID ) closesocket( inSocketID ) #endif #ifdef BSD // BSD does not define socklen_t typedef int socklen_t; #endif // prototypes /** * Waits on a socket for incoming data. * * @param inSocketID the socket to watch. * @param inMilliseconds the timeout. * * @return 1 if data is ready to be read with recvfrom, -2 if we * timeout, and -1 on an error. */ int waitForIncomingData( int inSocketID, long inMilliseconds ); SocketUDP::SocketUDP( unsigned short inReceivePort ) { int socketID; socketID = socket( AF_INET, SOCK_DGRAM, 0 ); // bind to receivePort struct sockaddr_in bindAddress; bindAddress.sin_family = AF_INET; bindAddress.sin_port = htons( inReceivePort ); bindAddress.sin_addr.s_addr = INADDR_ANY; bind( socketID, (struct sockaddr *)&bindAddress, sizeof(bindAddress) ); int *socketIDArray = new int[1]; socketIDArray[0] = socketID; mNativeObjectPointer = (void *)socketIDArray; } SocketUDP::~SocketUDP() { // unwrap our native object int *socketIDArray = (int *)( mNativeObjectPointer ); int socketID = socketIDArray[0]; close( socketID ); delete [] socketIDArray; } struct UDPAddress *SocketUDP::makeAddress( const char *inAddress, unsigned short inPort ) { // try converting it from aaa.bbb.ccc.ddd int convertedAddress = inet_addr( inAddress ); if( convertedAddress != -1 ) { struct UDPAddress *address = new struct UDPAddress; address->mIPAddress = convertedAddress; address->mPort = htons( inPort ); return address; } else { return NULL; } } char *SocketUDP::extractAddress( struct UDPAddress *inAddress, unsigned short *outPort ) { struct in_addr addressStructure; addressStructure.s_addr = inAddress->mIPAddress; NetworkFunctionLocks::mInet_ntoaLock.lock(); // returned string is statically allocated, copy it char *addressString = stringDuplicate( inet_ntoa( addressStructure) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); *outPort = ntohs( inAddress->mPort ); return addressString; } int SocketUDP::send( struct UDPAddress *inAddress, unsigned char *inData, unsigned long inNumBytes ) { // unwrap our native object int *socketIDArray = (int *)( mNativeObjectPointer ); int socketID = socketIDArray[0]; // pack our address into the required structure struct sockaddr_in toAddress; toAddress.sin_family = AF_INET; toAddress.sin_port = inAddress->mPort; toAddress.sin_addr.s_addr = inAddress->mIPAddress; return sendto( socketID, (char *)inData, inNumBytes, 0, (struct sockaddr *)( &toAddress ), sizeof( toAddress ) ); } int SocketUDP::receive( struct UDPAddress **outAddress, unsigned char **outData, long inTimeout ) { // unwrap our native object int *socketIDArray = (int *)( mNativeObjectPointer ); int socketID = socketIDArray[0]; if( inTimeout != -1 ) { int waitValue = waitForIncomingData( socketID, inTimeout ); // timed out or saw an error while waiting if( waitValue == -1 || waitValue == -2 ) { *outAddress = NULL; *outData = NULL; return waitValue; } // else we have data waiting } struct sockaddr_in fromAddress; int bufferSize = 10000; unsigned char *receiveBuffer = new unsigned char[ bufferSize ]; socklen_t fromAddressLength = sizeof( fromAddress ); int numReceived; numReceived = recvfrom( socketID, (char *)receiveBuffer, bufferSize, 0, (struct sockaddr *)( &fromAddress ), &fromAddressLength ); // if no error and no overflow if( numReceived >=0 && numReceived <= bufferSize ) { *outAddress = new struct UDPAddress; (*outAddress)->mPort = fromAddress.sin_port; (*outAddress)->mIPAddress = fromAddress.sin_addr.s_addr; *outData = new unsigned char[ numReceived ]; memcpy( (void *)( *outData ), (void *)receiveBuffer, numReceived ); } else { *outAddress = NULL; *outData = NULL; } delete [] receiveBuffer; return numReceived; } /* socket timing code adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ int waitForIncomingData( int inSocketID, long inMilliseconds ) { fd_set fsr; struct timeval tv; int returnValue; FD_ZERO( &fsr ); FD_SET( inSocketID, &fsr ); tv.tv_sec = inMilliseconds / 1000; int remainder = inMilliseconds % 1000; tv.tv_usec = remainder * 1000; returnValue = select( inSocketID + 1, &fsr, NULL, NULL, &tv ); if( returnValue == 0 ) { return -2; } else if( returnValue == -1 ) { printf( "Selecting socket during receive failed.\n" ); return returnValue; } else { return returnValue; } } primrose-6+dfsg1.orig/minorGems/network/web/0000755000175000017500000000000011201637531017661 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/network/web/WebClient.h0000644000175000017500000001731311067220046021712 0ustar pabspabs/* * Modification History * * 2002-May-5 Jason Rohrer * Created. * Added a utility function for receiving data. * * 2002-May-12 Jason Rohrer * Added support for fetching the final (after redirects) URL. * * 2002-May-26 Jason Rohrer * Added support for fetching mime types and content length. * Added a function for fetching MIME types alone. * * 2006-January-22 Jason Rohrer * Added support for timeouts. * * 2008-September-25 Jason Rohrer * Added POST. */ #include "minorGems/common.h" #ifndef WEB_CLIENT_INCLUDED #define WEB_CLIENT_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/network/Socket.h" #include "minorGems/network/SocketClient.h" #include "minorGems/network/SocketStream.h" #include #include /** * A class that implements a basic web client. * * @author Jason Rohrer. */ class WebClient { public: /** * Gets a web page. * * @param inURL the URL to get as a \0-terminated string. * Must be destroyed by caller if non-const. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * @param outFinalURL pointer to where the actual * URL of the content (after following redirects) should be returned, * or NULL to ignore the final URL. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param outMimeType pointer to where the MIME type * of the content should be returned, * or NULL to ignore the MIME type. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value when making * the connection and again when reading data in milliseconds, * or -1 for no timeout. * Defaults to -1. * * @return the fetched web page as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *getWebPage( char *inURL, int *outContentLength, char **outFinalURL = NULL, char **outMimeType = NULL, long inTimeoutInMilliseconds = -1 ); /** * Fetches a web page via POST. * * @param inURL the URL to post to as a \0-terminated string. * Must be destroyed by caller if non-const. * @param inPostBody the body of the post as \0-terminated string. * Body must match MIME type application/x-www-form-urlencoded * Must be destroyed by caller if non-const. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * @param outFinalURL pointer to where the actual * URL of the content (after following redirects) should be returned, * or NULL to ignore the final URL. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param outMimeType pointer to where the MIME type * of the content should be returned, * or NULL to ignore the MIME type. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value when making * the connection and again when reading data in milliseconds, * or -1 for no timeout. * Defaults to -1. * * @return the fetched web page as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *getWebPagePOST( char *inURL, char *inPostBody, int *outContentLength, char **outFinalURL = NULL, char **outMimeType = NULL, long inTimeoutInMilliseconds = -1 ); /** * Gets the MIME type for a web page without fetching the content. * * @param inURL the URL to get as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return the fetched MIME type as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *getMimeType( char *inURL ); protected: /** * Receives data on a connection until the connection is closed. * * @param inSocketStream the stream to read from. * Must be destroyed by caller. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * * @return the received data as a \0-terminated string. * Must be destroyed by caller. */ static char *receiveData( SocketStream *inSocketStream, int *outContentLength ); /** * Executes a web method. * * @param inMethod the method to execute (for example, GET or HEAD). * Must be destroyed by caller if non-const. * @param inURL the URL to get as a \0-terminated string. * Must be destroyed by caller if non-const. * @param inBody the request body as a \0-terminated string, or NULL * for bodyless requests (like GET or HEAD). * Body must match MIME type application/x-www-form-urlencoded * Must be destroyed by caller if non-const and not NULL. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * @param outFinalURL pointer to where the actual * URL of the content (after following redirects) should be returned, * or NULL to ignore the final URL. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param outMimeType pointer to where the MIME type * of the content should be returned, * or NULL to ignore the MIME type. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value when making * the connection and again when reading data in milliseconds, * or -1 for no timeout. * Defaults to -1. * * @return the fetched web page as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *executeWebMethod( char *inMethod, char *inURL, char *inBody, int *outContentLength, char **outFinalURL = NULL, char **outMimeType = NULL, long inTimeoutInMilliseconds = -1 ); }; #endif primrose-6+dfsg1.orig/minorGems/network/web/URLUtils.cpp0000644000175000017500000002200107550627305022055 0ustar pabspabs/* * Modification History * * 2002-May-10 Jason Rohrer * Created. * * 2002-May-11 Jason Rohrer * Added functions for hex encoding and decoding. * * 2002-May-12 Jason Rohrer * Added conversion for #, &, and ?. * Added conversion for CR and LF. * * 2002-August-1 Jason Rohrer * Added conversion for /, \, ., and :. * * 2002-September-12 Jason Rohrer * Added missing breaks. * * 2002-September-25 Jason Rohrer * Fixed a bug with the way + characters are handled. * Changed to trim the returned buffer. * * 2002-October-8 Jason Rohrer * Added functions for extracting query arguments. */ #include "URLUtils.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include char *URLUtils::getRootServer( char *inURL ) { char *urlCopy = stringDuplicate( inURL ); char *endOfURLType = strstr( urlCopy, "://" ); char *returnString = NULL; if( endOfURLType != NULL ) { char *startOfRootServer = &( endOfURLType[ 3 ] ); char *endOfRootServer = strstr( startOfRootServer, "/" ); if( endOfRootServer != NULL ) { endOfRootServer[0] = '\0'; } returnString = stringDuplicate( startOfRootServer ); } delete [] urlCopy; return returnString; } char *URLUtils::getRootRelativePath( char *inURL ) { char *urlCopy = stringDuplicate( inURL ); char *endOfURLType = strstr( urlCopy, "://" ); char *returnString = NULL; if( endOfURLType != NULL ) { char *startOfRootServer = &( endOfURLType[ 3 ] ); char *endOfRootServer = strstr( startOfRootServer, "/" ); if( endOfRootServer == NULL ) { returnString = stringDuplicate( "/" ); } else { char *lastSlash = endOfRootServer; char *currentSlash = strstr( &( lastSlash[1] ), "/" ); while( currentSlash != NULL ) { lastSlash = currentSlash; currentSlash = strstr( &( lastSlash[1] ), "/" ); } // terminate string right after last slash lastSlash[1] = '\0'; returnString = stringDuplicate( endOfRootServer ); } } delete [] urlCopy; return returnString; } char *URLUtils::hexDecode( char *inString ) { // first run through string and replace any + characters with spaces char *workingString = stringDuplicate( inString ); char *plusLocation = strstr( workingString, "+" ); while( plusLocation != NULL ) { plusLocation[0] = ' '; plusLocation = strstr( plusLocation, "+" ); } int stringLength = strlen( workingString ); char *returnString = new char[ stringLength + 1 ]; int stringIndex = 0; int returnStringIndex = 0; while( stringIndex < stringLength + 1 ) { if( workingString[ stringIndex ] != '%' ) { // not a hex representation returnString[ returnStringIndex ] = workingString[ stringIndex ]; stringIndex++; returnStringIndex++; } else { // the start of hex char twoChars[2]; twoChars[0] = workingString[ stringIndex + 1 ]; twoChars[1]= workingString[ stringIndex + 2 ]; char summedChar = 0; for( int i=0; i<2; i++ ) { int shiftAmount = 4 * ( 1 - i ); switch( twoChars[i] ) { case '0': summedChar += 0x0 << shiftAmount; break; case '1': summedChar += 0x1 << shiftAmount; break; case '2': summedChar += 0x2 << shiftAmount; break; case '3': summedChar += 0x3 << shiftAmount; break; case '4': summedChar += 0x4 << shiftAmount; break; case '5': summedChar += 0x5 << shiftAmount; break; case '6': summedChar += 0x6 << shiftAmount; break; case '7': summedChar += 0x7 << shiftAmount; break; case '8': summedChar += 0x8 << shiftAmount; break; case '9': summedChar += 0x9 << shiftAmount; break; case 'A': summedChar += 0xA << shiftAmount; break; case 'B': summedChar += 0xB << shiftAmount; break; case 'C': summedChar += 0xC << shiftAmount; break; case 'D': summedChar += 0xD << shiftAmount; break; case 'E': summedChar += 0xE << shiftAmount; break; case 'F': summedChar += 0xF << shiftAmount; break; default: break; } } returnString[ returnStringIndex ] = summedChar; stringIndex += 3; returnStringIndex++; } } delete [] workingString; // trim the return string workingString = returnString; returnString = stringDuplicate( workingString ); delete [] workingString; return returnString; } char *URLUtils::hexEncode( char *inString ) { SimpleVector *returnStringVector = new SimpleVector(); int stringLength = strlen( inString ); int i; for( i=0; ipush_back( '%' ); returnStringVector->push_back( '0' ); returnStringVector->push_back( 'A' ); break; case '\r': returnStringVector->push_back( '%' ); returnStringVector->push_back( '0' ); returnStringVector->push_back( 'D' ); break; case '#': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( '3' ); break; case '&': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( '6' ); break; case '?': returnStringVector->push_back( '%' ); returnStringVector->push_back( '3' ); returnStringVector->push_back( 'F' ); break; case '\\': returnStringVector->push_back( '%' ); returnStringVector->push_back( '5' ); returnStringVector->push_back( 'C' ); break; case '/': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( 'F' ); break; case ':': returnStringVector->push_back( '%' ); returnStringVector->push_back( '3' ); returnStringVector->push_back( 'A' ); break; case '.': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( 'E' ); break; case '+': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( 'B' ); break; case ' ': returnStringVector->push_back( '+' ); break; default: returnStringVector->push_back( inString[i] ); break; } } int numChars = returnStringVector->size(); char *returnString = new char[ numChars + 1 ]; for( i=0; igetElement( i ) ); } returnString[ numChars ] = '\0'; delete returnStringVector; return returnString; } char *URLUtils::extractArgument( char *inHaystack, char *inArgName ) { char *argNameWithEquals = new char[ strlen( inArgName ) + 2 ]; sprintf( argNameWithEquals, "%s%s", inArgName, "=" ); char *haystackCopy = stringDuplicate( inHaystack ); char *pointerToArgStart = strstr( haystackCopy, argNameWithEquals ); if( pointerToArgStart == NULL ) { delete [] haystackCopy; delete [] argNameWithEquals; return NULL; } else { char *pointerToArgEnd = strstr( pointerToArgStart, "&" ); if( pointerToArgEnd != NULL ) { // terminate string at arg end pointerToArgEnd[0] = '\0'; } // else entire remainder of string is argument char *pointerToArgValue = &( pointerToArgStart[ strlen( argNameWithEquals ) ] ); // trim string char *returnString = stringDuplicate( pointerToArgValue ); delete [] argNameWithEquals; delete [] haystackCopy; return returnString; } } char *URLUtils::extractArgumentRemoveHex( char *inHaystack, char *inArgName ) { char *extractedArg = extractArgument( inHaystack, inArgName ); if( extractedArg != NULL ) { char *convertedArg = URLUtils::hexDecode( extractedArg ); delete [] extractedArg; return convertedArg; } else { return NULL; } } primrose-6+dfsg1.orig/minorGems/network/web/URLUtils.h0000644000175000017500000000717307554101513021527 0ustar pabspabs/* * Modification History * * 2002-May-10 Jason Rohrer * Created. * * 2002-May-11 Jason Rohrer * Added functions for hex encoding and decoding. * * 2002-October-8 Jason Rohrer * Added functions for extracting query arguments. */ #include "minorGems/common.h" #ifndef URL_UTILS_INCLUDED #define URL_UTILS_INCLUDED /** * Utilities for handling URLS. * * @author Jason Rohrer */ class URLUtils { public: /** * Gets the root server from a URL. * * For example, if the URL is http://www.yahoo.com/test.html * the root server is www.yahoo.com * * @param inURL the URL as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return the root server as a newly allocated * \0-terminated string. * Must be destroyed by caller. */ static char *getRootServer( char *inURL ); /** * Gets the root-relative path from a URL. * * For example, if the URL is http://www.yahoo.com/temp/test/test.html * the root-relative path is /temp/test/ * * @param inURL the URL as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return the root-relative path as a newly allocated * \0-terminated string. * Must be destroyed by caller. */ static char *getRootRelativePath( char *inURL ); /** * Removes explicit hex encoding from a string. * * For example * http%3A%2F%2Fservera.com%2Ftesta.html * would be converted to * http://servera.com/testa.html * * @param inString the string to convert in \0-terminated form. * Must be destroyed by caller if non-const. * * @return a newly allocated converted string in \0-terminated form. * Must be destroyed by caller. */ static char *hexDecode( char *inString ); /** * Encodes a string in a browser-safe hex encoding * (including adding '+' for each space). * * @param inString the string to encode. * Must be destroyed by caller. * * @return an encoded string. Must be destroyed by caller. */ static char *hexEncode( char *inString ); /** * Extracts the value from an argument of the form: * name=value& or * name=value[string_end] * * Note that if name is the suffix of an argument with a longer name * the longer-named argument's value may be returned. Thus, * argument names should not be suffixes of eachother. * * All parameters must be destroyed by caller. * * @param inHaystack the string to extract the argument from. * @param inArgName the argument name (without ?, &, or =) to search * for in inHaystack. * * @return the value of the argument, or NULL if the argument is * not found. Must be destroyed by caller if non-NULL. */ static char *extractArgument( char *inHaystack, char *inArgName ); /** * The same as extractArgument, except that explicit * hex representations are translated to plain ascii * before the argument value is returned. */ static char *extractArgumentRemoveHex( char *inHaystack, char *inArgName ); }; #endif primrose-6+dfsg1.orig/minorGems/network/web/MimeTyper.h0000644000175000017500000000417107724666437021776 0ustar pabspabs/* * Modification History * * 2002-April-20 Jason Rohrer * Created. * * 2002-September-17 Jason Rohrer * Moved mime.ini into settings directory. * * 2002-October-7 Jason Rohrer * Added a function for getting mime types from file names. * * 2003-September-1 Jason Rohrer * Copied into minorGems from the konspire2b project. */ #ifndef MIME_TYPER_INCLUDED #define MIME_TYPER_INCLUDED #include /** * A class that can resolve file extensions to mime types. * * @author Jason Rohrer */ class MimeTyper { public: /** * Constructs a mime typer. * * @param inFileName the configuration file from, or * NULL to specify the default file name, "mime.ini". * File name is relative to the settings directory. * Defaults to NULL. * Must be destroyed by caller if non-NULL and non-const. */ MimeTyper( char *inConfigFileName = NULL ); ~MimeTyper(); /** * Gets a mime type string from a file extension string. * * @param inFileExtension a \0-terminated string containing * a file extension, including the '.' * Must be destroyed by caller if non-const. * * @return the mime type as a \0-terminated string, * or NULL if there is no match. * Must be destroyed by caller if non-NULL. */ char *getMimeType( char *inFileExtension ); /** * Gets a mime type string from a file name. * * @param inFileName a \0-terminated string containing * a file name with extension. * Must be destroyed by caller if non-const. * * @return the mime type as a \0-terminated string, * or NULL if there is no match. * Must be destroyed by caller if non-NULL. */ char *getFileNameMimeType( char *inFileName ); protected: // a string containing all types read from the configuration file char *mMimeTypesString; }; #endif primrose-6+dfsg1.orig/minorGems/network/web/WebClient.cpp0000644000175000017500000002730411070507451022250 0ustar pabspabs/* * Modification History * * 2002-May-5 Jason Rohrer * Created. * Changed to default to http:// if no URL type specified. * Added support for the Host: header. * * 2002-May-7 Jason Rohrer * Added support for pages that have been moved permanently. * * 2002-May-12 Jason Rohrer * Added support for the Object Moved message type. * Added support for fetching the final (after redirects) URL. * Fixed a memory leak. * * 2002-May-26 Jason Rohrer * Added support for fetching mime types and content length. * Added a function for fetching MIME types alone. * Changed to use case-ignoring string comparison where appropriate. * * 2002-July-19 Jason Rohrer * Changed to deal with not found headers properly. * * 2002-August-5 Jason Rohrer * Fixed a typo. * * 2002-November-10 Jason Rohrer * Added a fix to deal with a slashdot bug. * * 2006-January-22 Jason Rohrer * Added support for timeouts. * * 2008-September-25 Jason Rohrer * Added POST. */ #include "WebClient.h" #include "minorGems/util/log/AppLog.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" char *WebClient::getWebPage( char *inURL, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { return executeWebMethod( "GET", inURL, NULL, outContentLength, outFinalURL, outMimeType, inTimeoutInMilliseconds ); } char *WebClient::getWebPagePost( char *inURL, char *inPostBody, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { return executeWebMethod( "POST", inURL, inPostBody, outContentLength, outFinalURL, outMimeType, inTimeoutInMilliseconds ); } char *WebClient::getMimeType( char *inURL ) { int contentLength; char *mimeType; char *content = executeWebMethod( "HEAD", inURL, NULL, &contentLength, NULL, &mimeType ); if( content != NULL ) { delete [] content; } return mimeType; } char *WebClient::executeWebMethod( char *inMethod, char *inURL, char *inBody, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { char *returnString = NULL; char *startString = "http://"; char *urlCopy = stringDuplicate( inURL ); char *urlStart = stringLocateIgnoreCase( urlCopy, startString ); char *serverStart; if( urlStart == NULL ) { // no http:// at start of URL serverStart = urlCopy; } else { serverStart = &( urlStart[ strlen( startString ) ] ); } // find the first occurrence of "/", which is the end of the // server name char *serverNameCopy = stringDuplicate( serverStart ); char *serverEnd = strstr( serverNameCopy, "/" ); char *getPath = strstr( serverStart, "/" ); if( serverEnd == NULL ) { serverEnd = &( serverStart[ strlen( serverStart ) ] ); getPath = "/"; } // terminate the url here to extract the server name serverEnd[0] = '\0'; int portNumber = 80; // look for a port number char *colon = strstr( serverNameCopy, ":" ); if( colon != NULL ) { char *portNumberString = &( colon[1] ); int numRead = sscanf( portNumberString, "%d", & portNumber ); if( numRead != 1 ) { portNumber = 80; } // terminate the name here so port isn't taken as part // of the address colon[0] = '\0'; } HostAddress *host = new HostAddress( stringDuplicate( serverNameCopy ), portNumber ); // will be set to true if we time out while connecting char timedOut; Socket *sock = SocketClient::connectToServer( host, inTimeoutInMilliseconds, &timedOut ); char *finalURL = stringDuplicate( inURL ); char *mimeType = NULL; int receivedLength = 0; if( sock != NULL ) { SocketStream *stream = new SocketStream( sock ); // reuse the same timeout for read operations stream->setReadTimeout( inTimeoutInMilliseconds ); // method and trailing space need to be sent in the same // buffer to work around a bug in certain web servers char *methodWithSpace = new char[ strlen( inMethod ) + 2 ]; sprintf( methodWithSpace, "%s ", inMethod ); // send the request stream->writeString( methodWithSpace ); stream->writeString( getPath ); stream->writeString( " HTTP/1.0\r\n" ); stream->writeString( "Host: " ); stream->writeString( serverNameCopy ); stream->writeString( "\r\n" ); if( inBody != NULL ) { char *lengthString = autoSprintf( "Content-Length: %d\r\n", strlen( inBody ) ); stream->writeString( lengthString ); delete [] lengthString; stream->writeString( "Content-Type: application/x-www-form-urlencoded\r\n\r\n" ); stream->writeString( inBody ); } else { stream->writeString( "\r\n" ); } delete [] methodWithSpace; // the simplest thing to do is to read upto the // socket close first, then extract the content char *received = receiveData( stream, &receivedLength ); char *content = NULL; char notFound = false; if( stringLocateIgnoreCase( received, "404 Not Found" ) != NULL ) { notFound = true; } // watch for redirection headers if( stringLocateIgnoreCase( received, "302 Found" ) != NULL || stringLocateIgnoreCase( received, "301 Moved Permanently" ) != NULL || stringLocateIgnoreCase( received, "302 Object Moved" ) != NULL ) { // call ourself recursively to fetch the redirection char *locationTag = "Location: "; char *locationTagStart = stringLocateIgnoreCase( received, locationTag ); if( locationTagStart != NULL ) { char *locationStart = &( locationTagStart[ strlen( locationTag ) ] ); // replace next \r with \0 char *nextChar = locationStart; while( nextChar[0] != '\r' && nextChar[0] != '\0' ) { nextChar = &( nextChar[1] ); } nextChar[0] = '\0'; char *newFinalURL; content = getWebPage( locationStart, &receivedLength, &newFinalURL, &mimeType ); delete [] finalURL; finalURL = newFinalURL; if( content == NULL ) { // not found recursively notFound = true; } } } char *contentStartString = "\r\n\r\n"; char *contentTypeStartString = "Content-type:"; if( notFound ) { returnString = NULL; } else { if( content == NULL ) { // scan for content type char *contentTypeStartMarker = stringLocateIgnoreCase( received, contentTypeStartString ); if( contentTypeStartMarker != NULL ) { // skip marker char *contentTypeStart = &( contentTypeStartMarker[ strlen( contentTypeStartString ) ] ); // extract content type // make sure the buffer is big enough char *contentType = new char[ strlen( contentTypeStartMarker ) ]; int numRead = sscanf( contentTypeStart, "%s", contentType ); if( numRead == 1 ) { // trim mimeType = stringDuplicate( contentType ); } delete [] contentType; } // extract the content from what we've received char *contentStart = strstr( received, contentStartString ); if( contentStart != NULL ) { content = &( contentStart[ strlen( contentStartString ) ] ); receivedLength = receivedLength - strlen( contentStartString ) - ( (int)contentStart - (int)received ); returnString = new char[ receivedLength + 1 ]; returnString = (char*)memcpy( returnString, content, receivedLength ); returnString[ receivedLength ] = '\0'; } } else { // we already obtained our content recursively returnString = new char[ receivedLength + 1 ]; returnString = (char*)memcpy( returnString, content, receivedLength ); returnString[ receivedLength ] = '\0'; delete [] content; } } delete [] received; delete stream; delete sock; } delete host; delete [] serverNameCopy; delete [] urlCopy; if( outFinalURL != NULL ) { *outFinalURL = finalURL; } else { delete [] finalURL; } if( outMimeType != NULL ) { *outMimeType = mimeType; } else { if( mimeType != NULL ) { delete [] mimeType; } } *outContentLength = receivedLength; return returnString; } char *WebClient::receiveData( SocketStream *inSocketStream, int *outContentLength ) { SimpleVector *receivedVector = new SimpleVector(); char connectionBroken = false; long bufferLength = 5000; unsigned char *buffer = new unsigned char[ bufferLength ]; while( !connectionBroken ) { int numRead = inSocketStream->read( buffer, bufferLength ); if( numRead != bufferLength ) { connectionBroken = true; } if( numRead > 0 ) { for( int i=0; ipush_back( buffer[i] ); } } } delete [] buffer; // copy our vector into an array int receivedSize = receivedVector->size(); char *received = new char[ receivedSize + 1 ]; for( int i=0; igetElement( i ) ); } received[ receivedSize ] = '\0'; delete receivedVector; *outContentLength = receivedSize; return received; } primrose-6+dfsg1.orig/minorGems/network/web/MimeTyper.cpp0000644000175000017500000000757607724666437022345 0ustar pabspabs/* * Modification History * * 2002-April-20 Jason Rohrer * Created. * * 2002-April-22 Jason Rohrer * Fixed a bug with the mime type string. * * 2002-April-30 Jason Rohrer * Removed an unused variable. * * 2002-September-17 Jason Rohrer * Moved mime.ini into settings directory. * * 2002-October-7 Jason Rohrer * Added a function for getting mime types from file names. * * 2003-September-1 Jason Rohrer * Copied into minorGems from the konspire2b project. */ #include "MimeTyper.h" #include "minorGems/util/stringUtils.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include #include MimeTyper::MimeTyper( char *inConfigFileName ) { File *configFile; char **pathSteps = new char*[1]; pathSteps[0] = "settings"; if( inConfigFileName == NULL ) { configFile = new File( new Path( pathSteps, 1, false ), "mime.ini" ); } else { configFile = new File( new Path( pathSteps, 1, false ), inConfigFileName ); } delete [] pathSteps; if( !configFile->exists() ) { char *name = configFile->getFileName(); printf( "Error: MIME config file %s does not exist.\n", name ); delete [] name; mMimeTypesString = new char[ 1 ]; mMimeTypesString[0] = '\0'; } else { int length = configFile->getLength(); mMimeTypesString = new char[ length + 1 ]; char *name = configFile->getFileName(); FileInputStream *inStream = new FileInputStream( configFile ); int numRead = inStream->read( (unsigned char *)mMimeTypesString, length ); if( numRead != length ) { printf( "Error reading from MIME config file %s.\n", name ); delete [] mMimeTypesString; mMimeTypesString = new char[ 1 ]; mMimeTypesString[0] = '\0'; } else { mMimeTypesString[ length ] = '\0'; } delete [] name; delete inStream; } delete configFile; } MimeTyper::~MimeTyper() { if( mMimeTypesString != NULL ) { delete [] mMimeTypesString; } } char *MimeTyper::getMimeType( char *inFileExtension ) { char *extensionMatch = strstr( mMimeTypesString, inFileExtension ); if( extensionMatch ) { // we should be able to scan two strings from // the position of the match // the first string should be the extension // the second string should be the mime type // make sure buffer is big enough char *buffer = new char[ strlen( mMimeTypesString ) + 1 ]; int numRead = sscanf( extensionMatch, "%s", buffer ); char *returnString = NULL; if( numRead == 1 ) { int numToSkip = strlen( buffer ); // skip first string token (extension) // and read next string token (mime type) numRead = sscanf( &( extensionMatch[ numToSkip ] ), "%s", buffer ); if( numRead == 1 ) { returnString = stringDuplicate( buffer ); } } delete [] buffer; return returnString; } else { return NULL; } } char *MimeTyper::getFileNameMimeType( char *inFileName ) { int fileNameLength = strlen( inFileName ); int lastPeriodIndex = -1; for( int i=0; i #include /** * A class that handles permissions for received connections. * * @author Jason Rohrer. */ class ConnectionPermissionHandler { public: /** * Constructs a handler. */ ConnectionPermissionHandler(); ~ConnectionPermissionHandler(); /** * Gets whether a connection is permitted. * * @param inAddress the address of the host connecting. * Must be destroyed by caller. * * @return true iff a connection is allowed. */ char isPermitted( HostAddress *inAddress ); private: SimpleVector *mPermittedAddresses; SimpleVector *mPermittedPatterns; }; #endif primrose-6+dfsg1.orig/minorGems/network/web/server/RequestHandlingThread.h0000644000175000017500000000600307726131706025576 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Fixed include order. * * 2002-August-2 Jason Rohrer * Added use of ConnectionPermissionHandler. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #ifndef REQUEST_HANDLING_THREAD_INCLUDED #define REQUEST_HANDLING_THREAD_INCLUDED #include "PageGenerator.h" #include "ConnectionPermissionHandler.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/network/Socket.h" #include "minorGems/network/SocketStream.h" #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" #include #include #include #define REQUEST_HANDLING_THREAD_BUFFER_SIZE 4096 /** * Request handler for WebServer. * * @author Jason Rohrer. */ class RequestHandlingThread : public Thread { public: /** * Construct a handler. * * @param inSocket the socket to send the requested * file trough. Is destroyed before this thread terminates. * @param inGenerator the class that will generate the * page content. * Is not destroyed by this class. * @param inConnectionPermissionHandler the class that will * grant connection permissions * Is not destroyed by this class. */ RequestHandlingThread( Socket *inSocket, PageGenerator *inGenerator, ConnectionPermissionHandler *inConnectionPermissionHandler); ~RequestHandlingThread(); /** * Returns true if this handler is done and ready to be destroyed. * * Synchronized, so may block. * * @return true if this handler is done and ready to be destroyed. */ char isDone(); /** * Gets a string representation of the current time. * * @return a timestamp string. Must be destroyed by caller. */ static char* getTimestamp(); // implements the Thread interface virtual void run(); private: Socket *mSocket; PageGenerator *mGenerator; ConnectionPermissionHandler *mConnectionPermissionHandler; MutexLock *mDoneLock; char mDone; /** * Sends an HTTP "not found" message with a "not found" web page. * * @param inStream the stream to send the not found page to. * @param inFileName the name of the requested file, * or NULL. */ void sendNotFoundPage( SocketStream *inStream, char *inFileName ); /** * Sends a "bad request" web page. * * @param inStream the stream to send the page to. */ void sendBadRequest( SocketStream *inStream ); }; #endif primrose-6+dfsg1.orig/minorGems/network/web/server/ConnectionPermissionHandler.cpp0000644000175000017500000000641007726131706027354 0ustar pabspabs/* * Modification History * * 2002-August-2 Jason Rohrer * Created. * Fixed a buffer size error. * * 2002-September-17 Jason Rohrer * Changed to use the SettingsManager. * * 2002-November-9 Jason Rohrer * Added support for matching address patterns. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #include "ConnectionPermissionHandler.h" #include "minorGems/io/file/File.h" #include "minorGems/util/SettingsManager.h" ConnectionPermissionHandler::ConnectionPermissionHandler() { SimpleVector *addressVector = SettingsManager::getSetting( "allowedWebHosts" ); int numAddresses = addressVector->size(); mPermittedAddresses = new SimpleVector(); mPermittedPatterns = new SimpleVector(); for( int i=0; igetElement( i ) ); char *starLocation = strstr( addressString, "*" ); if( starLocation == NULL ) { // an address mPermittedAddresses->push_back( new HostAddress( addressString, 0 ) ); } else { // an address pattern mPermittedPatterns->push_back( addressString ); } } delete addressVector; } ConnectionPermissionHandler::~ConnectionPermissionHandler() { int numAddresses = mPermittedAddresses->size(); int i; for( i=0; igetElement( i ) ); delete address; } int numPatterns = mPermittedPatterns->size(); for( i=0; igetElement( i ) ); delete [] pattern; } delete mPermittedAddresses; delete mPermittedPatterns; } char ConnectionPermissionHandler::isPermitted( HostAddress *inAddress ) { int numAddresses = mPermittedAddresses->size(); int i; for( i=0; igetElement( i ) ); if( address->equals( inAddress ) ) { return true; } } // didn't match any address exactly // check if it matches one of our patterns HostAddress* numericalAddress = inAddress->getNumericalAddress(); if( numericalAddress == NULL ) { return false; } char *addressString = numericalAddress->mAddressString; int numPatterns = mPermittedPatterns->size(); char foundMatch = false; for( i=0; igetElement( i ) ); int patternLength = strlen( pattern ); int addressLength = strlen( addressString ); char done = false; for( int j=0; jlock(); tempDone = mDone; mDoneLock->unlock(); return mDone; } // example HTTP request and response /* GET /images/title_homepage4.gif HTTP/1.0 HTTP/1.0 200 OK Date: Fri, 11 May 2001 18:05:08 GMT Server: GWS/1.10 Connection: close Expires: Sun, 17 Jan 2038 19:14:07 GMT Content-Length: 7963 Content-Type: image/gif Last-Modified: Tue, 21 Nov 2000 16:20:07 GMT GIF89a1s */ void RequestHandlingThread::run() { HostAddress *receivedAddress = mSocket->getRemoteHostAddress(); if( receivedAddress == NULL ) { printf( "Failed to obtain host address, so " "refusing web connection.\n" ); // refuse delete mSocket; // flag that we're done mDoneLock->lock(); mDone = true; mDoneLock->unlock(); return; } else if( ! mConnectionPermissionHandler->isPermitted( receivedAddress ) ) { printf( "Refusing web connection from: " ); receivedAddress->print(); printf( "\n" ); // not permitted delete mSocket; delete receivedAddress; // flag that we're done mDoneLock->lock(); mDone = true; mDoneLock->unlock(); return; } // else permitted delete receivedAddress; int maxLength = 5000; // first, receive the request and parse it SocketStream *sockStream = new SocketStream( mSocket ); int requestBufferLength = maxLength; char *requestBuffer = new char[requestBufferLength]; int requestBufferIndex = 0; // read until we see two \r\n 's in a row unsigned char *charRead = new unsigned char[1]; charRead[0] = 0; char requestDone = false; char error = false; // _we_ actually only care about the first line of // the request, but we need to read the entire request // to make the other host happy char firstLineDone = false; int numRead = 0; while( !requestDone && !error ) { while( charRead[0] != 13 && !error ) { numRead = sockStream->read( charRead, 1 ); if( !firstLineDone ) { if( numRead != 1 ) { error = true; sendBadRequest( sockStream ); } // read data into our buffer else if( requestBufferIndex < requestBufferLength ) { requestBuffer[ requestBufferIndex ] = charRead[0]; requestBufferIndex++; if( charRead[0] == 13 ) { firstLineDone = true; } } else { error = true; sendBadRequest( sockStream ); } } } if( !error ) { // look for rest of double \r\n // this will effectively skip other lines in the request, // since we don't care about them numRead = sockStream->read( charRead, 1 ); if( charRead[0] == 10 && numRead == 1 ) { numRead = sockStream->read( charRead, 1 ); if( charRead[0] == 13 && numRead == 1 ) { numRead = sockStream->read( charRead, 1 ); if( charRead[0] == 10 && numRead == 1 ) { requestDone = true; } } } if( numRead != 1 ) { error = true; sendBadRequest( sockStream ); } } } // \0 terminate the request buffer if( requestBufferIndex < requestBufferLength ) { requestBuffer[ requestBufferIndex ] = '\0'; } else { requestBuffer[ requestBufferLength - 1 ] = '\0'; } if( !error ) { // at this point, we have received the entire // request, and stored the most important part in // requestBuffer // if maxLength = 500, // formatString = "%499s" // used to limit length of scanned string char *formatString = new char[ 20 ]; sprintf( formatString, "%%%ds", maxLength - 1 ); // the second string scanned from the buffer should // be the file path requested char *filePathBuffer = new char[ maxLength ]; int numRead = sscanf( requestBuffer, formatString, filePathBuffer ); if( numRead != 1 || strcmp( filePathBuffer, "GET" ) != 0 ) { // an invalid request error = true; sendBadRequest( sockStream ); } else { // a proper GET request // skip the GET and read the file name numRead = sscanf( &( requestBuffer[3] ), formatString, filePathBuffer ); if( numRead != 1 ) { error = true; sendBadRequest( sockStream ); } } delete [] requestBuffer; delete [] charRead; delete [] formatString; if( !error ) { // now we have the requested file string sockStream->writeString( "HTTP/1.0 200 OK\r\n" ); char *mimeType = mGenerator->getMimeType( filePathBuffer ); sockStream->writeString( "Content-Type: " ); sockStream->writeString( mimeType ); sockStream->writeString( "\r\n" ); delete [] mimeType; // even if the client requests a keep-alive, we force a close sockStream->writeString( "Connection: close" ); // finish header sockStream->writeString( "\r\n\r\n" ); // pass it to our page generator, which will send the content mGenerator->generatePage( filePathBuffer, sockStream ); } delete [] filePathBuffer; } else { delete [] requestBuffer; delete [] charRead; } delete sockStream; delete mSocket; // flag that we're done mDoneLock->lock(); mDone = true; mDoneLock->unlock(); } void RequestHandlingThread::sendNotFoundPage( SocketStream *inStream, char *inFileName ) { // example "not found" response /* HTTP/1.0 404 Not Found Date: Fri, 11 May 2001 18:26:16 GMT Server: GWS/1.10 Connection: close Set-Cookie: PREF=ID=3300d4623bf73a57:TM=989605576:LM=989605576; domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT Content-Length: 142 Content-Type: text/html Not Found

404 Not Found

The requested URL /fjfj was not found on this server. */ char *buffer = new char[500]; if( inFileName != NULL ) { sprintf( buffer, "HTTP/1.0 404 Not Found\r\n\r\n" "

404 Not Found

The requested file " "%s was not found\r\n", inFileName ); } else { sprintf( buffer, "HTTP/1.0 404 Not Found\r\n\r\n" "

404 Not Found

The requested " "file was not found\r\n" ); } inStream->write( (unsigned char *)buffer, strlen( buffer ) ); delete [] buffer; } void RequestHandlingThread::sendBadRequest( SocketStream *inStream ) { // exampl "bad request" response /* Bad Request

400 Bad Request

Your client has issued a malformed or illegal request. */ char *buffer = new char[500]; sprintf( buffer, "

400 Bad Request

" "Your client has issued a malformed or illegal request." "\r\n" ); inStream->write( (unsigned char *)buffer, strlen( buffer ) ); delete [] buffer; } char* RequestHandlingThread::getTimestamp() { char *stampBuffer = new char[99]; time_t t = time( NULL ); char *asciiTime = ctime( &t ); // this time string ends with a newline... // get rid of it asciiTime[ strlen(asciiTime) - 1 ] = '\0'; sprintf( stampBuffer, "[%s]", asciiTime ); // delete [] asciiTime; return stampBuffer; } primrose-6+dfsg1.orig/minorGems/network/web/server/WebServer.cpp0000644000175000017500000000476107726131706023621 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * Added timeouts to socket accept to support checking for stop signal. * * 2002-August-2 Jason Rohrer * Added use of ConnectionPermissionHandler. * * 2002-August-6 Jason Rohrer * Changed member init order. * * 2002-September-17 Jason Rohrer * Removed argument to ConnectionPermissionHandler constructor. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #include "WebServer.h" #include "minorGems/util/log/AppLog.h" WebServer::WebServer( int inPort, PageGenerator *inGenerator ) : mPortNumber( inPort ), mMaxQueuedConnections( 100 ), mThreadHandler( new ThreadHandlingThread() ), mPageGenerator( inGenerator ), mConnectionPermissionHandler( new ConnectionPermissionHandler() ) { mServer = new SocketServer( mPortNumber, mMaxQueuedConnections ); this->start(); } WebServer::~WebServer() { stop(); join(); delete mServer; delete mThreadHandler; delete mPageGenerator; delete mConnectionPermissionHandler; } void WebServer::run() { char *logMessage = new char[100]; sprintf( logMessage, "Listening for connections on port %d\n", mPortNumber ); AppLog::info( "WebServer", logMessage ); delete [] logMessage; char acceptFailed = false; // main server loop while( !isStopped() && !acceptFailed ) { char timedOut = true; // 5 seconds long timeout = 5000; Socket *sock; AppLog::info( "WebServer", "Waiting for connection." ); while( timedOut && !isStopped() ) { sock = mServer->acceptConnection( timeout, &timedOut ); } if( sock != NULL ) { AppLog::info( "WebServer", "Connection received." ); RequestHandlingThread *thread = new RequestHandlingThread( sock, mPageGenerator, mConnectionPermissionHandler ); thread->start(); mThreadHandler->addThread( thread ); } else if( isStopped() ) { AppLog::info( "WebServer", "Received stop signal." ); } else { AppLog::error( "WebServer", "Accepting a connection failed." ); acceptFailed = true; } } } primrose-6+dfsg1.orig/minorGems/network/web/server/ThreadHandlingThread.h0000644000175000017500000000256007726131706025361 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #ifndef THREAD_HANDLING_THREAD_INCLUDED #define THREAD_HANDLING_THREAD_INCLUDED #include "RequestHandlingThread.h" #include "minorGems/system/StopSignalThread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" #include #include /** * Thread handler for the microWeb server. Runs periodically * and checks for finished threads that can be deleted. * * @author Jason Rohrer. */ class ThreadHandlingThread : public StopSignalThread { public: /** * Constructs and starts a handler. */ ThreadHandlingThread(); /** * Stops and destroys this handler. */ ~ThreadHandlingThread(); /** * Adds a thread to the set managed by this handler. * * @param inThread the thread to add. */ void addThread( RequestHandlingThread *inThread ); // implements the Thread interface virtual void run(); private: SimpleVector *mThreadVector; MutexLock *mLock; }; #endif primrose-6+dfsg1.orig/minorGems/network/web/server/WebServer.h0000644000175000017500000000326407726131706023263 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Fixed include order. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * * 2002-August-2 Jason Rohrer * Added use of ConnectionPermissionHandler. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #ifndef WEB_SERVER_INCLUDED #define WEB_SERVER_INCLUDED #include "PageGenerator.h" #include "ConnectionPermissionHandler.h" #include "minorGems/network/Socket.h" #include "minorGems/network/SocketServer.h" #include "minorGems/network/SocketStream.h" #include "RequestHandlingThread.h" #include "ThreadHandlingThread.h" #include "minorGems/system/StopSignalThread.h" #include #include /** * A class that implements a basic web server. * * @author Jason Rohrer. */ class WebServer : public StopSignalThread { public: /** * Constructs an starts this server. * * @param inPort the port to listen on. * @param inGenerator the class to use for generating pages. * Will be destroyed when this class is destroyed. */ WebServer( int inPort, PageGenerator *inGenerator ); /** * Stops and destroys this server. */ ~WebServer(); // implements the Thread::run() interface void run(); private: int mPortNumber; int mMaxQueuedConnections; SocketServer *mServer; ThreadHandlingThread *mThreadHandler; PageGenerator *mPageGenerator; ConnectionPermissionHandler *mConnectionPermissionHandler; }; #endif primrose-6+dfsg1.orig/minorGems/network/web/server/ThreadHandlingThread.cpp0000644000175000017500000000471507726131706025720 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * * 2002-August-6 Jason Rohrer * Changed member init order. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #include "ThreadHandlingThread.h" ThreadHandlingThread::ThreadHandlingThread() : mThreadVector( new SimpleVector() ), mLock( new MutexLock() ) { this->start(); } ThreadHandlingThread::~ThreadHandlingThread() { stop(); join(); mLock->lock(); int numThreads = mThreadVector->size(); // join each thread and delete it for( int i=0; igetElement( i ) ); thread->join(); delete thread; } delete mThreadVector; mLock->unlock(); delete mLock; } void ThreadHandlingThread::addThread( RequestHandlingThread *inThread ) { mLock->lock(); mThreadVector->push_back( inThread ); mLock->unlock(); } void ThreadHandlingThread::run() { while( !isStopped() ) { // sleep for 5 seconds sleep( 5000 ); // printf( "Thread handler looking for finished threads\n" ); // look for threads that need to be deleted mLock->lock(); char threadFound = true; // examine each thread while( threadFound ) { threadFound = false; int numThreads = mThreadVector->size(); for( int i=0; igetElement( i ) ); if( thread->isDone() ) { // join the thread before destroying it // to prevent memory leaks thread->join(); // remove the thread from the vector and delete it // printf( "deleting a thread\n" ); mThreadVector->deleteElement( i ); delete thread; threadFound = true; // jump out of the for loop, since our // vector size has changed i = numThreads; } } } mLock->unlock(); } } primrose-6+dfsg1.orig/minorGems/network/SocketClient.h0000644000175000017500000000365411077456516021671 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2002-October-13 Jason Rohrer * Added support for timeout on connect. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. */ #include "minorGems/common.h" #ifndef SOCKET_CLIENT_CLASS_INCLUDED #define SOCKET_CLIENT_CLASS_INCLUDED #include "Socket.h" #include "HostAddress.h" #include /** * Class that can make connections to socket servers. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class SocketClient { public: /** * Connects to a server and returns a socket. * * NOTE: * If inAddress is not in numerical format (in other words, if it * requires a DNS lookup before connection), this function may block * even if non-blocking mode is specified. * Consider using LookupThread to lookup the address before * calling this function. * * @param inAddress the host to connect to. Must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value for the connect * in milliseconds, or -1 for no timeout. Defaults to -1. * Set to 0 for non-blocking connect that returns a not-yet-connected * socket. * @param outTimedOut pointer to where the timeout flag should * be returned, or NULL for no timeout. If timeout used, will * be set to true if timeout happened, or false if it did not. * Defaults to NULL. * * @return a socket for the connection, or NULL if an error occurs. */ static Socket *connectToServer( HostAddress *inAddress, long inTimeoutInMilliseconds = -1, char *outTimedOut = NULL ); }; #endif primrose-6+dfsg1.orig/minorGems/network/SocketManager.h0000644000175000017500000000324010157336507022007 0ustar pabspabs/* * Modification History * * 2004-December-13 Jason Rohrer * Created. */ #ifndef SOCKET_MANAGER_INCLUDED #define SOCKET_MANAGER_INCLUDED #include "minorGems/network/Socket.h" #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" /** * Ensures proper destruction of static data items at program termination. */ class SocketManagerDataWrapper { public: SocketManagerDataWrapper(); ~SocketManagerDataWrapper(); MutexLock *mLock; SimpleVector *mSocketVector; }; /** * A class that ensures thread-safe socket shutdown and destruction. * * Useful if a thread needs to break a socket that another thread is using. */ class SocketManager { public: /** * Adds a socket to this manager. * * @param inSocket the socket to add. * Will be destroyed by this manager. */ static void addSocket( Socket *inSocket ); /** * Breaks the connection (both directions) associated with a socket. * * This call is safe even if inSocket has already been destroyed. * * @param inSocket the socket to break. */ static void breakConnection( Socket *inSocket ); /** * Destroys a socket and removes it from this manager. * * @param inSocket the socket to destroy. */ static void destroySocket( Socket *inSocket ); private: // allocated statically to ensure destruction on program termination static SocketManagerDataWrapper mDataWrapper; }; #endif primrose-6+dfsg1.orig/minorGems/network/SocketManager.cpp0000644000175000017500000000375010157336507022350 0ustar pabspabs/* * Modification History * * 2004-December-13 Jason Rohrer * Created. */ #include "SocketManager.h" // static initialization SocketManagerDataWrapper SocketManager::mDataWrapper; SocketManagerDataWrapper::SocketManagerDataWrapper() : mLock( new MutexLock() ), mSocketVector( new SimpleVector() ) { } SocketManagerDataWrapper::~SocketManagerDataWrapper() { int numSockets = mSocketVector->size(); for( int i=0; igetElement( i ) ); } delete mSocketVector; delete mLock; } void SocketManager::addSocket( Socket *inSocket ) { MutexLock *lock = mDataWrapper.mLock; SimpleVector *socketVector = mDataWrapper.mSocketVector; lock->lock(); socketVector->push_back( inSocket ); lock->unlock(); } void SocketManager::breakConnection( Socket *inSocket ) { MutexLock *lock = mDataWrapper.mLock; SimpleVector *socketVector = mDataWrapper.mSocketVector; lock->lock(); int numSockets = socketVector->size(); char found = false; for( int i=0; igetElement( i ) ); if( currentSocket == inSocket ) { currentSocket->breakConnection(); found = true; } } lock->unlock(); } void SocketManager::destroySocket( Socket *inSocket ) { MutexLock *lock = mDataWrapper.mLock; SimpleVector *socketVector = mDataWrapper.mSocketVector; lock->lock(); int numSockets = socketVector->size(); char found = false; for( int i=0; igetElement( i ) ); if( currentSocket == inSocket ) { delete currentSocket; socketVector->deleteElement( i ); found = true; } } lock->unlock(); } primrose-6+dfsg1.orig/minorGems/network/SocketUDP.h0000644000175000017500000001325410144135464021066 0ustar pabspabs/* * Modification History * * 2004-November-3 Jason Rohrer * Created. * * 2004-November-4 Jason Rohrer * Added default receive timeout (infinite). * * 2004-November-9 Jason Rohrer * Added functions for comparing and copying UDPAddresses. */ #ifndef SOCKET_UDP_INCLUDED #define SOCKET_UDP_INCLUDED /** * Structure representing a UDP endpoint. */ struct UDPAddress { // binary internet address in network byte order unsigned long mIPAddress; // port number in network byte order unsigned short mPort; }; /** * Network socket that can be used as an endpoint for sending and receiving * UDP packets (unreliable datagrams). * * Note: Implementation for the functions defined here is provided * separately for each platform (in the unix/ and win32/ subdirectories). * * Socket::initSocketFramework() must be called once before this class * is used. * * @author Jason Rohrer */ class SocketUDP { public: /** * Constructs a UDP socket and starts listening for incoming datagrams. * * @param inReceivePort the port to listen on, in platform-dependent * byte order. */ SocketUDP( unsigned short inReceivePort ); ~SocketUDP(); /** * Makes a UDPAddress structure. * * @param inAddress the IP address in ascii numbers-and-dots notation. * Must be destroyed by caller if non-const. * @param inPort the port number in platform-specific byte order. * * @return an address structure, or NULL if converting the address * fails. * Must be destroyed by caller if non-NULL. */ static struct UDPAddress *makeAddress( const char *inAddress, unsigned short inPort ); /** * Extracts address elements from a UDPAddress structure. * * @param inAddress the address structure. Must be destroyed by * caller. * @param outPort pointer to where the port number, in * platform-specific byte order, should be returned. * * @return the IP address in ascci numbers-and-dots notation. * Must be destroyed by caller. */ static char *extractAddress( struct UDPAddress *inAddress, unsigned short *outPort ); /** * Compares two UDP addresses. * * @param inFirst the first address. * @param inSecond the second address. * * @return true if the addresses are equal, or false if they are * different. */ static char compare( struct UDPAddress *inFirst, struct UDPAddress *inSecond ); /** * Makes a copy of a UDP address. * * @param inAddress the address to copy. * * @return a copy of the address. Must be destroyed by caller. */ static struct UDPAddress *copy( struct UDPAddress *inAddress ); /** * Sends a datagram through this socket. * * Note: the recommended maximum data length is 512 bytes * to ensure that the datagram can be routed without * fragmentation through all spec-compliant routers. * Most routers support larger datagrams, however. * * @param inAddress the address to send data through. Must be * destroyed by caller. * @param inData the data bytes to send. * @param inNumBytes the number of bytes to send. * * @return the number of bytes sent successfully, * or -1 for a socket error. */ int send( struct UDPAddress *inAddress, unsigned char *inData, unsigned long inNumBytes ); /** * Receives a datagram from this socket. * * @param outAddress pointer to where the address of the remote * host (the datagram sender) should be returned. * Will be set to NULL on socket error or timeout. * Must be destroyed by caller if non-NULL. * @param outData pointer to where the received data should be * returned. Will be set to NULL on socket error or timeout. * Must be destroyed by caller if non-NULL. * @param inTimeout the timeout for this receive operation in * milliseconds. Set to -1 for an infinite timeout. * -2 is returned from this call in the event of a timeout. * Defaults to -1. * * @return the number of bytes received successfully, * -1 for a socket error, or -2 for a timeout. */ int receive( struct UDPAddress **outAddress, unsigned char **outData, long inTimeout = -1 ); /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; }; inline char SocketUDP::compare( struct UDPAddress *inFirst, struct UDPAddress *inSecond ) { if( inFirst->mIPAddress == inSecond->mIPAddress && inFirst->mPort == inSecond->mPort ) { return true; } else { return false; } } inline struct UDPAddress *SocketUDP::copy( struct UDPAddress *inAddress ) { struct UDPAddress *returnAddress = new struct UDPAddress; returnAddress->mIPAddress = inAddress->mIPAddress; returnAddress->mPort = inAddress->mPort; return returnAddress; } #endif primrose-6+dfsg1.orig/minorGems/network/socketTest.cpp0000644000175000017500000000426210157336507021754 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-28 Jason Rohrer * Added more output. * Added better error checking. * * 2001-December-14 Jason Rohrer * Added a test of HostAddress::getLocalAddress(). * * 2002-July-30 Jason Rohrer * Added a test of streams. * * 2002-July-31 Jason Rohrer * Changed to test multiple blocks. * * 2002-February-4 Jason Rohrer * Added test of getting local address from socket. */ #include "Socket.h" #include "SocketStream.h" #include "SocketServer.h" #include "SocketClient.h" #include "HostAddress.h" #include int main() { HostAddress *address = HostAddress::getLocalAddress(); printf( "Local address: " ); address->print(); printf( "\n" ); int port = 5158; SocketServer *server = new SocketServer( port, 100 ); printf( "Waiting for a connection on port %d\n", port ); Socket *receiveSocket = server->acceptConnection(); if( receiveSocket == NULL ) { return 1; } printf( "Connection received\n" ); HostAddress *localAddress = receiveSocket->getLocalHostAddress(); if( localAddress != NULL ) { printf( "Our local address (fetched from socket) is " ); localAddress->print(); printf( "\n" ); delete localAddress; } SocketStream *receiveStream = new SocketStream( receiveSocket ); receiveStream->setReadTimeout( 10000 ); int numBytes = 4000; int checksum = 0; unsigned char *buffer = new unsigned char[numBytes]; /* for( int i=0; iread( buffer, 1 ); checksum += buffer[ 0 ]; if( numRec != 1) { printf( "Faiedl to read.\n" ); return 1; } //sleep( 1 ); } */ int count = 0; while( true ) { int numRec = receiveStream->read( buffer, numBytes ); printf( "Received %d successfully,\tcount = %d\n", numBytes, count ); count++; } /* for( int i=0; icopy() ), mNumericalAddress( NULL ), mLookupDone( false ) { start(); } LookupThread::~LookupThread() { join(); delete mAddress; if( mNumericalAddress != NULL ) { delete mNumericalAddress; } } char LookupThread::isLookupDone() { mLock.lock(); char done = mLookupDone; mLock.unlock(); return done; } HostAddress *LookupThread::getResult() { mLock.lock(); HostAddress *result = NULL; if( mNumericalAddress != NULL ) { result = mNumericalAddress->copy(); } mLock.unlock(); return result; } void LookupThread::run() { HostAddress *numAddress = mAddress->getNumericalAddress(); mLock.lock(); mLookupDone = true; mNumericalAddress = numAddress; mLock.unlock(); setFinished(); } primrose-6+dfsg1.orig/minorGems/network/p2pParts/0000755000175000017500000000000011201637531020617 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/network/p2pParts/MultiSourceDownloader.h0000644000175000017500000000546210150605366025274 0ustar pabspabs/* * Modification History * * 2004-November-21 Jason Rohrer * Created. * * 2004-November-23 Jason Rohrer * Fixed compile errors caused by multiple definitions. */ #ifndef MULTISOURCE_DOWNLOADER_INCLUDED #define MULTISOURCE_DOWNLOADER_INCLUDED /** * Abstract API for multi-source downloads. * * @author Jason Rohrer. */ extern int MULTISOURCE_DOWNLOAD_IN_PROGRESS; extern int MULTISOURCE_DOWNLOAD_FAILED; extern int MULTISOURCE_DOWNLOAD_CANCELED; /** * Gets a file from multiple sources. * * @param inFileDescriptor abstract pointer to a file descriptor that can * be used by inChunkGetter to identify a file. * Must be destroyed by caller. * @param inFileSize the size of the file in bytes. * @param inChunkSize the size of a download chunk in bytes. * @param inNumSources the number of file sources. * @param inFileSources an array of abstract pointers to file sources that * can be used by inChunkSize to connect to sources. * Array and elements must be destroyed by caller. * @param inChunkGetter pointer to the function that can be used to get a * chunk. * The function must return an array of chunk bytes (or NULL on failure) * and take the following arguments: * ( void *inFileSource, void *inFileDescriptor, * unsigned long inChunkNumber, unsigned long inChunkSize ). * @praram inDownloadProgressHandler pointer to the handler function for * download progress events. * This function must return true to continue the download (or false * to cancel) and take the following arguments: * (int inResultCode, unsigned long inTotalBytesReceived, * void *inExtraArgument ). * inResultCode will be set to one of MULTISOURCE_DOWNLOAD_IN_PROGRESS, * MULTISOURCE_DOWNLOAD_FAILED, or MULTISOURCE_DOWNLOAD_CANCELED. * Once a FAILED or CANCELED result code is passed to the handler, the * handler will never be called again, so it should destroy its extra * argument, if necessary. * @param inProgressHandlerExtraArgument pointer to an extra argument to be * passed in to the handler function each time it is called. * Must be destroyed by caller. * @param inDestinationPath the path to save the file to. * Must be destroyed by caller. */ void multiSourceGetFile( void *inFileDescriptor, unsigned long inFileSize, unsigned long inChunkSize, int inNumSources, void **inFileSources, unsigned char * (*inChunkGetter)( void *, void *, unsigned long, unsigned long ), char (*inDownloadProgressHandler)( int, unsigned long, void * ), void *inProgressHandlerExtraArgument, char *inDestinationPath ); #endif primrose-6+dfsg1.orig/minorGems/network/p2pParts/DuplicateMessageDetector.cpp0000644000175000017500000000464307716730656026265 0ustar pabspabs/* * Modification History * * 2003-August-7 Jason Rohrer * Created. * * 2003-August-14 Jason Rohrer * Changed to output message history to file. */ #include "DuplicateMessageDetector.h" #include "minorGems/util/stringUtils.h" #include #include DuplicateMessageDetector::DuplicateMessageDetector( int inMessageHistorySize ) : mMaxHistorySize( inMessageHistorySize ), mLock( new MutexLock() ), mSeenIDs( new SimpleVector() ), mTotalMessageCount( 0 ), mHistoryOutputFile( NULL ) { mHistoryOutputFile = fopen( "messageHistory.log", "w" ); } DuplicateMessageDetector::~DuplicateMessageDetector() { int numIDs = mSeenIDs->size(); for( int i=0; igetElement( i ) ); } delete mSeenIDs; delete mLock; fclose( mHistoryOutputFile ); } char DuplicateMessageDetector::checkIfMessageSeen( char *inMessageUniqueID ) { mLock->lock(); mTotalMessageCount++; int numIDs = mSeenIDs->size(); char matchSeen = false; for( int i=0; igetElement( i ) ); if( strcmp( otherID, inMessageUniqueID ) == 0 ) { // match // push the ID back to the end of the queue mSeenIDs->deleteElement( i ); mSeenIDs->push_back( otherID ); matchSeen = true; } } if( mHistoryOutputFile != NULL ) { fprintf( mHistoryOutputFile, "%d %d %s", mTotalMessageCount, (int)( time( NULL ) ), inMessageUniqueID ); } if( !matchSeen ) { // add the message mSeenIDs->push_back( stringDuplicate( inMessageUniqueID ) ); // make sure history not too long if( mSeenIDs->size() > mMaxHistorySize ) { delete [] *( mSeenIDs->getElement( 0 ) ); mSeenIDs->deleteElement( 0 ); } if( mHistoryOutputFile != NULL ) { fprintf( mHistoryOutputFile, "\n" ); } } else { // add duplicate tag if( mHistoryOutputFile != NULL ) { fprintf( mHistoryOutputFile, " D\n" ); } } if( mHistoryOutputFile != NULL ) { fflush( mHistoryOutputFile ); } mLock->unlock(); return matchSeen; } primrose-6+dfsg1.orig/minorGems/network/p2pParts/protocolUtils.h0000644000175000017500000000370107721440564023665 0ustar pabspabs/* * Modification History * * 2003-August-12 Jason Rohrer * Created. * * 2003-August-22 Jason Rohrer * Added function for getting a token after reading. */ #ifndef P2P_PROTOCOL_UTILS_INCLUDED #define P2P_PROTOCOL_UTILS_INCLUDED #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" /** * A collection of common protocol processing functions. * * @author Jason Rohrer */ /** * Reads from a stream up to (and including) the * first occurence of a tag. * * @param inInputStream the stream to read from. * Must be destroyed by caller. * @param inTag the tag to look for. * Must be destroyed by caller if non-const. * @param inMaxCharsToRead the maximum number of characters to read. * * @return the read string, or NULL if reading fails. * NULL is also returned if the character count limit is * reached. * Must be destroyed by caller if non-NULL. */ char *readStreamUpToTag( InputStream *inInputStream, char *inTag, int inMaxCharsToRead ); /** * Reads from a stream up to (and including) the * first occurence of a tag and gets a specific token from the read data. * * Tokens are split by whitespace. * * @param inInputStream the stream to read from. * Must be destroyed by caller. * @param inTag the tag to look for. * Must be destroyed by caller if non-const. * @param inMaxCharsToRead the maximum number of characters to read. * @param inTokenNumber the token to get after reading up to inTag and * tokenizing the read data. 0 specifies the first token. * * @return the read token string, or NULL if reading or token extraction fails. * NULL is also returned if the character count limit is * reached. * Must be destroyed by caller if non-NULL. */ char *readStreamUpToTagAndGetToken( InputStream *inInputStream, char *inTag, int inMaxCharsToRead, int inTokenNumber ); #endif primrose-6+dfsg1.orig/minorGems/network/p2pParts/MultipleConnectionPreventer.cpp0000644000175000017500000000333307674671761027061 0ustar pabspabs/* * Modification History * * 2003-June-20 Jason Rohrer * Created. */ #include "MultipleConnectionPreventer.h" MultipleConnectionPreventer::MultipleConnectionPreventer() : mLock( new MutexLock() ), mConnections( new SimpleVector() ) { } MultipleConnectionPreventer::~MultipleConnectionPreventer() { mLock->lock(); int numConnections = mConnections->size(); for( int i=0; igetElement( i ) ); } delete mConnections; mLock->unlock(); delete mLock; } char MultipleConnectionPreventer::addConnection( HostAddress *inAddress ) { mLock->lock(); char connectionExists = false; int numConnections = mConnections->size(); for( int i=0; igetElement( i ) ); if( inAddress->equals( otherConnection ) ) { connectionExists = true; } } if( !connectionExists ) { mConnections->push_back( inAddress->copy() ); } mLock->unlock(); return !connectionExists; } void MultipleConnectionPreventer::connectionBroken( HostAddress *inAddress ) { mLock->lock(); char connectionFound = false; int numConnections = mConnections->size(); for( int i=0; igetElement( i ) ); if( inAddress->equals( otherConnection ) ) { connectionFound = true; delete otherConnection; mConnections->deleteElement( i ); } } mLock->unlock(); } primrose-6+dfsg1.orig/minorGems/network/p2pParts/MessagePerSecondLimiter.h0000644000175000017500000000402307775323015025516 0ustar pabspabs/* * Modification History * * 2003-October-9 Jason Rohrer * Created. * * 2003-October-12 Jason Rohrer * Switched to a floating point limit. * * 2004-January-2 Jason Rohrer * Added seprate mutex for transmission function to prevent UI freeze. */ #ifndef MESSAGE_PER_SECOND_LIMITER_INCLUDED_H #define MESSAGE_PER_SECOND_LIMITER_INCLUDED_H #include "minorGems/system/MutexLock.h" /** * Class that limits the number of messages transmitted per second. * * @author Jason Rohrer */ class MessagePerSecondLimiter { public: /** * Constructs a limiter. * * @param inLimitPerSecond the maximum number of messages * transmitted per second, or -1 for no limit. * Defaults to -1. */ MessagePerSecondLimiter( double inLimitPerSecond = -1 ); ~MessagePerSecondLimiter(); /** * Sets the limit. * * Thread safe. * * @param inLimitPerSecond the maximum number of messages * transmitted per second, or -1 for no limit. */ void setLimit( double inLimitPerSecond ); /** * Gets the limit. * * Thread safe. * * @return the maximum number of messages * transmitted per second, or -1 if no limit set. */ double getLimit(); /** * Called by a message transmitter to indicate that a message * is about to be transmitted. Will block if messages * are being transmitted too frequently. * * Thread safe. */ void messageTransmitted(); protected: MutexLock *mLock; MutexLock *mTransmitLock; double mLimitPerSecond; unsigned long mMillisecondsBetweenMessages; unsigned long mSecondTimeOfLastMessage; unsigned long mMillisecondTimeOfLastMessage; }; #endif primrose-6+dfsg1.orig/minorGems/network/p2pParts/DuplicateMessageDetector.h0000644000175000017500000000272507716716063025725 0ustar pabspabs/* * Modification History * * 2003-August-7 Jason Rohrer * Created. * * 2003-August-14 Jason Rohrer * Changed to output message history to file. */ #ifndef DUPLICATE_MESSAGE_DETECTOR_INCLUDED_H #define DUPLICATE_MESSAGE_DETECTOR_INCLUDED_H #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" #include /** * Class that detects duplicates of past messages so that they can be * discarded. * * @author Jason Rohrer */ class DuplicateMessageDetector { public: /** * Constructs a detector. * * @param inMessageHistorySize the number of message IDs to * maintain in our history. * Defaults to 1000. */ DuplicateMessageDetector( int inMessageHistorySize = 1000 ); ~DuplicateMessageDetector(); /** * Checks if a message has been seen in the past. * * @param inMessageUniqueID the unique ID for the message. * Must be destroyed by caller. * * @return true if the message has already been seen, or * false if the message is new. */ char checkIfMessageSeen( char *inMessageUniqueID ); protected: int mMaxHistorySize; MutexLock *mLock; SimpleVector *mSeenIDs; int mTotalMessageCount; FILE *mHistoryOutputFile; }; #endif primrose-6+dfsg1.orig/minorGems/network/p2pParts/MessagePerSecondLimiter.cpp0000644000175000017500000000523110227735471026052 0ustar pabspabs/* * Modification History * * 2003-October-9 Jason Rohrer * Created. * * 2003-October-12 Jason Rohrer * Switched to a floating point limit. * * 2004-January-2 Jason Rohrer * Added seprate mutex for transmission function to prevent UI freeze. * * 2005-April-15 Jason Rohrer * Changed to use updated Thread interface. */ #include "MessagePerSecondLimiter.h" #include "minorGems/system/Time.h" #include "minorGems/system/Thread.h" MessagePerSecondLimiter::MessagePerSecondLimiter( double inLimitPerSecond ) : mLock( new MutexLock() ), mTransmitLock( new MutexLock() ), mLimitPerSecond( inLimitPerSecond ) { if( mLimitPerSecond != -1 ) { mMillisecondsBetweenMessages = (int)( 1000 / mLimitPerSecond ); } else { mMillisecondsBetweenMessages = 0; } Time::getCurrentTime( &mSecondTimeOfLastMessage, &mMillisecondTimeOfLastMessage ); } MessagePerSecondLimiter::~MessagePerSecondLimiter() { delete mLock; delete mTransmitLock; } void MessagePerSecondLimiter::setLimit( double inLimitPerSecond ) { mLock->lock(); mLimitPerSecond = inLimitPerSecond; if( mLimitPerSecond != -1 ) { mMillisecondsBetweenMessages = (int)( 1000 / mLimitPerSecond ); } else { mMillisecondsBetweenMessages = 0; } mLock->unlock(); } double MessagePerSecondLimiter::getLimit() { mLock->lock(); double limit = mLimitPerSecond; mLock->unlock(); return limit; } void MessagePerSecondLimiter::messageTransmitted() { // allow only one transmitter to report at a time mTransmitLock->lock(); // protect our variables (make sure settings functions are not // called while we touch the variables) mLock->lock(); unsigned long millisecondsSinceLastMessage = Time::getMillisecondsSince( mSecondTimeOfLastMessage, mMillisecondTimeOfLastMessage ); if( millisecondsSinceLastMessage < mMillisecondsBetweenMessages ) { // this message is coming too soon after last message // sleep unsigned long sleepTime = mMillisecondsBetweenMessages - millisecondsSinceLastMessage; // unlock main lock befor sleeping so that settings can be changed mLock->unlock(); Thread::staticSleep( sleepTime ); // relock mLock->lock(); } Time::getCurrentTime( &mSecondTimeOfLastMessage, &mMillisecondTimeOfLastMessage ); mLock->unlock(); mTransmitLock->unlock(); } primrose-6+dfsg1.orig/minorGems/network/p2pParts/OutboundChannel.h0000644000175000017500000001150610157121106024056 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2003-July-27 Jason Rohrer * Added a setHost function. * * 2003-September-23 Jason Rohrer * Replaced sleep-waiting with semaphores. This results in a major speedup. * * 2003-October-9 Jason Rohrer * Added support for message limiters. * * 2004-December-12 Jason Rohrer * Added a queue size parameter. */ #ifndef OUTBOUND_CHANNEL_INCLUDED #define OUTBOUND_CHANNEL_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/io/OutputStream.h" #include "minorGems/system/MutexLock.h" #include "minorGems/system/Semaphore.h" #include "minorGems/system/Thread.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/network/p2pParts/MessagePerSecondLimiter.h" /** * A channel that can send messages to a receiving host. * * NOTE: * None of the member functions are safe to call if this class has been * destroyed. Since the application-specific channel manager class can * destroy a given instance of this class at any time, these member functions * should NEVER be called directly. * Instead, the appropriate channel manager functions should be called. * * @author Jason Rohrer */ class OutboundChannel : public Thread { public: /** * Constructs an OutboundChannel and starts the sending thread. * * @param inOutputStream the stream wrapped by this channel. * Must be destroyed by caller. * @param inHost the host on the other end of this channel. * Will be destroyed when this class is destroyed. * @param inLimiter the limiter for outbound messages. * Must be destroyed by caller after this class is destroyed. * @param inQueueSize the size of the send queue. Defaults to 50. */ OutboundChannel( OutputStream *inOutputStream, HostAddress *inHost, MessagePerSecondLimiter *inLimiter, unsigned long inQueueSize = 50 ); /** * Stops the sending thread and destroys this channel. */ ~OutboundChannel(); /** * Sends a message to this channel's receiver. * * Thread safe. * * This call queues the message to be sent, so it returns before * the send is complete. * * @param inMessage the message to send. * Must be destroyed by caller if non-const. * @param inPriority the priority of this message. * Values less than or equal to 0 indicate default priority, * while positive values suggest higher priority. * Granularity of prioritization is implementation dependent. * Defaults to 0. * * @return true if the channel is still functioning properly, * or false if the channel has been broken. */ char sendMessage( char *inMessage, int inPriority = 0 ); /** * Gets the host receiving from this channel. * * @return this channel's receiving host. * Must be destroyed by caller. */ HostAddress * getHost( ); /** * Sets the address of the remotely connected host. * * @param inHost the host on the other end of this channel. * Will be destroyed when this class is destroyed. */ void setHost( HostAddress *inHost ); /** * Gets the number of outbound messages that have been sent on * this channel. * * Thread safe. * * @return the number of sent messages. */ int getSentMessageCount(); /** * Gets the number of outbound messages that are currently * queued for this channel. * * Thread safe. * * @return the number of queued messages. */ int getQueuedMessageCount(); /** * Gets the number of outbound messages that have been dropped * by this channel. * * Thread safe. * * @return the number of dropped messages. */ int getDroppedMessageCount(); // implements the Thread interface void run(); protected: MutexLock *mLock; Semaphore *mMessageReadySemaphore; OutputStream *mStream; HostAddress *mHost; MessagePerSecondLimiter *mLimiter; char mConnectionBroken; char mThreadStopped; SimpleVector *mMessageQueue; SimpleVector *mHighPriorityMessageQueue; int mMaxQueueSize; int mDroppedMessageCount; int mSentMessageCount; }; #endif primrose-6+dfsg1.orig/minorGems/network/p2pParts/MultipleConnectionPreventer.h0000644000175000017500000000305007674671762026523 0ustar pabspabs/* * Modification History * * 2003-June-20 Jason Rohrer * Created. */ #ifndef MULTIPLE_CONNECTION_PREVENTER_INCLUDED_H #define MULTIPLE_CONNECTION_PREVENTER_INCLUDED_H #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/network/HostAddress.h" /** * Class that tracks current connections of a p2p node and prevents * multiple connections to the same address. * * @author Jason Rohrer */ class MultipleConnectionPreventer { public: MultipleConnectionPreventer(); ~MultipleConnectionPreventer(); /** * Adds a connection to a host, and checks if the connection * is permitted. * * The connection will not be permitted if another connection * to the address already exists. * * Thread safe. * * @param inAddress the address of the connection. * Must be destroyed by caller. * * @return true if the connection is permitted, or false otherwise. */ char addConnection( HostAddress *inAddress ); /** * Reports that a connection has been broken. * * Thread safe. * * @param inAddress the address of the broken connection. * Must be destroyed by caller. */ void connectionBroken( HostAddress *inAddress ); protected: MutexLock *mLock; SimpleVector *mConnections; }; #endif primrose-6+dfsg1.orig/minorGems/network/p2pParts/OutboundChannel.cpp0000644000175000017500000001363410157121106024415 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2003-July-27 Jason Rohrer * Added a setHost function. * * 2003-September-23 Jason Rohrer * Replaced sleep-waiting with semaphores. This results in a major speedup. * * 2003-October-9 Jason Rohrer * Added support for message limiters. * * 2004-January-11 Jason Rohrer * Made include paths explicit to help certain compilers. * * 2004-December-12 Jason Rohrer * Added a queue size parameter. */ #include "minorGems/network/p2pParts/OutboundChannel.h" OutboundChannel::OutboundChannel( OutputStream *inOutputStream, HostAddress *inHost, MessagePerSecondLimiter *inLimiter, unsigned long inQueueSize ) : mLock( new MutexLock() ), mMessageReadySemaphore( new Semaphore() ), mStream( inOutputStream ), mHost( inHost ), mLimiter( inLimiter ), mConnectionBroken( false ), mThreadStopped( false ), mMessageQueue( new SimpleVector() ), mHighPriorityMessageQueue( new SimpleVector() ), mMaxQueueSize( inQueueSize ), mDroppedMessageCount( 0 ), mSentMessageCount( 0 ) { // start our thread start(); } OutboundChannel::~OutboundChannel() { mLock->lock(); mThreadStopped = true; mLock->unlock(); // wake the thread up if it is waiting mMessageReadySemaphore->signal(); // wait for our thread to get the stop signal and finish join(); mLock->lock(); delete mMessageReadySemaphore; // clear the queues int numMessages = mMessageQueue->size(); int i; for( i=0; igetElement( i ) ); delete [] message; } delete mMessageQueue; numMessages = mHighPriorityMessageQueue->size(); for( i=0; igetElement( i ) ); delete [] message; } delete mHighPriorityMessageQueue; delete mHost; mLock->unlock(); delete mLock; } char OutboundChannel::sendMessage( char * inMessage, int inPriority ) { mLock->lock(); char sent; if( !mConnectionBroken ) { // add it to the queue SimpleVector *queueToUse; if( inPriority <=0 ) { queueToUse = mMessageQueue; } else { queueToUse = mHighPriorityMessageQueue; } queueToUse->push_back( stringDuplicate( inMessage ) ); sent = true; if( queueToUse->size() > mMaxQueueSize ) { // the queue is over-full // drop the oldest message char *message = *( queueToUse->getElement( 0 ) ); queueToUse->deleteElement( 0 ); delete [] message; mDroppedMessageCount++; } } else { // channel no longer working sent = false; } mLock->unlock(); if( sent ) { mMessageReadySemaphore->signal(); } return sent; } HostAddress * OutboundChannel::getHost() { return mHost->copy(); } void OutboundChannel::setHost( HostAddress *inHost ) { delete mHost; mHost = inHost->copy(); } int OutboundChannel::getSentMessageCount() { mLock->lock(); int count = mSentMessageCount; mLock->unlock(); return count; } int OutboundChannel::getQueuedMessageCount() { mLock->lock(); int count = mMessageQueue->size() + mHighPriorityMessageQueue->size(); mLock->unlock(); return count; } int OutboundChannel::getDroppedMessageCount() { mLock->lock(); int count = mDroppedMessageCount; mLock->unlock(); return count; } void OutboundChannel::run() { mLock->lock(); char stopped = mThreadStopped; mLock->unlock(); while( !stopped ) { // get a message from the queue, checking high priority queue first char *message = NULL; mLock->lock(); if( mHighPriorityMessageQueue->size() >= 1 ) { message = *( mHighPriorityMessageQueue->getElement( 0 ) ); mHighPriorityMessageQueue->deleteElement( 0 ); } else if( mMessageQueue->size() >= 1 ) { message = *( mMessageQueue->getElement( 0 ) ); mMessageQueue->deleteElement( 0 ); } mLock->unlock(); // note that we're unlocked during the send, so messages // can be freely added to the queue without blocking while we send // this message if( message != NULL ) { // obey the limit // we will block here if message rate is too high mLimiter->messageTransmitted(); int bytesSent = mStream->writeString( message ); int messageLength = strlen( message ); delete [] message; char sent; if( bytesSent == messageLength ) { sent = true; mLock->lock(); mSentMessageCount++; mLock->unlock(); } else { sent = false; } if( !sent ) { // connection is broken // stop this thread mLock->lock(); mConnectionBroken = true; mThreadStopped = true; mLock->unlock(); } } else { // no messages in the queue. // wait for more messages to be ready mMessageReadySemaphore->wait(); } // check if we've been stopped mLock->lock(); stopped = mThreadStopped; mLock->unlock(); } } primrose-6+dfsg1.orig/minorGems/network/p2pParts/HostCatcher.cpp0000644000175000017500000001516010161606173023537 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2003-July-27 Jason Rohrer * Fixed a bug when catcher is empty. * * 2003-December-21 Jason Rohrer * Fixed a memory leak when catcher is full. * * 2004-January-11 Jason Rohrer * Made include paths explicit to help certain compilers. * * 2004-December-20 Jason Rohrer * Changed to convert to numerical form before comparing against host list. * Changed getHost to return hosts in random order. * Added a getOrderedHost function that returns hosts in linear order. */ #include "minorGems/network/p2pParts/HostCatcher.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/random/StdRandomSource.h" HostCatcher::HostCatcher( int inMaxListSize ) : mMaxListSize( inMaxListSize ), mHostVector( new SimpleVector() ), mLock( new MutexLock() ), mRandSource( new StdRandomSource() ) { } HostCatcher::~HostCatcher() { mLock->lock(); int numHosts = mHostVector->size(); for( int i=0; igetElement( i ) ); } delete mHostVector; mLock->unlock(); delete mLock; delete mRandSource; } void HostCatcher::addHost( HostAddress * inHost ) { // convert to numerical form once and for all here // (to avoid converting over and over in equals checks below) HostAddress *numericalAddress = inHost->getNumericalAddress(); if( numericalAddress != NULL ) { mLock->lock(); // make sure this host doesn't already exist in our list char exists = false; int numHosts = mHostVector->size(); for( int i=0; igetElement( i ) ); if( otherHost->equals( numericalAddress ) ) { exists = true; // jump out of loop i = numHosts; } } if( !exists ) { mHostVector->push_back( numericalAddress->copy() ); } while( mHostVector->size() > mMaxListSize ) { // remove first host from queue HostAddress *host = *( mHostVector->getElement( 0 ) ); mHostVector->deleteElement( 0 ); delete host; } mLock->unlock(); delete numericalAddress; } } HostAddress * HostCatcher::getHostOrdered( ) { mLock->lock(); int numHosts = mHostVector->size(); if( numHosts == 0 ) { mLock->unlock(); return NULL; } // remove first host from queue HostAddress *host = *( mHostVector->getElement( 0 ) ); mHostVector->deleteElement( 0 ); // add host to end of queue mHostVector->push_back( host ); HostAddress *hostCopy = host->copy(); mLock->unlock(); return hostCopy; } HostAddress * HostCatcher::getHost( ) { mLock->lock(); int numHosts = mHostVector->size(); if( numHosts == 0 ) { mLock->unlock(); return NULL; } // remove random host from queue int index = mRandSource->getRandomBoundedInt( 0, numHosts - 1 ); HostAddress *host = *( mHostVector->getElement( index ) ); mHostVector->deleteElement( index ); // add host to end of queue mHostVector->push_back( host ); HostAddress *hostCopy = host->copy(); mLock->unlock(); return hostCopy; } SimpleVector *HostCatcher::getHostList( int inMaxHostCount, HostAddress *inSkipHost ) { HostAddress *hostToSkip; if( inSkipHost != NULL ) { hostToSkip = inSkipHost->copy(); } else { // don't skip any host // create a dummy host that won't match any other valid hosts // make sure dummy is in numerical form to avoid DNS lookups hostToSkip = new HostAddress( stringDuplicate( "1.1.1.1" ), 1 ); } SimpleVector *collectedHosts = new SimpleVector(); char repeat = false; int numCollected = 0; // This function assumes that getHostOrdered() draws // hosts in order with no repetition except when we have // exhausted the host supply. // Note that this will not be true when other threads // have getHostOrdered() (or getHost) calls interleaved with ours, but this // should be a rare case. It will simply result // in a smaller host list being returned. HostAddress *firstHost = getHostOrdered(); if( firstHost == NULL ) { // the catcher is empty delete hostToSkip; // an empty host list return collectedHosts; } if( ! hostToSkip->equals( firstHost ) ) { collectedHosts->push_back( firstHost ); numCollected++; } while( numCollected < inMaxHostCount && !repeat ) { HostAddress *nextHost = getHostOrdered(); if( nextHost->equals( firstHost ) ) { delete nextHost; repeat = true; } else { if( ! hostToSkip->equals( nextHost ) ) { collectedHosts->push_back( nextHost ); numCollected++; } else { delete nextHost; } } } if( hostToSkip->equals( firstHost ) ) { // we didn't include firstHost in our collectedHosts, so // we must delete it. delete firstHost; } delete hostToSkip; return collectedHosts; } void HostCatcher::addHostList( SimpleVector * inHostList ) { int numToAdd = inHostList->size(); for( int i=0; igetElement( i ) ) ); } } void HostCatcher::noteHostBad( HostAddress * inHost ) { mLock->lock(); // make sure this host already exists in our list char exists = false; HostAddress *foundHost = NULL; int numHosts = mHostVector->size(); for( int i=0; igetElement( i ) ); if( otherHost->equals( inHost ) ) { exists = true; // delete the host that we've found mHostVector->deleteElement( i ); foundHost = otherHost; // jump out of loop i = numHosts; } } if( exists ) { delete foundHost; //mHostVector->push_back( foundHost ); } mLock->unlock(); } primrose-6+dfsg1.orig/minorGems/network/p2pParts/HostCatcher.h0000644000175000017500000000730210161606173023203 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2004-December-20 Jason Rohrer * Changed getHost to return hosts in random order. * Added a getOrderedHost function that returns hosts in linear order. */ #ifndef HOST_CATCHER_INCLUDED #define HOST_CATCHER_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/random/RandomSource.h" #include "minorGems/system/MutexLock.h" /** * Manages a collection of hosts. * * @author Jason Rohrer */ class HostCatcher { public: /** * Constructs a host catcher. * * @param inMaxListSize the maximum number of hosts to hold. */ HostCatcher( int inMaxListSize ); ~HostCatcher(); /** * Adds a host to this catcher. * * Thread safe. * * @param inHost the host to add. * Must be destroyed by caller. */ void addHost( HostAddress * inHost ); /** * Gets a "fresh" host from this catcher. * * The returned host is "fresh" in that it has not * been returned by this call in a while. * * Thread safe. * * @return a host, or NULL if there are no hosts. * Must be destroyed by caller if non-NULL. */ HostAddress * getHost( ); /** * Gets a "fresh" host list from this catcher. * The result of this function call is similar to that obtained * by calling getHost inMaxHostCount times and constructing * a HostList from the result, except that this function * will produce a list with no repeated hosts. * * Thread safe. * * @para inMaxHostCount the maximum number of hosts to retrieve. * @param inSkipHost a host to skip when building the list, * or NULL to not skip any host. (Useful * fo constructing a host list at the request of another host.) * Defaults to NULL. Must be destroyed by caller. * * @return a host list containing <= inMaxHostCount hosts. * Vector and addresses must be destroyed by caller. */ SimpleVector *getHostList( int inMaxHostCount, HostAddress *inSkipHost = NULL ); /** * Adds an entire list of hosts to this catcher. * * Thread safe. * * @param inHostList the list to add. * Vector and addresses must be destroyed by caller. */ void addHostList( SimpleVector *inHostList ); /** * Tells this catcher that a host is "bad" * (in other words, dead, dropping connections, etc.). * * Thread safe. * * @param inHost the bad host. * Must be destroyed by caller. */ void noteHostBad( HostAddress * inHost ); protected: int mMaxListSize; SimpleVector *mHostVector; MutexLock *mLock; RandomSource *mRandSource; /** * Gets a "fresh" host from this catcher, walking through the host * list in order. * * The returned host is "fresh" in that it has not * been returned by this call in a while. * * Thread safe. * * @return a host, or NULL if there are no hosts. * Must be destroyed by caller if non-NULL. */ HostAddress *getHostOrdered(); }; #endif primrose-6+dfsg1.orig/minorGems/network/p2pParts/MultiSourceDownloader.cpp0000644000175000017500000000764710154110372025626 0ustar pabspabs/* * Modification History * * 2004-November-21 Jason Rohrer * Created. * * 2004-November-23 Jason Rohrer * Fixed compile errors caused by multiple definitions. * * 2004-December-4 Jason Rohrer * Fixed bug in source indexing. */ #include "MultiSourceDownloader.h" #include int MULTISOURCE_DOWNLOAD_IN_PROGRESS = 0; int MULTISOURCE_DOWNLOAD_FAILED = 1; int MULTISOURCE_DOWNLOAD_CANCELED = 2; void multiSourceGetFile( void *inFileDescriptor, unsigned long inFileSize, unsigned long inChunkSize, int inNumSources, void **inFileSources, unsigned char * (*inChunkGetter)( void *, void *, unsigned long, unsigned long ), char (*inDownloadProgressHandler)( int, unsigned long, void * ), void *inProgressHandlerExtraArgument, char *inDestinationPath ) { FILE *outputFile = fopen( inDestinationPath, "wb" ); if( outputFile == NULL ) { inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_FAILED, 0, inProgressHandlerExtraArgument ); return; } // for now, just fetch chunks in linear order, using each file source // until it fails char failed = false; char canceled = false; unsigned long chunksSoFar = 0; unsigned long numChunks = inFileSize / inChunkSize; if( inFileSize % inChunkSize != 0 ) { // extra partial chunk numChunks++; } unsigned long bytesSoFar = 0; int sourceIndex = 0; while( sourceIndex < inNumSources && !failed && !canceled && chunksSoFar < numChunks ) { void *source = inFileSources[ sourceIndex ]; unsigned long chunkSize = inChunkSize; if( chunksSoFar * inChunkSize + chunkSize > inFileSize ) { // partial chunk chunkSize = inFileSize - chunksSoFar * inChunkSize; } unsigned char *chunkData = inChunkGetter( source, inFileDescriptor, chunksSoFar, chunkSize ); if( chunkData != NULL ) { chunksSoFar += 1; bytesSoFar += chunkSize; unsigned long numWritten = fwrite( chunkData, 1, chunkSize, outputFile ); if( numWritten == chunkSize ) { char shouldContinue = inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_IN_PROGRESS, bytesSoFar, inProgressHandlerExtraArgument ); if( !shouldContinue ) { canceled = true; // call handler last time inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_CANCELED, bytesSoFar, inProgressHandlerExtraArgument ); } } else { // failed to write to file, so download cannot continue inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_FAILED, bytesSoFar, inProgressHandlerExtraArgument ); failed = true; } delete [] chunkData; } else { // else go on to the next host sourceIndex ++; } } // check if we got here because we ran out of hosts (another type of // failure if( !failed && !canceled && chunksSoFar < numChunks ) { inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_FAILED, bytesSoFar, inProgressHandlerExtraArgument ); } fclose( outputFile ); } primrose-6+dfsg1.orig/minorGems/network/p2pParts/protocolUtils.cpp0000644000175000017500000000644507721440564024230 0ustar pabspabs/* * Modification History * * 2003-August-12 Jason Rohrer * Created. * * 2003-August-22 Jason Rohrer * Added function for getting a token after reading. */ #include "minorGems/network/p2pParts/protocolUtils.h" #include "minorGems/util/log/AppLog.h" #include "minorGems/util/stringUtils.h" char *readStreamUpToTag( InputStream *inInputStream, char *inTag, int inMaxCharsToRead ) { char *readCharBuffer = new char[ inMaxCharsToRead + 1 ]; int numCharsRead = 0; char tagSeen = false; char readError = false; int tagLength = strlen( inTag ); // start with empty string readCharBuffer[ numCharsRead ] = '\0'; while( numCharsRead < inMaxCharsToRead && !tagSeen && !readError ) { long numRead = inInputStream->readByte( (unsigned char *) ( &( readCharBuffer[ numCharsRead ] ) ) ); if( numRead != 1 ) { readError = true; readCharBuffer[ numCharsRead ] = '\0'; } else { numCharsRead++; // terminate and check if buffer ends with our tag readCharBuffer[ numCharsRead ] = '\0'; if( numCharsRead > tagLength ) { char *possibleBodyStart = &( readCharBuffer[ numCharsRead - tagLength ] ); if( strcmp( possibleBodyStart, inTag ) == 0 ) { tagSeen = true; } } } } if( !readError && tagSeen ) { char *returnString = stringDuplicate( readCharBuffer ); delete [] readCharBuffer; return returnString; } else { char *message = autoSprintf( "Failed to find end tag \"%s\", read %d characters:\n%s\n", inTag, numCharsRead, readCharBuffer ); AppLog::info( "readStreamUpToTag", message ); delete [] message; delete [] readCharBuffer; return NULL; } } char *readStreamUpToTagAndGetToken( InputStream *inInputStream, char *inTag, int inMaxCharsToRead, int inTokenNumber ) { // read the string char *readString = readStreamUpToTag( inInputStream, inTag, inMaxCharsToRead ); if( readString == NULL ) { return NULL; } SimpleVector *readTokens = tokenizeString( readString ); delete [] readString; // second token should be their key char *selectedToken = NULL; int numTokens = readTokens->size(); if( numTokens > inTokenNumber ) { selectedToken = stringDuplicate( *( readTokens->getElement( inTokenNumber ) ) ); } else { char *message = autoSprintf( "Looking for token %d, but only %d tokens available\n", inTokenNumber, numTokens ); AppLog::error( "readStreamUpToTagAndGetToken", message ); } for( int i=0; igetElement( i ) ); } delete readTokens; // will be NULL if not enough tokens read return selectedToken; } primrose-6+dfsg1.orig/minorGems/network/SocketServer.h0000644000175000017500000000347107554101513021703 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2002-March-27 Jason Rohrer * Added a timeout to accept. */ #include "minorGems/common.h" #ifndef SOCKET_SERVER_CLASS_INCLUDED #define SOCKET_SERVER_CLASS_INCLUDED #include #include "Socket.h" /** * Network socket server that listens for connections on a certain port. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class SocketServer { public: /** * Constructs a SocketServer and begins listening for connections. * * @param inPort the port to listen on. * @param inMaxQueuedConnections the number of connection requests * that will be queued before further requests are refused. */ SocketServer( int inPort, int inMaxQueuedConnections ); ~SocketServer(); /** * Accepts a an incoming connection on our port. * * @param inTimeoutInMilliseconds the timeout in milliseconds, * or -1 for no timeout. Defaults to -1. * @param outTimedOut pre-allocated char where timeout * flag will be returned. If non-NULL, true will * be inserted upon timeout, and false will be inserted * upon other error or no error/timeout. * Must be destroyed by caller if non-NULL. * Defaults to NULL. * * @return a socket for the accepted connection, * or NULL if a socket error/timeout occurred. */ Socket *acceptConnection( long inTimeoutInMilliseconds = -1, char *outTimedOut = NULL ); private: /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; }; #endif primrose-6+dfsg1.orig/minorGems/network/socketTestCompile0000755000175000017500000000065710157336507022513 0ustar pabspabsg++ -g -o socketTest -I../.. socketTest.cpp linux/SocketLinux.cpp linux/SocketClientLinux.cpp linux/SocketServerLinux.cpp linux/HostAddressLinux.cpp ../system/linux/MutexLockLinux.cpp NetworkFunctionLocks.cpp g++ -g -o socketClientTest -I../.. socketClientTest.cpp linux/SocketLinux.cpp linux/SocketClientLinux.cpp linux/SocketServerLinux.cpp linux/HostAddressLinux.cpp ../system/linux/MutexLockLinux.cpp NetworkFunctionLocks.cpp primrose-6+dfsg1.orig/minorGems/network/linux/0000755000175000017500000000000011201637531020243 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/network/linux/gnut_net.c0000644000175000017500000002560107552330061022240 0ustar pabspabs/* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ #include #include #include #ifndef WIN32 #include #include #include #include #include #include #include #include #include #endif #include #include #include #include #include #include #include #include "gnut_lib.h" #include "gnut_threads.h" #include "gnut_if.h" #include "protocol.h" uchar local_ip[4]; // uint32 net_local_ip() // // returns the local ip address // uchar *net_local_ip() { return local_ip; } int gnut_net_host() { char host[256]; struct hostent *he; int ret; g_debug(2,"entering\n"); ret=gethostname(host,sizeof(host)); if (ret<0) { perror("gnut_net_host, gethostname"); return ret; } he=gethostbyname(host); if (he==NULL) { perror("gnut_net_host, gethostbyname"); return ret; } memcpy(local_ip,he->h_addr_list[0],4); return 0; } // int net_init(char *iface) // // Does misc. net init stuff. Mostly just finds our local IP address // int net_init(char *iface) { struct sockaddr_in *sinptr=NULL; g_debug(2,"entering\n"); if (iface!=NULL) { if (inet_aton(iface,(struct in_addr *) local_ip)) { g_debug(1,"local was set by command to: %i.%i.%i.%i\n",local_ip[0],local_ip[1], local_ip[2],local_ip[3]); return 0; } } if ((sinptr = get_if_addr(iface))==NULL) { g_debug(1,"Can't get local IP address through interface, trying host name...\n"); gnut_net_host(); } else { memcpy(local_ip,&(sinptr->sin_addr),sizeof(local_ip)); } g_debug(1,"local ip is: %i.%i.%i.%i\n",local_ip[0],local_ip[1], local_ip[2],local_ip[3]); return 0; } // exactly like the real read, except that it returns -2 // if no data was read before the timeout occurred... int timed_read(int sock, char *buf, int len, int secs) { fd_set fsr; struct timeval tv; int ret; ret=fcntl(sock,F_SETFL,O_NONBLOCK); FD_ZERO(&fsr); FD_SET(sock,&fsr); tv.tv_sec=secs; tv.tv_usec=0; ret=select(sock+1,&fsr,NULL,NULL,&tv); if (ret==0) { return -2; } if (ret<0) return ret; ret=read(sock,buf,len); fcntl(sock,F_SETFL,0); return ret; } // int timed_connect(int sock, struct sockaddr *sa,int addrlen,int secs) // // just like connect except that it times out after time secs // returns -2 on timeout, otherwise same as connect // int timed_connect(int sockfd, struct sockaddr *sa, int addrlen,int secs) { int ret; fd_set fsr; struct timeval tv; int val,len; g_debug(1,"entering sock=%i secs=%i\n",sockfd,secs); ret=fcntl(sockfd,F_SETFL,O_NONBLOCK); g_debug(5,"fcntl returned %i\n",ret); if (ret<0) return ret; ret=connect(sockfd,sa,addrlen); g_debug(5,"connect returned %i\n",ret); if (ret==0) { g_debug(0,"immediate connection!\n"); // wooah! immediate connection return -2; } // if (errno != EINPROGRESS) { // perror("timed_connect, connect"); // return ret; // } FD_ZERO(&fsr); FD_SET(sockfd,&fsr); tv.tv_sec=secs; tv.tv_usec=0; ret=select(sockfd+1,NULL,&fsr,NULL,&tv); g_debug(5,"select returned %i\n",ret); if (ret==0) { // timeout g_debug(1,"timeout\n"); fcntl(sockfd,F_SETFL,0); return -2; } len=4; ret=getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&val,&len); g_debug(5,"getsockopt returned %i val=%i\n",ret,val); if (ret<0) { g_debug(1,"getsockopt returned: %i\n",ret); return ret; } if (val!=0) { g_debug(3,"returning failure!\n"); return -1; } ret=fcntl(sockfd,F_SETFL,0); g_debug(1,"fcntl: %i\n",ret); g_debug(3,"returning success val=%i\n",val); return 0; } // int create_listen_socket(int * port) // // attempts to create a socket to listen on port // returns the actual port bound to in port or <0 if not // successfull // int create_listen_socket(int *port) { struct sockaddr_in sin; int sock; int ret,i; int val; g_debug(3,"entering\n"); sock=socket(AF_INET,SOCK_STREAM,6); if (sock<0) { perror("create_listen_socket, socket"); return sock; } val=1; ret=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val)); i=0; ret=-1; while (ret<0) { sin.sin_addr.s_addr=INADDR_ANY; sin.sin_port=htons(*port); sin.sin_family=AF_INET; ret=bind(sock,(struct sockaddr *) &sin,sizeof(struct sockaddr_in)); if (++i>50) { (*port)++; i=0; } } if (ret<0) { perror("create_listen_socket, bind"); return ret; } ret=listen(sock,5); if (ret<0) { perror("create_listen_socket, listen"); return ret; } g_debug(1,"bound to port %i\n",*port); printf("Bound to port: %i\n",*port); ret=fcntl(sock,F_SETFL,O_NONBLOCK); if (ret<0) { perror("create_listen_socket, fcntl"); return ret; } return sock; } // int read_line(int sock, char *buf, int len) // // reads a line from sock into buf, not exceeding len chars // returns 0 on EOF, -1 on error, or num of characters read // and -2 if buffer length exceeded // int read_line(int sock, char *buf, int len) { int i,ret; char c; char *ptr; ptr=buf; g_debug(3,"entering\n"); fcntl(sock,F_SETFL,0); buf[0]=0; for (i=1;i=1) perror("read_line, read"); return -1; } } buf[i]=0; g_debug(3,"returning success\n"); return i; } #ifndef PTHREADS_DRAFT4 pthread_mutex_t make_connection_mutex=PTHREAD_MUTEX_INITIALIZER; #else pthread_mutex_t make_connection_mutex; #endif struct hostent *gnut_hostent_copy(struct hostent *he) { struct hostent *n; int i,len; if (!he) return NULL; n=(struct hostent *) calloc(sizeof(struct hostent),1); memcpy(n,he,sizeof(struct hostent)); if (he->h_name) n->h_name=strdup(he->h_name); for (len=0;he->h_addr_list[len];len++); n->h_addr_list=(char **) calloc(sizeof(char *) * (len+1),1); for (i=0;ih_addr_list[i]=xmalloc(4); memcpy(n->h_addr_list[i],he->h_addr_list[i],4); } return n; } void gnut_hostent_delete(struct hostent *he) { int i,len; g_debug(1,"entering\n"); for (len=0;he->h_addr_list[len];len++); g_debug(1,"len=%i\n",len); for (i=0;ih_addr_list[i]) free(he->h_addr_list[i]); } g_debug(1,"freeing h_name\n"); if (he->h_name) free(he->h_name); g_debug(1,"freeing h_addr_list\n"); free(he->h_addr_list); g_debug(1,"freeing he\n"); free(he); g_debug(1,"returning\n"); } // int make_connection(char *host, uint port, uchar ip[4]) // // creates a socket, and attempts to make a connection to the host // named. it tries multiple resolved ip addresses if necessary, // returning the socket on success and storing the good ip number in ip // otherwise it returns <0 // // Notes: due to the fact that gethostbyname is not thread safe // we need to protect this function with a mutex // int make_connection(uchar *host, uint port, uchar ip[4]) { struct hostent *he; struct sockaddr_in sin; int i,sock=-1,ret; g_debug(1,"entering\n"); pthread_mutex_lock(&make_connection_mutex); he=gnut_hostent_copy(gethostbyname(host)); if (he==NULL) { pthread_mutex_unlock(&make_connection_mutex); return -1; } pthread_mutex_unlock(&make_connection_mutex); for (i=0,ret=-1;he->h_addr_list[i]!=NULL && ret<0;i++) { g_debug(1,"trying host %i.%i.%i.%i:%i\n", (uchar) he->h_addr_list[i][0],(uchar) he->h_addr_list[i][1], (uchar) he->h_addr_list[i][2],(uchar) he->h_addr_list[i][3],port); sock=socket(AF_INET,SOCK_STREAM,6); if (sock<0) { perror("make_connection, socket"); gnut_hostent_delete(he); return sock; } sin.sin_family=AF_INET; sin.sin_port=htons(port); memcpy(&sin.sin_addr.s_addr,he->h_addr_list[i],4); ret=timed_connect(sock,(struct sockaddr *) &sin, sizeof(struct sockaddr_in),10); g_debug(5,"timed_connect returned: %i\n",ret); if (ret<0) { g_debug(1,"host bad, closing\n"); close(sock); } else { break; } } if (ret<0 || he->h_addr_list[i]==NULL) { g_debug(1,"returning failure\n"); gnut_hostent_delete(he); return -2; } g_debug(5,"about to copy ip from slot %i\n",i); memcpy(ip,he->h_addr_list[i],4); g_debug(4,"trying to unlock mutex\n"); gnut_hostent_delete(he); g_debug(1,"returning success\n"); return sock; } // int send_packet (int sock, gnutella_packet *gpa) // // sends the packet described by gpa over socket sock // return 0 on success or <0 for error // int send_packet(int sock, gnutella_packet *gpa) { int ret; int t; g_debug(3,"entering\n"); ret=write(sock,(char *) &gpa->gh,sizeof(gnutella_hdr)); if (ret<0) { if (gnut_lib_debug>3) perror("send_packet, write header"); return ret; } memcpy(&t,gpa->gh.dlen,4); t=GUINT32_FROM_LE(t); if (t>0) { ret=write(sock,gpa->data,t); if (ret<0) { if (gnut_lib_debug>3) perror("send_packet, write data"); return ret; } } g_debug(3,"returning success\n"); return 23+t; } // int read_packet(int sock, gnutella_packet *gpa) // // reads a packet from the socket sock into the packet // structure of gpa. // returns 0 on success or <0 on error // int read_packet(int sock, gnutella_packet *gpa) { int ret; char *ptr; int left; uint dlen; int i; g_debug(3,"entering\n"); ptr=(char *) &gpa->gh; for (left=sizeof(gnutella_hdr);left>0;) { ret=timed_read(sock,ptr,left,10); g_debug(6,"timed_read returned: %i\n",ret); if (ret==-2) return 0; if (ret==0) { return -2; } else if (ret<0) { if (errno!=EINTR) { if (gnut_lib_debug>3) perror("read_packet, header"); return ret; } else ret=0; } ptr+=ret; left-=ret; } assert(left==0); memcpy(&dlen,gpa->gh.dlen,4); dlen=GUINT32_FROM_LE(dlen); while (dlen>32767 || (gpa->gh.func==129 && dlen>65536)) { // We're out of sync! I'm going to do large reads until // one returns 23, which is probably a ping packet.... g_debug(2,"out of sync! func=%i dlen=%i\n",gpa->gh.func,dlen); ptr=(char *) xmalloc(100); ret=1; i=0; while (ret>0 && ret!=23 && ret!=49) { ret=timed_read(sock,ptr,60,2); g_debug(6,"timed_read returned: %i\n",ret); if (ret==-2 || (++i>5)) { free(ptr); return 0; } } if (ret<=0) { free(ptr); return ret; } free(ptr); memcpy(&gpa->gh,ptr,23); memcpy(&dlen,gpa->gh.dlen,4); dlen=GUINT32_FROM_LE(dlen); } if (dlen>0) { gpa->data=(char *) calloc(dlen,1); ptr=gpa->data; for (left=dlen;left>0;) { ret=timed_read(sock,ptr,left,10); g_debug(6,"timed_read returned: %i\n",ret); if (ret==-2) return 0; if (ret==0) return -2; if (ret<0) { if (gnut_lib_debug>3) perror("read_packet, data"); return ret; } ptr+=ret; left-=ret; } } if (dlen>3000) g_debug(2,"OVERSIZE packet! size: %i\n",dlen); g_debug(3,"returning success\n"); return 23+dlen; } primrose-6+dfsg1.orig/minorGems/network/linux/socketServerTimeoutTest.compile0000755000175000017500000000016007455745246026526 0ustar pabspabsg++ -g -o socketServerTimeoutTest socketServerTimeoutTest.cpp -I../../.. SocketServerLinux.cpp SocketLinux.cpp primrose-6+dfsg1.orig/minorGems/network/linux/SocketClientLinux.cpp0000644000175000017500000001772311165410607024372 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Commented out a redundant print statement (it's better if these kinds * of messages are handled at a higher level). * * 2001-January-28 Jason Rohrer * Changed to comply with new initSocketFramework Socket interface. * * 2001-January-29 Jason Rohrer * Fixed an endian bug with the port number. * * 2001-November-13 Jason Rohrer * Added a missing include. * * 2001-December-12 Jason Rohrer * Changed the include order to make BSD compatible. * * 2002-August-5 Jason Rohrer * Removed use of obsolete call. * * 2002-October-13 Jason Rohrer * Added support for timeout on connect. * * 2002-October-17 Jason Rohrer * Added missing include. * Added support for BSD's version of getsockopt. * * 2002-Novenber-27 Jason Rohrer * Changed to print error number. There's a bug that needs to be fixed. * * 2002-December-2 Jason Rohrer * Fixed resource leak when connection fails. * * 2003-March-18 Jason Rohrer * Fixed a thread safety issue with gethostbyname. * * 2004-January-2 Jason Rohrer * Fixed a memory leak when host name lookup fails. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2006-April-25 Jason Rohrer * Added missing check for a NULL outTimedOut parameter. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * * 2009-April-3 Jason Rohrer * OpenBSD support. */ #include "minorGems/network/SocketClient.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/system/MutexLock.h" #include #include #include #include #include #include #include #include #include #include #include // BSD does not define socklen_t #ifdef BSD #ifndef IPHONE #ifndef __OpenBSD__ typedef int socklen_t; #endif #endif #endif // prototypes struct in_addr *nameToAddress( char *inAddress ); int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ); Socket *SocketClient::connectToServer( HostAddress *inAddress, long inTimeoutInMilliseconds, char *outTimedOut ) { if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } int socketID = socket( AF_INET, SOCK_STREAM, 0 ); if( socketID == -1 ) { printf( "Creating socket failed, error %d.\n", errno ); return NULL; } union sock { struct sockaddr s; struct sockaddr_in i; } sock; struct in_addr *internet_address = nameToAddress( inAddress->mAddressString ); if( internet_address == NULL ) { printf( "Host name lookup failed: " ); inAddress->print(); printf( "\n" ); close( socketID ); return NULL; } sock.i.sin_family = AF_INET; sock.i.sin_port = htons( inAddress->mPort ); sock.i.sin_addr = *internet_address; int error; if( inTimeoutInMilliseconds != -1 ) { // use timeout error = timed_connect( socketID, &sock.s, sizeof( struct sockaddr ), inTimeoutInMilliseconds ); if( outTimedOut != NULL ) { if( error == -2 ) { *outTimedOut = true; if( inTimeoutInMilliseconds == 0 ) { // caller didn't want to wait at all error = 0; } else { // treat timeout as error error = -1; } } else { *outTimedOut = false; } } } else { // don't use timeout error = connect( socketID, &sock.s, sizeof( struct sockaddr ) ); } delete internet_address; if( error == -1 ) { //printf( "Connecting to host failed: " ); //inAddress->print(); //printf( "\n" ); close( socketID ); return NULL; } // package into a Socket and return it Socket *returnSocket = new Socket(); int *idSpace = new int[1]; idSpace[0] = socketID; returnSocket->mNativeObjectPointer = (void *)idSpace; if( *outTimedOut ) { // not connected yet returnSocket->setConnected( false ); } return returnSocket; } /* Converts ascii text to in_addr struct. NULL is returned if the address can not be found. Result must be destroyed by caller. Adapted from the Unix Socket FAQ */ struct in_addr *nameToAddress( char *inAddress ) { struct hostent *host; static struct in_addr saddr; struct in_addr *copiedSaddr = new struct in_addr; /* First try it as aaa.bbb.ccc.ddd. */ // this is obsolete on linux // saddr.s_addr = inet_addr( inAddress ); int error = inet_aton( inAddress, &saddr ); if( error != 0 ) { // copy to avoid returning pointer to stack memcpy( copiedSaddr, &saddr, sizeof( struct in_addr ) ); return copiedSaddr; } // must keep this locked until we are done copying the in_addr out // of the returned hostent NetworkFunctionLocks::mGetHostByNameLock.lock(); char hostFound = false; host = gethostbyname( inAddress ); if( host != NULL ) { memcpy( copiedSaddr, *host->h_addr_list, sizeof( struct in_addr ) ); hostFound = true; } NetworkFunctionLocks::mGetHostByNameLock.unlock(); if( hostFound ) { return copiedSaddr; } else { delete copiedSaddr; } return NULL; } /* timed_connect adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // just like connect except that it times out after time secs // returns -2 on timeout, otherwise same as connect int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ) { int ret; fd_set fsr; struct timeval tv; int val; socklen_t len; //g_debug(1,"entering sock=%i secs=%i\n",inSocketID,inTimeoutInSeconds); ret = fcntl( inSocketID, F_SETFL, O_NONBLOCK ); //g_debug(5,"fcntl returned %i\n",ret); if( ret < 0 ) { return ret; } ret = connect( inSocketID, inSocketAddress, inAddressLength ); //g_debug(5,"connect returned %i\n",ret); if( ret == 0 ) { //g_debug(0,"immediate connection!\n"); // wooah! immediate connection // return -2; // changed from what Josh originally returned (-2) // immediate connection *can* happen sometimes, right? // for example, when connecting to localhost... return 0; } // if (errno != EINPROGRESS) { // perror("timed_connect, connect"); // return ret; // } FD_ZERO( &fsr ); FD_SET( inSocketID, &fsr ); tv.tv_sec = inTimeoutInMilliseconds / 1000; int remainder = inTimeoutInMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSocketID+1, NULL, &fsr, NULL, &tv ); //g_debug(5,"select returned %i\n",ret); if( ret==0 ) { // timeout //g_debug(1,"timeout\n"); fcntl( inSocketID, F_SETFL, 0 ); return -2; } len = 4; ret = getsockopt( inSocketID, SOL_SOCKET, SO_ERROR, &val, &len ); //g_debug(5,"getsockopt returned %i val=%i\n",ret,val); if( ret < 0 ) { //g_debug(1,"getsockopt returned: %i\n",ret); return ret; } if (val!=0) { //g_debug(3,"returning failure!\n"); return -1; } ret = fcntl( inSocketID, F_SETFL, 0 ); //g_debug(1,"fcntl: %i\n",ret); //g_debug(3,"returning success val=%i\n",val); return 0; } primrose-6+dfsg1.orig/minorGems/network/linux/socketServerTimeoutTest.cpp0000644000175000017500000000226007455745246025660 0ustar pabspabs/* * Modification History * * 2002-April-12 Jason Rohrer * Created. */ #include "minorGems/network/Socket.h" #include "minorGems/network/SocketServer.h" #include void usage( char *inAppName ); int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 2 ) { usage( inArgs[0] ); } int port; int numRead = sscanf( inArgs[1], "%d", &port ); if( numRead != 1 ) { usage( inArgs[0] ); } SocketServer *server = new SocketServer( port, 100 ); char timedOut; Socket *sock; printf( "waiting for connection on port %d\n", port ); sock = server->acceptConnection( 5000, &timedOut ); if( timedOut ) { printf( "timed out after 5 seconds, waiting again\n" ); sock = server->acceptConnection( 5000, &timedOut ); } if( !timedOut && sock != NULL ) { printf( "connection received\n" ); delete sock; } else { printf( "timed out again\n" ); } delete server; return 1; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( " %s port_number\n", inAppName ); exit( 1 ); } primrose-6+dfsg1.orig/minorGems/network/linux/gnut_lib.c0000644000175000017500000000401707552330060022215 0ustar pabspabs/* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ #include #include #include #include #include #ifndef WIN32 #include #endif #ifdef MCHECK #include #endif #include "gnut_lib.h" #include "gnut_threads.h" int gnut_mprobe(void *d) { #ifdef MCHECK return mprobe(d); #else return 0; #endif } #ifndef HAVE_XMALLOC #ifndef xmalloc char *xmalloc(int size) { char *ptr; ptr=malloc(size); if (!ptr) { g_debug(0,"malloc(%d) failed!\n", size); exit(1); } return ptr; } #endif #endif char *expand_path(char *a) { char *b; if (strncmp(a,"~/", 2)==0) { #ifndef WIN32 char *c; c=getenv("HOME"); #else char c[MAX_PATH]; GetWindowsDirectory(c, MAX_PATH); #endif b=(char *)xmalloc(strlen(a)+strlen(c)+1); strcpy(b, c); strcat(b, &a[1]); return b; } b=(char *) xmalloc(strlen(a)+1); strcpy(b,a); return b; } int gnut_lib_debug=0; #ifndef PTHREADS_DRAFT4 pthread_mutex_t _g_debug_mutex=PTHREAD_MUTEX_INITIALIZER; #else pthread_mutex_t _g_debug_mutex; #endif #ifndef WIN32 void _g_debug(char *file, int line, int num, char *format, ...) { va_list argp; if (gnut_lib_debug>=num) { pthread_mutex_lock(&_g_debug_mutex); fprintf(stderr,"%i %s:%i > ", getpid(),file,line); fflush(stdout); va_start(argp,format); vfprintf(stderr,format,argp); va_end(argp); pthread_mutex_unlock(&_g_debug_mutex); } } #else void g_debug(int a, char *format, ...) { va_list argp; if (gnut_lib_debug>=a) { pthread_mutex_lock(&_g_debug_mutex); fprintf(stderr,"%li > ", (long) pthread_self()); va_start(argp,format); vfprintf(stderr,format,argp); va_end(argp); pthread_mutex_unlock(&_g_debug_mutex); } } #endif char *gnut_strdelimit(char *string, char *delim, char new_delim) { char *c; for (c=string;*c;c++) { if (strchr(delim,*c)) *c=new_delim; } return string; } primrose-6+dfsg1.orig/minorGems/network/linux/SocketServerLinux.cpp0000644000175000017500000001322110016416560024405 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Commented out redundant status messages that should be handled at a * higher level. * * 2001-January-28 Jason Rohrer * Changed to comply with new initSocketFramework Socket interface. * * 2001-January-29 Jason Rohrer * Fixed an endian bug with the port number. * * 2001-May-12 Jason Rohrer * Added a port number to the "bad socket bind" error message. * * 2001-November-13 Jason Rohrer * Added a missing include. * * 2001-December-12 Jason Rohrer * Changed some type usage and the include order to make BSD compatible. * Added a BSD definition test to make socklen_t type compatible * on both BSD and Linux. * * 2002-March-27 Jason Rohrer * Added a timeout to accept. * * 2002-March-29 Jason Rohrer * Fixed a bug in return value when accept fails. * * 2002-April-11 Jason Rohrer * Changed to use select instead of poll to make it more portable. * Fixed a bug in the timeout implementation. * * 2002-April-12 Jason Rohrer * Changed to use poll on Linux and select on BSD, * since select does not seem to work on LinuxX86. * Fixed X86 accept/select bug by getting rid of union * and some unused parameters (it seems that stack space was a problem). * * 2004-February-23 Jason Rohrer * Added socket option to clear up lingering bound ports after shutdown. * Changed to close server socket instead of using shutdown. */ #include "minorGems/network/SocketServer.h" #include #include #include #include #include #include #include // BSD does not define socklen_t #ifdef BSD typedef int socklen_t; #else // poll not available on BSD #include #endif /** * BSD Compilation note: * * Use g++ option -DBSD to define the BSD preprocessor variable. */ SocketServer::SocketServer( int inPort, int inMaxQueuedConnections ) { int error = 0; if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); exit( 1 ); } } // create the socket int sockID = socket( AF_INET, SOCK_STREAM, 0 ); if( sockID == -1 ) { printf( "Failed to construct a socket\n" ); exit( 1 ); } // store socket id in native object pointer int *idStorage = new int[1]; idStorage[0] = sockID; mNativeObjectPointer = (void *)idStorage; // this setsockopt code partially copied from gnut // set socket option to enable reusing addresses so that the socket is // unbound immediately when the server is shut down // (otherwise, rebinding to the same port will fail for a while // after the server is shut down) int reuseAddressValue = 1; error = setsockopt( sockID, SOL_SOCKET, // socket-level option SO_REUSEADDR, // reuse address option &reuseAddressValue, // value to set for this option sizeof( reuseAddressValue) ); // size of the value if( error == -1 ) { printf( "Failed to set socket options\n" ); exit( 1 ); } // bind socket to the port struct sockaddr_in address; address.sin_family = AF_INET; address.sin_port = htons( inPort ); address.sin_addr.s_addr = INADDR_ANY; error = bind( sockID, (struct sockaddr *) &address, sizeof( address ) ); if( error == -1 ) { printf( "Bad socket bind, port %d\n", inPort ); exit( 1 ); } // start listening for connections error = listen( sockID, inMaxQueuedConnections ); if( error == -1 ) { printf( "Bad socket listen\n" ); exit(1); } } SocketServer::~SocketServer() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; close( socketID ); delete [] socketIDptr; } Socket *SocketServer::acceptConnection( long inTimeoutInMilliseconds, char *outTimedOut ) { // printf( "Waiting for a connection.\n" ); // extract socket id from native object pointer int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( outTimedOut != NULL ) { *outTimedOut = false; } if( inTimeoutInMilliseconds != -1 ) { // if we have a timeout specified, select before accepting // this found in the Linux man page for select, // but idea (which originally used poll) was found // in the Unix Socket FAQ fd_set rfds; struct timeval tv; int retval; // insert our socket descriptor into this set FD_ZERO( &rfds ); FD_SET( socketID, &rfds ); // convert our timeout into the structure's format tv.tv_sec = inTimeoutInMilliseconds / 1000; tv.tv_usec = ( inTimeoutInMilliseconds % 1000 ) * 1000 ; retval = select( socketID + 1, &rfds, NULL, NULL, &tv ); if( retval == 0 ) { // timeout if( outTimedOut != NULL ) { *outTimedOut = true; } return NULL; } } int acceptedID = accept( socketID, NULL, NULL ); if( acceptedID == -1 ) { printf( "Failed to accept a network connection.\n" ); return NULL; } else { Socket *acceptedSocket = new Socket(); int *idStorage = new int[1]; idStorage[0] = acceptedID; acceptedSocket->mNativeObjectPointer = (void *)idStorage; //printf( "Connection received.\n" ); return acceptedSocket; } } primrose-6+dfsg1.orig/minorGems/network/linux/HostAddressLinux.cpp0000644000175000017500000000631707776034461024240 0ustar pabspabs/* * Modification History * * 2001-December-14 Jason Rohrer * Created. * Fixed a typo. * Added a missing include. * * 2002-March-25 Jason Rohrer * Added function for conversion to numerical addresses. * * 2002-March-26 Jason Rohrer * Changed to use strdup. * Fixed problem on some platforms where local address does * not include domain name. * Fixed so that numerical address is actually retrieved by * getNumericalAddress(). * * 2002-April-6 Jason Rohrer * Replaced use of strdup. * * 2002-April-8 Jason Rohrer * Changed to return numerical address from getLocalAddress, * since it is simpler, and we probably want the numerical * address anyway. * This new implementation also fixes a BSD domain-name lookup bug. * Changed to check if address is numerical before * performing a lookup on it. * * 2002-July-10 Jason Rohrer * Fixed a bug that occurs when fetching numerical address fails. * * 2004-January-4 Jason Rohrer * Added use of network function locks. */ #include "minorGems/network/HostAddress.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/util/stringUtils.h" #include #include #include #include #include HostAddress *HostAddress::getLocalAddress() { int bufferLength = 200; char *buffer = new char[ bufferLength ]; gethostname( buffer, bufferLength ); char *name = stringDuplicate( buffer ); delete [] buffer; // this class will destroy name for us HostAddress *nameAddress = new HostAddress( name, 0 ); HostAddress *fullAddress = nameAddress->getNumericalAddress(); if( fullAddress != NULL ) { delete nameAddress; return fullAddress; } else { return nameAddress; } } HostAddress *HostAddress::getNumericalAddress() { // make sure we're not already numerical if( this->isNumerical() ) { return this->copy(); } // need to use two function locks here // first, lock for gethostbyname NetworkFunctionLocks::mGetHostByNameLock.lock(); struct hostent *host = gethostbyname( mAddressString ); if (host != NULL) { // this line adapted from the // Unix Socket FAQ struct in_addr *inetAddress = (struct in_addr *) *host->h_addr_list; // now lock for inet_ntoa NetworkFunctionLocks::mInet_ntoaLock.lock(); // the returned string is statically allocated, so copy it char *inetAddressString = stringDuplicate( inet_ntoa( *inetAddress ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); // done with returned hostent now, so unlock first lock NetworkFunctionLocks::mGetHostByNameLock.unlock(); return new HostAddress( inetAddressString, mPort ); } else { // unlock first lock before returning NetworkFunctionLocks::mGetHostByNameLock.unlock(); return NULL; } } char HostAddress::isNumerical() { struct in_addr addressStruct; int isValid = inet_aton( mAddressString, &addressStruct ); if( isValid == 0 ) { return false; } else { return true; } } primrose-6+dfsg1.orig/minorGems/network/linux/socketSelectAcceptBug.cpp0000644000175000017500000000600707455757734025210 0ustar pabspabs/* * Demonstration of "accept after select" socket bug. * * This program works fine on: * LinuxPPC, FreeBSD, and MacOSX * * This program does not work on: * LinuxX86 Kernel 2.4 * (accept fails after select returns) * * This bug has something to do with the size of the * variables on the stack... * Getting rid of the union (which is unnecessary) seems * to fix the problem. * * * Jason Rohrer * 2002-April-12 * rohrer@cse.ucsc.edu */ #include #include #include #include #include #include #include #include union sock { struct sockaddr s; struct sockaddr_in i; } sock; void usage( char *inAppName ); int acceptConnection( int inSocketID, long inTimeoutMS ); int port; int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 2 ) { usage( inArgs[0] ); } int numRead = sscanf( inArgs[1], "%d", &port ); // create a socket and start listening for connections printf( "Creating socket\n" ); int socketID = socket( AF_INET, SOCK_STREAM, 0 ); if( socketID == -1 ) { printf( "Socket creation failed\n" ); exit( 1 ); } // bind socket to the port union sock sockAddress; sockAddress.i.sin_family = AF_INET; sockAddress.i.sin_port = htons( port ); sockAddress.i.sin_addr.s_addr = INADDR_ANY; printf( "Binding to socket at port %d\n", port ); int error = bind( socketID, &(sockAddress.s), sizeof( struct sockaddr ) ); if( error == -1 ) { printf( "Bad socket bind, port %d\n", port ); exit( 1 ); } // start listening for connections, max queued = 100 connections printf( "Starting to listen to socket\n" ); error = listen( socketID, 100 ); if( error == -1 ) { printf( "Bad socket listen\n" ); exit(1); } // no we're listening to this socket int acceptedID = acceptConnection( socketID, 50000 ); if( acceptedID != -1 ) { // close the connection shutdown( acceptedID, SHUT_RDWR ); close( acceptedID ); } shutdown( socketID, SHUT_RD ); return 1; } int acceptConnection( int inSocketID, long inTimeoutMS ) { // use select to timeout if no connection received in 10 seconds struct timeval tv; socklen_t addressLength; union sock acceptedAddress; int acceptedID = accept( inSocketID, &( acceptedAddress.s ), &addressLength ); if( acceptedID == -1 ) { printf( "Failed to accept the connection\n" ); printf( "Error = %d\n", errno ); return -1; } else { printf( "Successfully accepted the connection\n" ); return acceptedID; } } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( " %s port_number\n", inAppName ); exit( 1 ); } primrose-6+dfsg1.orig/minorGems/network/linux/socketSelectAcceptBug.compile0000755000175000017500000000007107455750432026040 0ustar pabspabsg++ -g -o socketSelectAcceptBug socketSelectAcceptBug.cppprimrose-6+dfsg1.orig/minorGems/network/linux/SocketLinux.cpp0000644000175000017500000002074511165410607023231 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-10 Jason Rohrer * Fixed a bug in the receive code (in use of timed_read). * * 2001-January-15 Jason Rohrer * Added a safeguard against receives that exceed the * network buffer size. * * 2001-January-28 Jason Rohrer * Changed to comply with new initSocketFramework Socket interface. * Added a close() call to the destructor. * * 2001-January-29 Jason Rohrer * Fixed compile bug by including unistd.h for close call. * * 2001-November-13 Jason Rohrer * Changed to use ::send function instead of __send function. * Changed timeout parameter to signed, since -1 is a possible argument. * * 2001-December-12 Jason Rohrer * Changed the include order to make BSD compatible. * * 2002-August-2 Jason Rohrer * Changed to ignore SIGPIPE. * Added functon for getting remote host address. * Added fix for linux-BSD differences. * * 2002-November-15 Jason Rohrer * Fixed a security hole when getting the remote host address. * * 2003-February-3 Jason Rohrer * Added a function for getting the local host address from a socket. * * 2003-February-21 Jason Rohrer * Fixed a BSD compatibility bug. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2004-March-23 Jason Rohrer * Removed timeout error message. * * 2004-December13 Jason Rohrer * Added a breakConnection function. * * 2005-July-5 Jason Rohrer * Added port number when getting address of remote host. * * 2006-May-28 Jason Rohrer * Changed timeout behavior slightly to support emulation of non-blocking mode. * Added support for non-blocking sends. * * 2006-June-5 Jason Rohrer * Fixed error checking for non-blocking sends. * * 2006-June-23 Jason Rohrer * Changed implementation of non-blocking sends to work on Mac. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * Fixed close-detection in non-blocking read. * * 2009-April-3 Jason Rohrer * OpenBSD support. */ #include "minorGems/network/Socket.h" #include "minorGems/network/NetworkFunctionLocks.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // BSD does not define socklen_t #ifdef BSD #ifndef IPHONE #ifndef __OpenBSD__ typedef int socklen_t; #endif #endif #endif // prototypes int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ); /** * Linux-specific implementation of the Socket class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * no special options needed */ char Socket::sInitialized = false; int Socket::initSocketFramework() { // ignore SIGPIPE, which occurs on send whenever the receiver // has closed the socket signal(SIGPIPE, SIG_IGN); sInitialized = true; return 0; } Socket::~Socket() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { shutdown( socketID, SHUT_RDWR ); mIsConnectionBroken = true; } close( socketID ); delete [] socketIDptr; } int Socket::isConnected() { if( mConnected ) { return 1; } int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int ret; fd_set fsr; struct timeval tv; int val; socklen_t len; FD_ZERO( &fsr ); FD_SET( socketID, &fsr ); // check if connection event waiting right now // timeout of 0 tv.tv_sec = 0; tv.tv_usec = 0; ret = select( socketID + 1, NULL, &fsr, NULL, &tv ); if( ret==0 ) { // timeout return 0; } // no timeout // error? len = 4; ret = getsockopt( socketID, SOL_SOCKET, SO_ERROR, &val, &len ); if( ret < 0 ) { // error return -1; } if( val != 0 ) { // error return -1; } // success mConnected = true; return 1; } int Socket::send( unsigned char *inBuffer, int inNumBytes, char inAllowedToBlock ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( inAllowedToBlock ) { return ::send( socketID, inBuffer, inNumBytes, 0 ); } else { // set to non-blocking mode int result = fcntl( socketID, F_SETFL, O_NONBLOCK ); if( result < 0 ) { return result; } int returnValue = ::send( socketID, inBuffer, inNumBytes, // no flags 0 ); // back into blocking mode result = fcntl( socketID, F_SETFL, 0 ); if( result < 0 ) { return result; } if( returnValue == -1 && errno == EAGAIN ) { return -2; } else { return returnValue; } } } int Socket::receive( unsigned char *inBuffer, int inNumBytes, long inTimeout ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( inTimeout == -1 ) { // use MSG_WAITALL flag here to block until inNumBytes has arrived return recv( socketID, inBuffer, inNumBytes, MSG_WAITALL ); } else { return timed_read( socketID, inBuffer, inNumBytes, inTimeout ); } } void Socket::breakConnection() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { shutdown( socketID, SHUT_RDWR ); mIsConnectionBroken = true; } close( socketID ); } HostAddress *Socket::getRemoteHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from Unix Socket FAQ socklen_t len; struct sockaddr_in sin; len = sizeof sin; int error = getpeername( socketID, (struct sockaddr *) &sin, &len ); if( error ) { return NULL; } // this is potentially insecure, since a fake DNS name might be returned // we should use the IP address only // // struct hostent *host = gethostbyaddr( (char *) &sin.sin_addr, // sizeof sin.sin_addr, // AF_INET ); NetworkFunctionLocks::mInet_ntoaLock.lock(); // returned string is statically allocated, copy it char *ipAddress = stringDuplicate( inet_ntoa( sin.sin_addr ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); int port = ntohs( sin.sin_port ); return new HostAddress( ipAddress, port ); } HostAddress *Socket::getLocalHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from GTK-gnutalla code, and elsewhere struct sockaddr_in addr; socklen_t len = sizeof( struct sockaddr_in ); int result = getsockname( socketID, (struct sockaddr*)( &addr ), &len ); if( result == -1 ) { return NULL; } else { char *stringAddress = inet_ntoa( addr.sin_addr ); return new HostAddress( stringDuplicate( stringAddress ), 0 ); } } /* timed_read adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // exactly like the real read, except that it returns -2 // if no data was read before the timeout occurred... int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ) { fd_set fsr; struct timeval tv; int ret; //ret = fcntl( inSock, F_SETFL, O_NONBLOCK ); FD_ZERO( &fsr ); FD_SET( inSock, &fsr ); tv.tv_sec = inMilliseconds / 1000; int remainder = inMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSock + 1, &fsr, NULL, NULL, &tv ); if( ret==0 ) { // printf( "Timed out waiting for data on socket receive.\n" ); return -2; } if( ret<0 ) { printf( "Selecting socket during receive failed.\n" ); return ret; } // do not use MSG_WAITALL flag here, since we just want to return // data that is available ret = recv( inSock, inBuf, inLen, 0 ); if( ret == 0 ) { // select came back as 1, but no data there // connection closed on remote end return -1; } //fcntl( inSock, F_SETFL, 0 ); return ret; } primrose-6+dfsg1.orig/minorGems/network/linux/gnut_lib.h0000644000175000017500000000435207552330061022225 0ustar pabspabs/* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ #ifndef GNUT_LIB_H #define GNUT_LIB_H 0 #include #ifndef WIN32 #include #include #endif #ifdef DMALLOC #include #endif #ifndef MIN #define MIN(a,b) (((a < b)) ? (a) : (b)) #define MAX(a,b) (((a > b)) ? (a) : (b)) #endif #ifndef __bswap_16 #define __bswap_16(x) \ ((((x) >> 8) & 0xff) | (((x) &0xff) <<8)) #endif #ifndef __bswap_32 #define __bswap_32(x) \ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) #endif #ifndef GUINT16_TO_LE #ifdef WORDS_BIGENDIAN #define GUINT16_TO_LE(x) __bswap_16(x) #define GUINT32_TO_LE(x) __bswap_32(x) #define GUINT16_FROM_LE(x) __bswap_16(x) #define GUINT32_FROM_LE(x) __bswap_32(x) #else #define GUINT16_TO_LE(x) (x) #define GUINT32_TO_LE(x) (x) #define GUINT16_FROM_LE(x) (x) #define GUINT32_FROM_LE(x) (x) #endif #endif typedef unsigned int uint32; typedef unsigned short uint16; typedef unsigned char uchar; #ifndef WIN32 typedef unsigned long long uint64; //#define g_debug(num, format, args... ) #define g_debug(num, format, args... ) _g_debug(__FUNCTION__,__LINE__, num, format, ##args) void _g_debug(char *,int,int num, char *,...); #endif extern int gnut_lib_debug; int gnut_mprobe(void *); char *gnut_strdelimit(char *string, char *delimeters, char new_delim); char *expand_path(char *); #ifndef xmalloc char *xmalloc(int size); #endif #ifdef WIN32 #include #define VERSION "0.3.22/win32" void g_debug(int, char *, ...); typedef unsigned __int64 uint64; typedef unsigned int uint; #define sleep Sleep char *strtok_r(char *, const char *, char **); int getopt(int argc, char *argv[], char *); extern char *optarg; extern int optind; #define strncasecmp strnicmp #define inet_aton(string, ip) (ip)->s_addr = inet_addr(string) #define write(sock, buf, len) send(sock, buf, len, 0) #define read(sock, buf, len) recv(sock, buf, len, 0) #define close(sock) closesocket(sock) #define F_SETFL 1 #define O_NONBLOCK 1 int fcntl(int sock, int, uint); #define flock(a,b) 0 #endif #endif primrose-6+dfsg1.orig/minorGems/network/Socket.h0000644000175000017500000002214011070507667020516 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-28 Jason Rohrer * Added a static framework init function. * * 2001-November-13 Jason Rohrer * Changed timeout parameter to signed, since -1 is a possible argument. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-August-2 Jason Rohrer * Added functon for getting remote host address. * * 2003-February-3 Jason Rohrer * Added a function for getting the local host address from a socket. * * 2003-August-12 Jason Rohrer * Added more verbose comment about receive timeout parameter. * Added a function for flushing socket sends. * * 2003-November-20 Jason Rohrer * Made flush function robust against bogus receive return values. * * 2004-December13 Jason Rohrer * Added a breakConnection function. * * 2005-July-5 Jason Rohrer * Added port number when getting address of remote host. * * 2006-May-28 Jason Rohrer * Changed timeout behavior slightly to support emulation of non-blocking mode. * Added support for non-blocking sends. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. */ #include "minorGems/common.h" #ifndef SOCKET_CLASS_INCLUDED #define SOCKET_CLASS_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/system/Time.h" #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Network socket. Does not contain an interface for listening to connections * (see SocketServer for these interfaces) or for establishing connections * (see SocketClient for these interfaces). * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class Socket { public: /** * Constructor for a socket. * * Should not be called directly. Use SocketClient or SocketServer * to obtain an outbound or inbound socket connection. */ Socket(); // destroying a Socket closes the connection ~Socket(); /** * Initializes the socket framework. Must be called * once by program before sockets are used. Note * that SocketClient and SocketServer both should call * init automatically when they are first used. * * @return 0 on success, or -1 on failure. */ static int initSocketFramework(); /** * Gets whether the socket framework has been initialized. * * @return true if the framework has been initialized. */ static char isFrameworkInitialized(); /** * For outbound sockets that were opened in non-blocking mode: * * Get whether socket is connected yet. * * @return 1 on success, 0 on still waiting, -1 on error. */ int isConnected(); /** * Sends bytes through this socket. * * @param inBuffer the buffer of bytes to send. * @param inNumBytes the number of bytes to send. * @param inAllowedToBlock set to false to prevent blocking. * Defaults to true. * * @return the number of bytes sent successfully, * or -1 for a socket error. * Returns -2 if not allowed to block and the operation * would block. */ int send( unsigned char *inBuffer, int inNumBytes, char inAllowedToBlock = true ); /** * Receives bytes from this socket. * * @param inBuffer the buffer where received bytes will be put. * Must be pre-allocated memory space. * @param inNumBytes the number of bytes to read from the socket. * @param inTimeout the timeout for this receive operation in * milliseconds. Set to -1 for an infinite timeout. * -2 is returned from this call in the event of a timeout. * If timeout is set, only available data is returned (up * to, but not more than inNumBytes). The socket does not * wait for all inNumBytes to become available before returning. * Thus, a timeout return value (-2) means no data was available * before the timeout. If some data is available, we never * time out. If no timeout is set (-1 for infinite), the socket * waits for all inNumBytes to arrive before returning. * Thus, setting a timeout of 0 effectively puts the socket * into non-blocking mode. * * @return the number of bytes read successfully, * or -1, -2 for a socket error or timeout, respectively. */ int receive( unsigned char *inBuffer, int inNumBytes, long inTimeout ); /** * Flushes sent data through the socket. * * Intended to be called before deleting the socket to ensure * that data goes through. The mechanism used by this function * does not guarantee that data goes through, but it works * better than simply closing the socket on many platforms. * * The method used by this call works best if the remote * host closes the connection. For example, if we send the * remote host a "connection closing" indicator, then * call writeFlushBeforeClose, and the remote host closes * the connection upon receiving the indicator, all of our * sent data will be received by the remote host after * writeFlushBeforeClose returns (assuming that the maximum * time is long enough for the remote host to actually close * the connection). * * Good maximum times should be in the several-second range, * though the Apache system uses 30 seconds. For slow connections, * this might be necessary. * * This call will cause any received data to be discarded. * * This call DOES NOT close the socket. The socket must be deleted * as usual after this call returns. * * @param inMaxTimeInMilliseconds the maximum time to wait * in milliseconds. This call may block slightly longer than * this if the remote host is still sending data. */ void sendFlushBeforeClose( int inMaxTimeInMilliseconds ); /** * Forces this socket's connection to break, causing any blocked * send or receive operations to fail. * * Note that this operation is inherently not thread-safe, so * some external mechanism must be used to ensure that the socket * is not destroyed by another thread before breakConnection is called. * The SocketManager class is one such external mechanism. */ void breakConnection(); /** * Gets the host connected to the other end of this socket. * * @return the address of the remote host, or NULL if obtaining * the address fails. The port of the returned address * will always be set to the port that the host is connecting from. * Must be destroyed by caller if non-NULL. */ HostAddress *getRemoteHostAddress(); /** * Gets the local address attached to this socket. * * Getting the local address from a socket is more * accurate than non-connected methods (for example, the methods * used in HostAddress.h implementations. * * @return the address of the local host, or NULL if obtaining * the address fails. The port of the returned address * will always be set to 0. * Must be destroyed by caller if non-NULL. */ HostAddress *getLocalHostAddress(); /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; // called by socket client to set connected status void setConnected( char inConnected ) { mConnected = inConnected; } private: static char sInitialized; char mConnected; char mIsConnectionBroken; }; inline Socket::Socket() : mConnected( true ), mIsConnectionBroken( false ) { } inline char Socket::isFrameworkInitialized() { return sInitialized; } inline void Socket::sendFlushBeforeClose( int inMaxTimeInMilliseconds ) { unsigned char *tempBuffer = new unsigned char[1]; int numRead = -2; int timeout = 1000; if( timeout > inMaxTimeInMilliseconds ) { timeout = inMaxTimeInMilliseconds; } long totalTimeout = 0; unsigned long startSec; unsigned long startMsec; Time::getCurrentTime( &startSec, &startMsec ); // keep reading data from socket until we get an error // or wait too long (pass our max timeout) while( numRead != -1 && totalTimeout < inMaxTimeInMilliseconds ) { numRead = this->receive( tempBuffer, 1, timeout ); // track total time whether the receive timed out or not totalTimeout = (long)( Time::getMillisecondsSince( startSec, startMsec ) ); } delete [] tempBuffer; } #endif primrose-6+dfsg1.orig/minorGems/network/socketClientTest.cpp0000644000175000017500000000560307620021426023103 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-28 Jason Rohrer * Added more output. * Changed so that it doesn't sleep in the middle of a block * since the requirements of the socket interface have changed * and implementations no longer have to support this behavior. * * 2001-December-12 Jason Rohrer * Changed to use new HostAddress constructor. * * 2002-July-30 Jason Rohrer * Fixed a bug in localhost address. Added a test of streams. * * 2002-July-31 Jason Rohrer * Changed to test multiple blocks. * * 2002-December-2 Jason Rohrer * Changed to test socket creation failure. * Added counter to output. * * 2002-February-4 Jason Rohrer * Added test of getting local address from socket. */ #include "Socket.h" #include "SocketStream.h" #include "SocketServer.h" #include "SocketClient.h" #include "HostAddress.h" #include int main() { char *name = new char[99]; sprintf( name, "63.249.65.249" ); //char *name = new char[99]; //sprintf( name, "192.168.1.2" ); //char *name = "192.168.1.1"; //int addressLength = 11; //char *name = "monolith.2y.net"; //int addressLength = 15; int port = 5158; HostAddress *address = new HostAddress( name, port ); printf( "Trying to connect to server: " ); address->print(); printf( "\n" ); Socket *sock; int numConnections = 0; while( true ) { sock = SocketClient::connectToServer( address ); if( sock == NULL ) { printf( "%d Connecting to server failed\n", numConnections ); //return 1; } else { printf( "%d Connection established\n", numConnections ); HostAddress *localAddress = sock->getLocalHostAddress(); if( localAddress != NULL ) { printf( "Our local address (fetched from socket) is " ); localAddress->print(); printf( "\n" ); delete localAddress; } delete sock; } //usleep( 1000 ); numConnections++; } int numBytes = 4000; unsigned char *buffer = new unsigned char[numBytes]; for( int i=0; iwrite( buffer, numBytes ); printf( "Sent %d successfully,\tcount = %d\n", numSent, count ); count++; } int checksum = 0; for( int i=0; i /** * A SocketStream that logs inbound and outbound data. * * @author Jason Rohrer */ class LoggingSocketStream : public SocketStream { public: /** * Constructs a SocketStream. * * @param inSocket the newtork socket wrapped by this stream. * inSocket is NOT destroyed when the stream is destroyed. * @param inEnableInboundLog set to true to enable inbound logging. * @param inEnableOutboundLog set to true to enable outbound logging. * @param inLogSizeLimit the size limit of each log (both inbound * and outbound), in bytes. * Logging will stop after inLogSizeLimit bytes have been * written to each log. * @param inLogNamePrefix a string that will be used to name * the log files (appending .in and .out for the two logs). * Should be unique. * Must be destroyed by caller. */ LoggingSocketStream( Socket *inSocket, char inEnableInboundLog, char inEnableOutboundLog, unsigned long inLogSizeLimit, char *inLogNamePrefix ); virtual ~LoggingSocketStream(); // overrides the SocketStream implementations long read( unsigned char *inBuffer, long inNumBytes ); long write( unsigned char *inBuffer, long inNumBytes ); protected: char mEnableInboundLog; char mEnableOutboundLog; unsigned long mLogSizeLimit; FILE *mInboundLogFile; FILE *mOutboundLogFile; unsigned long mInboundSizeSoFar; unsigned long mOutboundSizeSoFar; }; inline LoggingSocketStream::LoggingSocketStream( Socket *inSocket, char inEnableInboundLog, char inEnableOutboundLog, unsigned long inLogSizeLimit, char *inLogNamePrefix ) : SocketStream( inSocket ), mEnableInboundLog( inEnableInboundLog ), mEnableOutboundLog( inEnableOutboundLog ), mLogSizeLimit( inLogSizeLimit ), mInboundLogFile( NULL ), mOutboundLogFile( NULL ), mInboundSizeSoFar( 0 ), mOutboundSizeSoFar( 0 ) { if( mEnableInboundLog ) { char *inboundFileName = autoSprintf( "%s.in", inLogNamePrefix ); mInboundLogFile = fopen( inboundFileName, "wb" ); delete [] inboundFileName; } if( mEnableOutboundLog ) { char *outboundFileName = autoSprintf( "%s.out", inLogNamePrefix ); mOutboundLogFile = fopen( outboundFileName, "wb" ); delete [] outboundFileName; } } inline LoggingSocketStream::~LoggingSocketStream() { if( mInboundLogFile != NULL ) { fclose( mInboundLogFile ); mInboundLogFile = NULL; } if( mOutboundLogFile != NULL ) { fclose( mOutboundLogFile ); mOutboundLogFile = NULL; } } inline long LoggingSocketStream::read( unsigned char *inBuffer, long inNumBytes ) { long returnVal = SocketStream::read( inBuffer, inNumBytes ); if( mEnableInboundLog && mInboundSizeSoFar < mLogSizeLimit && returnVal == inNumBytes ) { int numToLog = inNumBytes; if( mInboundSizeSoFar + numToLog > mLogSizeLimit ) { numToLog = mLogSizeLimit - mInboundSizeSoFar; } if( mInboundLogFile != NULL ) { fwrite( inBuffer, 1, numToLog, mInboundLogFile ); fflush( mInboundLogFile ); } mInboundSizeSoFar += numToLog; } return returnVal; } inline long LoggingSocketStream::write( unsigned char *inBuffer, long inNumBytes ) { long returnVal = SocketStream::write( inBuffer, inNumBytes ); if( mEnableOutboundLog && mOutboundSizeSoFar < mLogSizeLimit && returnVal == inNumBytes ) { int numToLog = inNumBytes; if( mOutboundSizeSoFar + numToLog > mLogSizeLimit ) { numToLog = mLogSizeLimit - mOutboundSizeSoFar; } if( mOutboundLogFile != NULL ) { fwrite( inBuffer, 1, numToLog, mOutboundLogFile ); fflush( mOutboundLogFile ); } mOutboundSizeSoFar += numToLog; } return returnVal; } #endif primrose-6+dfsg1.orig/minorGems/network/LookupThread.h0000644000175000017500000000272111145450322021656 0ustar pabspabs/* * Modification History * * 2008-October-21 Jason Rohrer * Created. * * 2009-February-3 Jason Rohrer * Changed to subclass FinishedSignalThread. * * 2009-February-14 Jason Rohrer * Changed to copy inAddress internally. */ #ifndef LOOKUP_THREAD_CLASS_INCLUDED #define LOOKUP_THREAD_CLASS_INCLUDED #include "minorGems/system/FinishedSignalThread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/network/HostAddress.h" /** * Thread that performs DNS lookup on a host name. * * @author Jason Rohrer */ class LookupThread : public FinishedSignalThread { public: /** * Constructs and starts a lookup thread. * * @param inAddress the address to lookup. Destroyed by caller, * copied internally. */ LookupThread( HostAddress *inAddress ); // joins and destroys this thread ~LookupThread(); /** * Returns true if lookup done. */ char isLookupDone(); /** * Returns numerical address result, or NULL if lookup failed. * * Must be destroyed by caller if non-NULL. */ HostAddress *getResult(); // override the run method from Thread void run(); private: MutexLock mLock; HostAddress *mAddress; HostAddress *mNumericalAddress; char mLookupDone; }; #endif primrose-6+dfsg1.orig/minorGems/network/win32/0000755000175000017500000000000011201637531020046 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/network/win32/SocketWin32.cpp0000644000175000017500000002375411101230232022622 0ustar pabspabs/* * Modification History * * 2001-January-28 Jason Rohrer * Created. * * 2001-February-4 Jason Rohrer * Fixed receive so that it waits for all requested bytes to arrive. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2001-May-12 Jason Rohrer * Fixed a bug in socket receive error checking. * * 2001-November-13 Jason Rohrer * Changed timeout parameter to signed, since -1 is a possible argument. * * 2002-April-15 Jason Rohrer * Removed call to WSAGetLastError, since it seems to pick up errors from * non-socket calls. For example, if sys/stat.h stat() is called on a file * that does not exist, WSAGetLastError returns 2, which is not even a * winsock error code. We should probably report this bug, huh? * * 2002-August-2 Jason Rohrer * Added functon for getting remote host address, but no implementation. * * 2002-August-5 Jason Rohrer * Added implementation of getRemoteHostAddress(). * * 2002-September-8 Jason Rohrer * Fixed a major looping bug with broken sockets. * * 2002-November-15 Jason Rohrer * Fixed a security hole when getting the remote host address. * * 2003-February-4 Jason Rohrer * Added a function for getting the local host address from a socket. * Still need to test the win32 version of this. * * 2003-February-5 Jason Rohrer * Fixed a bug in call to gethostname. Removed unused variable. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2004-January-11 Jason Rohrer * Fixed a bug in handling of timeout return value. * * 2004-March-23 Jason Rohrer * Removed timeout error message. * * 2004-December-13 Jason Rohrer * Added a breakConnection function. * * 2004-December-24 Jason Rohrer * Fixed bug in close call. * * 2005-July-5 Jason Rohrer * Added port number when getting address of remote host. * * 2006-May-28 Jason Rohrer * Changed timeout behavior slightly to support emulation of non-blocking mode. * * 2006-June-5 Jason Rohrer * Added support for non-blocking sends. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * Fixed close-detection in non-blocking read. */ #include "minorGems/network/Socket.h" #include "minorGems/network/NetworkFunctionLocks.h" #include #include #include #include #include // prototypes int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ); /** * Windows-specific implementation of the Socket class member functions. * */ // Win32 does not define socklen_t typedef int socklen_t; char Socket::sInitialized = false; int Socket::initSocketFramework() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // no usable DLL found printf( "WinSock DLL version 1.0 or higher not found.\n" ); return -1; } sInitialized = true; return 0; } Socket::~Socket() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { // 2 specifies shutting down both sends and receives shutdown( socketID, 2 ); mIsConnectionBroken = true; } closesocket( socketID ); delete [] socketIDptr; } int Socket::isConnected() { if( mConnected ) { return 1; } int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int ret; fd_set fsr; struct timeval tv; int val; socklen_t len; FD_ZERO( &fsr ); FD_SET( socketID, &fsr ); // check if connection event waiting right now // timeout of 0 tv.tv_sec = 0; tv.tv_usec = 0; ret = select( socketID + 1, NULL, &fsr, NULL, &tv ); if( ret==0 ) { // timeout return 0; } // no timeout // error? len = 4; ret = getsockopt( socketID, SOL_SOCKET, SO_ERROR, (char*)( &val ), &len ); if( ret < 0 ) { // error return -1; } if( val != 0 ) { // error return -1; } // success mConnected = true; return 1; } int Socket::send( unsigned char *inBuffer, int inNumBytes, char inAllowedToBlock ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( inAllowedToBlock ) { return ::send( socketID, (char*)inBuffer, inNumBytes, 0 ); } else { // 1 for non-blocking, 0 for blocking u_long socketMode = 1; ioctlsocket( socketID, FIONBIO, &socketMode ); int result = ::send( socketID, (char*)inBuffer, inNumBytes, 0 ); // set back to blocking socketMode = 0; ioctlsocket( socketID, FIONBIO, &socketMode ); if( result == -1 && WSAGetLastError() == WSAEWOULDBLOCK ) { return -2; } else { return result; } } } int Socket::receive( unsigned char *inBuffer, int inNumBytes, long inTimeout ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int numReceived = 0; char error = false; char errorReturnValue = -1; char stopLooping = false; // for win32, we can't specify MSG_WAITALL // so we have too loop until the entire message is received, // as long as there is no error. // note that if a timeout is set, we use the stopLooping flag // to return only the available data (we do not emulate MSG_WAITALL) while( numReceived < inNumBytes && !error && !stopLooping ) { // the number of bytes left to receive int numRemaining = inNumBytes - numReceived; // pointer to the spot in the buffer where the // remaining bytes should be stored unsigned char *remainingBuffer = &( inBuffer[ numReceived ] ); int numReceivedIn; if( inTimeout == -1 ) { numReceivedIn = recv( socketID, (char*)remainingBuffer, numRemaining, 0 ); } else { numReceivedIn = timed_read( socketID, remainingBuffer, numRemaining, inTimeout ); // stop looping after one timed read stopLooping = true; } if( numReceivedIn > 0 ) { numReceived += numReceivedIn; } else { error = true; if( numReceivedIn == 0 ) { // the socket was gracefully closed errorReturnValue = -1; } else if( numReceivedIn == SOCKET_ERROR ) { // socket error errorReturnValue = -1; } else if( numReceivedIn == -2 ) { // timeout errorReturnValue = -2; } else { printf( "Unexpected return value from socket receive: %d.\n", numReceivedIn ); errorReturnValue = -1; } } } if( error ) { return errorReturnValue; } else { return numReceived; } } void Socket::breakConnection() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { shutdown( socketID, 2 ); mIsConnectionBroken = true; } closesocket( socketID ); } HostAddress *Socket::getRemoteHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from Unix Socket FAQ socklen_t len; struct sockaddr_in sin; len = sizeof sin; int error = getpeername( socketID, (struct sockaddr *) &sin, &len ); if( error ) { return NULL; } // this is potentially insecure, since a fake DNS name might be returned // we should use the IP address only // // struct hostent *host = gethostbyaddr( (char *) &sin.sin_addr, // sizeof sin.sin_addr, // AF_INET ); NetworkFunctionLocks::mInet_ntoaLock.lock(); // returned string is statically allocated, copy it char *ipAddress = stringDuplicate( inet_ntoa( sin.sin_addr ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); int port = ntohs( sin.sin_port ); return new HostAddress( ipAddress, port ); } HostAddress *Socket::getLocalHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from GTK-gnutalla code, and elsewhere struct sockaddr_in addr; int len = sizeof( struct sockaddr_in ); int result = getsockname( socketID, (struct sockaddr*)( &addr ), &len ); if( result == -1 ) { return NULL; } else { char *stringAddress = inet_ntoa( addr.sin_addr ); return new HostAddress( stringDuplicate( stringAddress ), 0 ); } } /* timed_read adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // exactly like the real read, except that it returns -2 // if no data was read before the timeout occurred... int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ) { fd_set fsr; struct timeval tv; int ret; FD_ZERO( &fsr ); FD_SET( inSock, &fsr ); tv.tv_sec = inMilliseconds / 1000; int remainder = inMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSock + 1, &fsr, NULL, NULL, &tv ); if( ret==0 ) { // printf( "Timed out waiting for data on socket receive.\n" ); return -2; } if( ret<0 ) { printf( "Selecting socket during receive failed.\n" ); return ret; } ret = recv( inSock, (char*)inBuf, inLen, 0 ); if( ret == 0 ) { // select came back as 1, but no data there // connection closed on remote end return -1; } return ret; } primrose-6+dfsg1.orig/minorGems/network/win32/HostAddressWin32.cpp0000644000175000017500000000715111103257444023626 0ustar pabspabs/* * Modification History * * 2001-December-14 Jason Rohrer * Created. * Has not been compiled or tested under windows. * * 2002-March-25 Jason Rohrer * Added function for conversion to numerical addresses. * * 2002-March-26 Jason Rohrer * Changed to use strdup. * Fixed problem on some platforms where local address does * not include domain name. * Fixed so that numerical address is actually retrieved by * getNumericalAddress(). * * 2002-April-6 Jason Rohrer * Replaced use of strdup. * * 2002-April-7 Jason Rohrer * Changed to return numerical address from getLocalAddress, * since getdomainname() call not available on Win32. * * 2002-April-8 Jason Rohrer * Changed to init socket framework before getting local address. * Changed to check if address is numerical before * performing a lookup on it. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2008-November-2 Jason Rohrer * Added framework init in getNumericalAddress. */ #include "minorGems/network/HostAddress.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/util/stringUtils.h" #include #include #include #include "minorGems/network/Socket.h" HostAddress *HostAddress::getLocalAddress() { // first make sure sockets are initialized if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } int bufferLength = 200; char *buffer = new char[ bufferLength ]; gethostname( buffer, bufferLength ); char *name = stringDuplicate( buffer ); delete [] buffer; // this class will destroy name for us HostAddress *nameAddress = new HostAddress( name, 0 ); HostAddress *fullAddress = nameAddress->getNumericalAddress(); delete nameAddress; return fullAddress; } HostAddress *HostAddress::getNumericalAddress() { // make sure we're not already numerical if( this->isNumerical() ) { return this->copy(); } if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } // need to use two function locks here // first, lock for gethostbyname NetworkFunctionLocks::mGetHostByNameLock.lock(); struct hostent *host = gethostbyname( mAddressString ); if (host != NULL) { // this line adapted from the // Unix Socket FAQ struct in_addr *inetAddress = (struct in_addr *) *host->h_addr_list; // now lock for inet_ntoa NetworkFunctionLocks::mInet_ntoaLock.lock(); // the returned string is statically allocated, so copy it char *inetAddressString = stringDuplicate( inet_ntoa( *inetAddress ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); // done with returned hostent now, so unlock first lock NetworkFunctionLocks::mGetHostByNameLock.unlock(); return new HostAddress( inetAddressString, mPort ); } else { // unlock first lock before returning NetworkFunctionLocks::mGetHostByNameLock.unlock(); return NULL; } } char HostAddress::isNumerical() { unsigned long returnedValue = inet_addr( mAddressString ); if( returnedValue == INADDR_NONE ) { return false; } else { return true; } } primrose-6+dfsg1.orig/minorGems/network/win32/SocketClientWin32.cpp0000644000175000017500000001706411101230232023756 0ustar pabspabs/* * Modification History * * 2001-January-28 Jason Rohrer * Created. * * 2001-January-29 Jason Rohrer * Fixed an endian bug that was messing up the port numbers. * * 2002-October-13 Jason Rohrer * Added support for timeout on connect. * Fixed several windows compile bugs. * * 2002-December-2 Jason Rohrer * Fixed resource leak when connection fails. * Changed close calls to win32 closesocket calls. * * 2004-January-2 Jason Rohrer * Fixed a thread safety issue with gethostbyname. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2006-April-25 Jason Rohrer * Added missing check for a NULL outTimedOut parameter. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. */ #include "minorGems/network/SocketClient.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/system/MutexLock.h" #include #include #include #include #include // prototypes struct in_addr *nameToAddress( char *inAddress ); int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ); Socket *SocketClient::connectToServer( HostAddress *inAddress, long inTimeoutInMilliseconds, char *outTimedOut ) { if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } unsigned long socketID = socket( AF_INET, SOCK_STREAM, 0 ); if( socketID == INVALID_SOCKET ) { printf( "Creating socket failed.\n" ); return NULL; } union sock { struct sockaddr s; struct sockaddr_in i; } sock; //struct in_addr internet_address; //struct hostent *hp; struct in_addr *internet_address = nameToAddress( inAddress->mAddressString ); if( internet_address == NULL ) { printf( "Host name lookup failed: " ); inAddress->print(); printf( "\n" ); closesocket( socketID ); return NULL; } //hp = gethostbyname( inAddress->mAddressString ); //memcpy( &internet_address, *( hp->h_addr_list ), sizeof( struct in_addr ) ); sock.i.sin_family = AF_INET; sock.i.sin_port = htons( inAddress->mPort ); sock.i.sin_addr = *internet_address; int error; if( inTimeoutInMilliseconds != -1 ) { // use timeout error = timed_connect( socketID, &sock.s, sizeof( struct sockaddr ), inTimeoutInMilliseconds ); if( outTimedOut != NULL ) { if( error == -2 ) { *outTimedOut = true; if( inTimeoutInMilliseconds == 0 ) { // caller didn't want to wait at all error = 0; } else { // treat timeout as error error = -1; } } else { *outTimedOut = false; } } } else { // don't use timeout error = connect( socketID, &sock.s, sizeof( struct sockaddr ) ); } delete internet_address; if( error == -1 ) { //printf( "Connecting to host failed: " ); //inAddress->print(); //printf( "\n" ); closesocket( socketID ); return NULL; } // package into a Socket and return it Socket *returnSocket = new Socket(); unsigned long *idSpace = new unsigned long[1]; idSpace[0] = socketID; returnSocket->mNativeObjectPointer = (void *)idSpace; if( *outTimedOut ) { // not connected yet returnSocket->setConnected( false ); } return returnSocket; } /* Converts ascii text to in_addr struct. NULL is returned if the address can not be found. Result must be destroyed by caller. Adapted from the Unix Socket FAQ */ struct in_addr *nameToAddress( char *inAddress ) { struct hostent *host; static struct in_addr saddr; struct in_addr *copiedSaddr = new struct in_addr; /* First try it as aaa.bbb.ccc.ddd. */ saddr.s_addr = inet_addr( inAddress ); if( saddr.s_addr != INADDR_NONE ) { // copy to avoid returning pointer to stack memcpy( copiedSaddr, &saddr, sizeof( struct in_addr ) ); return copiedSaddr; } // must keep this locked until we are done copying the in_addr out // of the returned hostent NetworkFunctionLocks::mGetHostByNameLock.lock(); char hostFound = false; host = gethostbyname( inAddress ); if( host != NULL ) { memcpy( copiedSaddr, *host->h_addr_list, sizeof( struct in_addr ) ); hostFound = true; } NetworkFunctionLocks::mGetHostByNameLock.unlock(); if( hostFound ) { return copiedSaddr; } else { delete copiedSaddr; } return NULL; } /* timed_read adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // just like connect except that it times out after time secs // returns -2 on timeout, otherwise same as connect int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ) { int ret; fd_set fsr; struct timeval tv; int val; int len; //g_debug(1,"entering sock=%i secs=%i\n",inSocketID,inTimeoutInSeconds); //ret = fcntl( inSocketID, F_SETFL, O_NONBLOCK ); // use ioctlsocket on win32 instead of fcntl // set to non-blocking mode unsigned long onFlag = 1; ret = ioctlsocket( inSocketID, FIONBIO, &onFlag ); //g_debug(5,"fcntl returned %i\n",ret); if( ret < 0 ) { return ret; } ret = connect( inSocketID, inSocketAddress, inAddressLength ); //g_debug(5,"connect returned %i\n",ret); if( ret == 0 ) { //g_debug(0,"immediate connection!\n"); // wooah! immediate connection // return -2; // changed from what Josh originally returned (-2) // immediate connection *can* happen sometimes, right? // for example, when connecting to localhost... return 0; } // if (errno != EINPROGRESS) { // perror("timed_connect, connect"); // return ret; // } FD_ZERO( &fsr ); FD_SET( inSocketID, &fsr ); tv.tv_sec = inTimeoutInMilliseconds / 1000; int remainder = inTimeoutInMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSocketID+1, NULL, &fsr, NULL, &tv ); //g_debug(5,"select returned %i\n",ret); if( ret==0 ) { // timeout //g_debug(1,"timeout\n"); //fcntl( inSocketID, F_SETFL, 0 ); unsigned long offFlag = 0; ret = ioctlsocket( inSocketID, FIONBIO, &offFlag ); return -2; } len = 4; ret = getsockopt( inSocketID, SOL_SOCKET, SO_ERROR, (char*)( &val ), &len ); //g_debug(5,"getsockopt returned %i val=%i\n",ret,val); if( ret < 0 ) { //g_debug(1,"getsockopt returned: %i\n",ret); return ret; } if (val!=0) { //g_debug(3,"returning failure!\n"); return -1; } //ret = fcntl( inSocketID, F_SETFL, 0 ); // use ioctlsocket on win32 instead of fcntl // set back to blocking mode unsigned long offFlag = 0; ret = ioctlsocket( inSocketID, FIONBIO, &offFlag ); //g_debug(1,"fcntl: %i\n",ret); //g_debug(3,"returning success val=%i\n",val); return 0; } primrose-6+dfsg1.orig/minorGems/network/win32/WSABugDemo.cpp0000644000175000017500000000140207457040432022452 0ustar pabspabs#include #include #include #include int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // no usable DLL found printf( "WinSock DLL version 1.0 or higher not found.\n" ); return -1; } int error = WSAGetLastError(); printf( "WSA Error before stat call = %d\n", error ); struct stat fileInfo; int statError = stat( "DoesNotExist", &fileInfo ); printf( "stat error = %d\n", statError ); error = WSAGetLastError(); printf( "WSA Error after stat call = %d\n", error ); return 0; } primrose-6+dfsg1.orig/minorGems/network/win32/SocketServerWin32.cpp0000644000175000017500000000762710016424475024034 0ustar pabspabs/* * Modification History * * 2001-January-28 Jason Rohrer * Created. * * 2001-January-29 Jason Rohrer * Fixed an endian bug that was messing up the port numbers. * * 2002-April-6 Jason Rohrer * Changed to implement the new timeout-on-accept interface, * though did no actually implement timeouts. * * 2002-September-8 Jason Rohrer * Added a check for a potentially NULL argument. * * 2004-February-23 Jason Rohrer * Added timeout code for accepting connections. * Removed use of shutdown on listening socket. */ #include "minorGems/network/SocketServer.h" #include #include union sock { struct sockaddr s; struct sockaddr_in i; } sock; SocketServer::SocketServer( int inPort, int inMaxQueuedConnections ) { int error = 0; if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); exit( 1 ); } } // create the socket int sockID = socket( AF_INET, SOCK_STREAM, 0 ); if( sockID == INVALID_SOCKET ) { printf( "Creating socket failed.\n" ); exit( 1 ); } // store socket id in native object pointer int *idStorage = new int[1]; idStorage[0] = sockID; mNativeObjectPointer = (void *)idStorage; // bind socket to the port union sock sockAddress; sockAddress.i.sin_family = AF_INET; sockAddress.i.sin_port = htons( inPort ); sockAddress.i.sin_addr.s_addr = INADDR_ANY; error = bind( sockID, &(sockAddress.s), sizeof( struct sockaddr ) ); if( error == -1 ) { printf( "Network socket bind to port %d failed\n", inPort ); exit( 1 ); } // start listening for connections error = listen( sockID, inMaxQueuedConnections ); if( error == -1 ) { printf( "Listening for network socket connections failed.\n" ); exit(1); } } SocketServer::~SocketServer() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; closesocket( socketID ); delete [] socketIDptr; } Socket *SocketServer::acceptConnection( long inTimeoutInMilliseconds, char *outTimedOut ) { if( outTimedOut != NULL ) { *outTimedOut = false; } // printf( "Waiting for a connection.\n" ); // extract socket id from native object pointer int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // same timeout code as in linux version if( inTimeoutInMilliseconds != -1 ) { // if we have a timeout specified, select before accepting // this found in the Linux man page for select, // but idea (which originally used poll) was found // in the Unix Socket FAQ fd_set rfds; struct timeval tv; int retval; // insert our socket descriptor into this set FD_ZERO( &rfds ); FD_SET( socketID, &rfds ); // convert our timeout into the structure's format tv.tv_sec = inTimeoutInMilliseconds / 1000; tv.tv_usec = ( inTimeoutInMilliseconds % 1000 ) * 1000 ; retval = select( socketID + 1, &rfds, NULL, NULL, &tv ); if( retval == 0 ) { // timeout if( outTimedOut != NULL ) { *outTimedOut = true; } return NULL; } } //int addressLength; //union sock acceptedAddress; struct sockaddr acceptedAddress; //int addressLength = sizeof( struct sockaddr ); int acceptedID = accept( socketID, &( acceptedAddress ), NULL ); if( acceptedID == -1 ) { printf( "Failed to accept a network connection.\n" ); return NULL; } Socket *acceptedSocket = new Socket(); int *idStorage = new int[1]; idStorage[0] = acceptedID; acceptedSocket->mNativeObjectPointer = (void *)idStorage; //printf( "Connection received.\n" ); return acceptedSocket; } primrose-6+dfsg1.orig/minorGems/network/SocketStream.h0000644000175000017500000000712510005505371021663 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Changed so that underlying socket is not destroyed when the stream * is destroyed. Updated to match new Stream interface, which uses longs * instead of ints. * * 2001-February-21 Jason Rohrer * Changed to set stream error messages on socket errors. * * 2002-July-31 Jason Rohrer * Added fix for partial sends. * * 2003-August-12 Jason Rohrer * Added support for read timeouts. * * 2004-January-27 Jason Rohrer * Made functions virtual to support subclassing. */ #include "minorGems/common.h" #ifndef SOCKET_STREAM_CLASS_INCLUDED #define SOCKET_STREAM_CLASS_INCLUDED #include "Socket.h" #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" /** * A input and output stream interface for a network socket. * * @author Jason Rohrer */ class SocketStream : public InputStream, public OutputStream { public: /** * Constructs a SocketStream. * * @param inSocket the newtork socket wrapped by this stream. * inSocket is NOT destroyed when the stream is destroyed. */ SocketStream( Socket *inSocket ); // a virtual destructor to ensure that subclass destructors are called virtual ~SocketStream(); /** * Sets the timeout for reads on this socket. * * The timeout defaults to -1 (no timeout). * * @param inMilliseconds the timeout in milliseconds, * or -1 to specify no timeout. */ void setReadTimeout( long inMilliseconds ); /** * Gets the timeout for reads on this socket. * * @return the timeout in milliseconds, * or -1 to indicate no timeout. */ long getReadTimeout(); // implements the InputStream interface. // virtual to allow subclasses to override // in addition, -2 is returned if the read times out. virtual long read( unsigned char *inBuffer, long inNumBytes ); // implements the OutputStream interface virtual long write( unsigned char *inBuffer, long inNumBytes ); protected: Socket *mSocket; long mReadTimeout; }; inline SocketStream::SocketStream( Socket *inSocket ) : mSocket( inSocket ), mReadTimeout( -1 ) { } inline SocketStream::~SocketStream() { // does nothing // exists only to allow for subclass destructors } inline void SocketStream::setReadTimeout( long inMilliseconds ) { mReadTimeout = inMilliseconds; } inline long SocketStream::getReadTimeout() { return mReadTimeout; } inline long SocketStream::read( unsigned char *inBuffer, long inNumBytes ) { int numReceived = mSocket->receive( inBuffer, inNumBytes, mReadTimeout ); if( numReceived == -1 ) { // socket error InputStream::setNewLastErrorConst( "Network socket error on receive." ); } return numReceived; } inline long SocketStream::write( unsigned char *inBuffer, long inNumBytes ) { long numTotalSent = 0; while( numTotalSent < inNumBytes ) { unsigned char *partialBuffer = &( inBuffer[numTotalSent] ); int numRemaining = inNumBytes - numTotalSent; int numSent = mSocket->send( partialBuffer, numRemaining ); if( numSent == -1 || numSent == 0 ) { // socket error OutputStream::setNewLastErrorConst( "Network socket error on send." ); return -1; } numTotalSent += numSent; } return numTotalSent; } #endif primrose-6+dfsg1.orig/minorGems/network/Message.h0000644000175000017500000000162507554101513020647 0ustar pabspabs/* * Modification History * * 2001-January-15 Jason Rohrer * Created. * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. */ #include "minorGems/common.h" #ifndef MESSAGE_CLASS_INCLUDED #define MESSAGE_CLASS_INCLUDED #include "minorGems/io/Serializable.h" /** * A simple message that carries a 4 byte opcode. Useful for sending a * simple service request. * * @author Jason Rohrer */ class Message : public Serializable { public: long mOpcode; // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline int Message::serialize( OutputStream *inOutputStream ) { return inOutputStream->writeLong( mOpcode ); } inline int Message::deserialize( InputStream *inInputStream ) { return inInputStream->readLong( &mOpcode ); } #endif primrose-6+dfsg1.orig/minorGems/math/0000755000175000017500000000000011201637530016343 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/math/BigInt.h0000644000175000017500000001045707474074412017712 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * Made getZero static. */ #ifndef BIG_INT_INCLUDED #define BIG_INT_INCLUDED /** * A multi-byte integer representation. * * Some of the ideas used in this class were gleaned * from studying Sun's Java 1.3 BigInteger implementation. * * @author Jason Rohrer. */ class BigInt { public: /** * Constructs an integer. * * @param inSign the sign of this integer: * -1 if negative, +1 if positive, and 0 if zero. * @param inNumBytes the number of bytes in this integer. * @param inBytes the bytes for this integer. * Copied internally, so must be destroyed by caller. */ BigInt( int inSign, int inNumBytes, unsigned char *inBytes ); /** * Constructs an integer from a 32-bit int. * * @param inInt the int to use. */ BigInt( int inInt ); ~BigInt(); /** * Adds an integer to this integer. * * @praram inOtherInt the int to add. * Must be destroyed by caller. * * @return a newly allocated integer containing the sum. * Must be destroyed by caller. */ BigInt *add( BigInt *inOtherInt ); /** * Subtracts an integer from this integer. * * @praram inOtherInt the int to subtract. * Must be destroyed by caller. * * @return a newly allocated integer containing the difference. * Must be destroyed by caller. */ BigInt *subtract( BigInt *inOtherInt ); /** * Gets whether this integer is less than another integer. * * @praram inOtherInt the integer test. * Must be destroyed by caller. * * @return true if this integer is less than the other. */ char isLessThan( BigInt *inOtherInt ); /** * Gets whether this integer is equal to another integer. * * @praram inOtherInt the integer test. * Must be destroyed by caller. * * @return true if this integer is equal to the other. */ char isEqualTo( BigInt *inOtherInt ); /** * Gets a copy of this integer. * * @return a newly allocated integer containing the copy. * Must be destroyed by caller. */ BigInt *copy(); /** * Gets an integer equal to zero. * * @return a newly allocated integer containing zero. * Must be destroyed by caller. */ static BigInt *getZero(); /** * Converts this integer to a decimal string. * * @return a \0-terminated ascii decimal string. * Must be destroyed by caller. */ //char *convertToDecimalString(); /** * Converts this integer to a hex string. * * @return a \0-terminated ascii hexx string. * Must be destroyed by caller. */ char *convertToHexString(); /** * Converts this integer to a 32-bit int. * * If this integer contains more than 32-bits, the high-order * bits will be discarded, though the sign will be preserved. */ int convertToInt(); /** * -1 if negative, +1 if positive, and 0 if zero. */ int mSign; int mNumBytes; /** * Integer is stored in big endian byte order. */ unsigned char *mBytes; protected: /** * Flips the byte order of this integer. * * @return a newly allocated integer containing the flipped version. * Must be destroyed by caller. */ BigInt *flipByteOrder(); /** * Computes the hex representation of a four-bit int. * * @param inInt the four-bit int to convert. * * @return the int as a hex ascii character, * in {0, 1, ..., A, B, ..., F}. */ char fourBitIntToHex( int inInt ); }; #endif primrose-6+dfsg1.orig/minorGems/math/stats/0000755000175000017500000000000011201637530017501 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/math/stats/PairwiseOrderingErrorEvaluator.h0000644000175000017500000000237007215720625026036 0ustar pabspabs/* * Modification History * * 2000-September-28 Jason Rohrer * Created. */ #ifndef PAIRWISE_ORDERING_ERROR_EVALUATOR_INCLUDED #define PAIRWISE_ORDERING_ERROR_EVALUATOR_INCLUDED #include "ErrorEvaluator.h" /** * Implementation of ErrorEvaluator that generates an error * value based on the number of pairs of elements in the * the test vector that are not given the same order by their values * as are the corresponding pair of values in the correct vector. * * I.e., if A[i] > A[j], then B[i] < B[j] adds 1 to the error term, * while B[i] > B[j] adds 0 to the error term. * * @author Jason Rohrer */ class PairwiseOrderingErrorEvaluator : public ErrorEvaluator { // implements ErrorEvaluator interface double evaluate( double *inVectorA, double *inVectorB, int inLength ); }; inline double PairwiseOrderingErrorEvaluator::evaluate( double *inVectorA, double *inVectorB, int inLength ) { double sum = 0; // examine all pairs of components in the vectors for( int i=0; i inVectorA[j] && inVectorB[i] <= inVectorB[j] ) || ( inVectorA[i] < inVectorA[j] && inVectorB[i] >= inVectorB[j] ) ) { sum++; } } } return sum; } #endif primrose-6+dfsg1.orig/minorGems/math/stats/ErrorEvaluator.h0000644000175000017500000000131107215720625022632 0ustar pabspabs/* * Modification History * * 2000-September-28 Jason Rohrer * Created. */ #ifndef ERROR_EVALUATOR_INCLUDED #define ERROR_EVALUATOR_INCLUDED /** * Interface for a class that evaluates a vector against another * to produce a scalar error value. * * @author Jason Rohrer */ class ErrorEvaluator { public: /** * Evaluates two input vectors to produce an output error value. * * @param inVectorA the first vector (the actual, or "correct" value) * @param inVectorB the second vector ( the predicted, or "test" value) * * @return the error value between the two vectors */ virtual double evaluate( double *inVectorA, double *inVectorB, int inLength ) = 0; }; #endif primrose-6+dfsg1.orig/minorGems/math/stats/L1ErrorEvaluator.h0000644000175000017500000000134407215720625023035 0ustar pabspabs/* * Modification History * * 2000-September-28 Jason Rohrer * Created. */ #ifndef L1_ERROR_EVALUATOR_INCLUDED #define L1_ERROR_EVALUATOR_INCLUDED #include "ErrorEvaluator.h" /** * L1 distance implementation of ErrorEvaluator. * * @author Jason Rohrer */ class L1ErrorEvaluator : public ErrorEvaluator { public: // implements ErrorEvaluator interface double evaluate( double *inVectorA, double *inVectorB, int inLength ); }; inline double L1ErrorEvaluator::evaluate( double *inVectorA, double *inVectorB, int inLength ) { double sum = 0; for( int i=0; ievaluate() ); } long InvertExpression::getID() { return mID; } inline long InvertExpression::staticGetID() { return mID; } inline void InvertExpression::print() { printf( "( 1/" ); mArgument->print(); printf( " )" ); } inline Expression *InvertExpression::copy() { InvertExpression *copy = new InvertExpression( mArgument->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/BinaryLogicExpression.h0000644000175000017500000001064107655132767025223 0ustar pabspabs/* * Modification History * * 2003-May-2 Jason Rohrer * Created. * * 2003-May-3 Jason Rohrer * Fixed a few compile-time errors. */ #ifndef BINARY_LOGIC_EXPRESSION_INCLUDED #define BINARY_LOGIC_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary logic operation. * * Evaluating this expression returns 1 if the logic operation is true * and 0 if it is false. * * During evaluation, positive values are treated as logical true, * while all other values (zero and negative) are treated as false. * * @author Jason Rohrer */ class BinaryLogicExpression : public BinaryOperationExpression { public: static const int LOGIC_AND = 0; static const int LOGIC_OR = 1; static const int LOGIC_XOR = 2; /** * Constructs a binary logic operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inLogicOperation the logical operation, one of * LOGIC_AND, LOGIC_OR, LOGIC_XOR. * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ BinaryLogicExpression( int inLogicOperation, Expression *inArgumentA, Expression *inArgumentB ); /** * Gets the logical operation. * * @return one of LOGIC_AND, LOGIC_OR, LOGIC_XOR. */ int getLogicOperation(); /** * Sets the logical operation * * @param inLogicOperation LOGIC_AND, LOGIC_OR, LOGIC_XOR. */ void setLogicOperation( int inLogicOperation ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; int mLogicOperation; }; // static init long BinaryLogicExpression::mID = 16; inline BinaryLogicExpression::BinaryLogicExpression( int inLogicOperation, Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ), mLogicOperation( inLogicOperation ) { } inline int BinaryLogicExpression::getLogicOperation() { return mLogicOperation; } inline void BinaryLogicExpression::setLogicOperation( int inLogicOperation ) { mLogicOperation = inLogicOperation; } inline double BinaryLogicExpression::evaluate() { if( mLogicOperation == LOGIC_AND ) { if( mArgumentA->evaluate() > 0 && mArgumentB->evaluate() > 0 ) { return 1; } else { return 0; } } else if( mLogicOperation == LOGIC_OR ) { if( mArgumentA->evaluate() > 0 || mArgumentB->evaluate() > 0 ) { return 1; } else { return 0; } } else if( mLogicOperation == LOGIC_XOR ) { double valA = mArgumentA->evaluate(); double valB = mArgumentB->evaluate(); if( ( valA > 0 && valB <= 0 ) || ( valA <= 0 && valB > 0 ) ) { return 1; } else { return 0; } } else { // unknown operation type // default to false return 0; } } inline long BinaryLogicExpression::getID() { return mID; } inline long BinaryLogicExpression::staticGetID() { return mID; } inline void BinaryLogicExpression::print() { printf( "( " ); mArgumentA->print(); if( mLogicOperation == LOGIC_AND ) { printf( " and " ); } else if( mLogicOperation == LOGIC_OR ) { printf( " or " ); } else if( mLogicOperation == LOGIC_XOR ) { printf( " xor " ); } else { printf( " UNKNOWN_LOGIC_OPERATION " ); } mArgumentB->print(); printf( " )" ); } inline Expression *BinaryLogicExpression::copy() { BinaryLogicExpression *copy = new BinaryLogicExpression( mLogicOperation, mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/ConstantExpression.h0000644000175000017500000000473607347050154024605 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. * * 2001-September-9 Jason Rohrer * Added an extractArgument() implemenation. */ #ifndef CONSTANT_EXPRESSION_INCLUDED #define CONSTANT_EXPRESSION_INCLUDED #include "Expression.h" /** * Expression implementation of a constant. * * @author Jason Rohrer */ class ConstantExpression : public Expression { public: /** * Constructs a constant expression. * * @param inValue the constant value. */ ConstantExpression( double inValue ); /** * Sets the constant value. * * @param inValue the constant value. */ void setValue( double inValue ); /** * Gets the constant value. * * @return the constant value. */ double getValue(); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getNumArguments(); virtual long getID(); virtual Expression *copy(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); virtual void print(); protected: double mValue; static long mID; }; // static init long ConstantExpression::mID = 1; inline ConstantExpression::ConstantExpression( double inValue ) : mValue( inValue ) { } inline void ConstantExpression::setValue( double inValue ) { mValue = inValue; } inline double ConstantExpression::getValue() { return mValue; } inline double ConstantExpression::evaluate() { return mValue; } long ConstantExpression::getNumArguments() { return 0; } inline long ConstantExpression::getID() { return mID; } inline Expression *ConstantExpression::getArgument( long inArgumentNumber ) { return NULL; } inline void ConstantExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { // do nothing return; } inline Expression *ConstantExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline Expression *ConstantExpression::copy() { ConstantExpression *copy = new ConstantExpression( mValue ); return copy; } inline long ConstantExpression::staticGetID() { return mID; } inline void ConstantExpression::print() { printf( "( %f )", mValue ); } #endif primrose-6+dfsg1.orig/minorGems/math/expression/SumExpression.h0000644000175000017500000000337207252524064023554 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef SUM_EXPRESSION_INCLUDED #define SUM_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary sum operation. * * @author Jason Rohrer */ class SumExpression : public BinaryOperationExpression { public: /** * Constructs a binary sum operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ SumExpression( Expression *inArgumentA, Expression *inArgumentB ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long SumExpression::mID = 7; inline SumExpression::SumExpression( Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ) { } inline double SumExpression::evaluate() { return mArgumentA->evaluate() + mArgumentB->evaluate(); } inline long SumExpression::getID() { return mID; } inline long SumExpression::staticGetID() { return mID; } inline void SumExpression::print() { printf( "( " ); mArgumentA->print(); printf( " + " ); mArgumentB->print(); printf( " )" ); } inline Expression *SumExpression::copy() { SumExpression *copy = new SumExpression( mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/Variable.h0000644000175000017500000000332607655253371022463 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. * * 2003-April-29 Jason Rohrer * Added missing destructor. */ #ifndef VARIABLE_INCLUDED #define VARIABLE_INCLUDED #include "minorGems/util/stringUtils.h" /** * Wrapper for a variable value. * * @author Jason Rohrer */ class Variable { public: /** * Constructs a variable, setting its value. * * @param inName the name of the variable. * Must be destroyed by caller if non-const. * @param inValue the initial value of the variable. */ Variable( char *inName, double inValue ); virtual ~Variable(); /** * Gets the value of this variable. * * @return the variable's value. */ virtual double getValue(); /** * Sets the value for this variable. * * @param inValue the value. */ virtual void setValue( double inValue ); /** * Gets the name of this variable. * * @return the name. * Must be destroyed by caller. */ virtual char *getName(); protected: char *mName; double mValue; }; inline Variable::Variable( char *inName, double inValue ) : mName( stringDuplicate( inName ) ), mValue( inValue ) { } inline Variable::~Variable() { delete [] mName; } inline double Variable::getValue() { return mValue; } inline void Variable::setValue( double inValue ) { mValue = inValue; } inline char *Variable::getName() { return stringDuplicate( mName ); } #endif primrose-6+dfsg1.orig/minorGems/math/expression/ComparisonExpression.h0000644000175000017500000001246407654613702025130 0ustar pabspabs/* * Modification History * * 2003-May-2 Jason Rohrer * Created. */ #ifndef COMPARISON_EXPRESSION_INCLUDED #define COMPARISON_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary comparison operation. * * Evaluating this expression returns 1 if the comparisson is true * and 0 if it is false. * * @author Jason Rohrer */ class ComparisonExpression : public BinaryOperationExpression { public: static const int GREATER_THAN = 0; static const int LESS_THAN = 1; static const int GREATER_THAN_OR_EQUAL_TO = 2; static const int LESS_THAN_OR_EQUAL_TO = 3; static const int EQUAL_TO = 4; static const int NOT_EQUAL_TO = 5; /** * Constructs a binary comparison operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inComparison the comparison to make, one of * GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL_TO, * LESS_THAN_OR_EQUAL_TO, EQUAL_TO, NOT_EQUAL_TO. * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ ComparisonExpression( int inComparison, Expression *inArgumentA, Expression *inArgumentB ); /** * Gets the comparison being made. * * @return one of GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL_TO, * LESS_THAN_OR_EQUAL_TO, EQUAL_TO, NOT_EQUAL_TO. */ int getComparison(); /** * Sets the comparison to make. * * @param inComparison the comparison to make, one of * GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL_TO, * LESS_THAN_OR_EQUAL_TO, EQUAL_TO, NOT_EQUAL_TO. */ void setComparison( int inComparison ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; int mComparison; }; // static init long ComparisonExpression::mID = 15; inline ComparisonExpression::ComparisonExpression( int inComparison, Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ), mComparison( inComparison ) { } inline int ComparisonExpression::getComparison() { return mComparison; } inline void ComparisonExpression::setComparison( int inComparison ) { mComparison = inComparison; } inline double ComparisonExpression::evaluate() { if( mComparison == GREATER_THAN ) { if( mArgumentA->evaluate() > mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == LESS_THAN ) { if( mArgumentA->evaluate() < mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == GREATER_THAN_OR_EQUAL_TO ) { if( mArgumentA->evaluate() >= mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == LESS_THAN_OR_EQUAL_TO ) { if( mArgumentA->evaluate() <= mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == EQUAL_TO ) { if( mArgumentA->evaluate() == mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == NOT_EQUAL_TO ) { if( mArgumentA->evaluate() != mArgumentB->evaluate() ) { return 1; } else { return 0; } } else { // unknown comparison type // default to false return 0; } } inline long ComparisonExpression::getID() { return mID; } inline long ComparisonExpression::staticGetID() { return mID; } inline void ComparisonExpression::print() { printf( "( " ); mArgumentA->print(); if( mComparison == GREATER_THAN ) { printf( " > " ); } else if( mComparison == LESS_THAN ) { printf( " < " ); } else if( mComparison == GREATER_THAN_OR_EQUAL_TO ) { printf( " >= " ); } else if( mComparison == LESS_THAN_OR_EQUAL_TO ) { printf( " <= " ); } else if( mComparison == EQUAL_TO ) { printf( " == " ); } else if( mComparison == NOT_EQUAL_TO ) { printf( " != " ); } else { printf( " UNKNOWN_COMPARISON " ); } mArgumentB->print(); printf( " )" ); } inline Expression *ComparisonExpression::copy() { ComparisonExpression *copy = new ComparisonExpression( mComparison, mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/UnaryOperationExpression.h0000644000175000017500000000551207347047600025766 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-September-4 Jason Rohrer * Changed the destructor to virtual to fix a memory leak. * * 2001-September-9 Jason Rohrer * Changed setArgument to be more intelligent about duplicated calls. * Added an extractArgument() implemenation. */ #ifndef UNARY_OPERATION_EXPRESSION_INCLUDED #define UNARY_OPERATION_EXPRESSION_INCLUDED #include "Expression.h" /** * Abstract base for an unary operation expression object. * * @author Jason Rohrer */ class UnaryOperationExpression : public Expression { public: /** * Constructs a unary operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. Defaults to NULL. */ UnaryOperationExpression( Expression *inArgument = NULL ); virtual ~UnaryOperationExpression(); /** * Sets the argument for the operation. * * @param inArgument the argument. Is destroyed * when the class is destroyed, or by another * call to setArgument. */ void setArgument( Expression *inArgument ); /** * Gets the argument for the operation. * * @return the argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. Returns NULL if the * argument was never set. */ Expression *getArgument(); // implements the Expression interface virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); protected: Expression *mArgument; }; inline UnaryOperationExpression::UnaryOperationExpression( Expression *inArgument ) : mArgument( inArgument ) { } inline UnaryOperationExpression::~UnaryOperationExpression() { if( mArgument != NULL ) { delete mArgument; } } inline void UnaryOperationExpression::setArgument( Expression *inArgument ) { if( mArgument != NULL && inArgument != mArgument ) { delete mArgument; } mArgument = inArgument; } inline Expression *UnaryOperationExpression::getArgument() { return mArgument; } long UnaryOperationExpression::getNumArguments() { return 1; } inline Expression *UnaryOperationExpression::getArgument( long inArgumentNumber ) { if( inArgumentNumber == 0 ) { return getArgument(); } else { return NULL; } } inline void UnaryOperationExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { if( inArgumentNumber == 0 ) { setArgument( inArgument ); return; } else { return; } } inline Expression *UnaryOperationExpression::extractArgument( long inArgumentNumber ) { Expression *returnArg = mArgument; mArgument = NULL; return returnArg; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/ProductExpression.h0000644000175000017500000000346307252524064024431 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef PRODUCT_EXPRESSION_INCLUDED #define PRODUCT_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary product operation. * * @author Jason Rohrer */ class ProductExpression : public BinaryOperationExpression { public: /** * Constructs a binary product operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ ProductExpression( Expression *inArgumentA, Expression *inArgumentB ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long ProductExpression::mID = 5; inline ProductExpression::ProductExpression( Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ) { } inline double ProductExpression::evaluate() { return mArgumentA->evaluate() * mArgumentB->evaluate(); } inline long ProductExpression::getID() { return mID; } inline long ProductExpression::staticGetID() { return mID; } inline void ProductExpression::print() { printf( "( " ); mArgumentA->print(); printf( " * " ); mArgumentB->print(); printf( " )" ); } inline Expression *ProductExpression::copy() { ProductExpression *copy = new ProductExpression( mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/SqrtExpression.h0000644000175000017500000000334307653343375023750 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef SQRT_EXPRESSION_INCLUDED #define SQRT_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary sqrt operation. * * @author Jason Rohrer */ class SqrtExpression : public UnaryOperationExpression { public: /** * Constructs a unary sqrt operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ SqrtExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long SqrtExpression::mID = 13; inline SqrtExpression::SqrtExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double SqrtExpression::evaluate() { return sqrt( mArgument->evaluate() ); } inline long SqrtExpression::getID() { return mID; } inline long SqrtExpression::staticGetID() { return mID; } inline void SqrtExpression::print() { printf( "( sqrt" ); mArgument->print(); printf( " )" ); } inline Expression *SqrtExpression::copy() { SqrtExpression *copy = new SqrtExpression( mArgument->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/expressionTester.cpp0000644000175000017500000000552607653343375024665 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-February-12 Jason Rohrer * Added code to test serialization. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. * * 2001-April-12 Jason Rohrer * Changed to comply with new FileInput/OutputStream interface * (underlying File must be destroyed explicitly). */ #include "Expression.h" #include "ConstantExpression.h" #include "PowerExpression.h" #include "ProductExpression.h" #include "NegateExpression.h" #include "InvertExpression.h" #include "SinExpression.h" #include "LnExpression.h" #include "SumExpression.h" #include "ExpressionSerializer.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" // test function for expressions int main() { ProductExpression *expression = new ProductExpression( new PowerExpression( new ConstantExpression( 5 ), new ConstantExpression( 6 ) ), new NegateExpression( new SinExpression( new ConstantExpression( 19 ) ) ) ); InvertExpression *invExpression = new InvertExpression( expression ); SumExpression *sumExpression = new SumExpression( invExpression, new ConstantExpression( 2 ) ); sumExpression->print(); printf( "\n" ); printf( "%f\n", sumExpression->evaluate() ); printf( "Writing to file.\n" ); char **pathSteps = new char*[2]; pathSteps[0] = new char[10]; pathSteps[1] = new char[10]; sprintf( pathSteps[0], "test" ); sprintf( pathSteps[1], "file" ); int *stepLength = new int[2]; stepLength[0] = 4; stepLength[1] = 4; Path *path = new Path( pathSteps, 2, stepLength, false ); File *file = new File( path, "test.out", 8 ); FileOutputStream *outStream = new FileOutputStream( file, false ); char *error = outStream->getLastError(); if( error != NULL ) { printf( "Error: %s\n", error ); delete error; } ExpressionSerializer::serializeExpression( sumExpression, outStream ); delete outStream; delete file; printf( "Reading back in from file.\n" ); pathSteps = new char*[2]; pathSteps[0] = new char[10]; pathSteps[1] = new char[10]; sprintf( pathSteps[0], "test" ); sprintf( pathSteps[1], "file" ); stepLength = new int[2]; stepLength[0] = 4; stepLength[1] = 4; path = new Path( pathSteps, 2, stepLength, false ); file = new File( path, "test.out", 8 ); FileInputStream *inStream = new FileInputStream( file ); error = inStream->getLastError(); if( error != NULL ) { printf( "Error: %s\n", error ); delete error; } Expression *readExpression; ExpressionSerializer::deserializeExpression( &readExpression, inStream ); delete inStream; delete file; readExpression->print(); printf( "\n" ); printf( "%f\n", readExpression->evaluate() ); delete sumExpression; delete readExpression; return 0; } primrose-6+dfsg1.orig/minorGems/math/expression/ExpressionMutator.h0000644000175000017500000001604107350157715024444 0ustar pabspabs/* * Modification History * * 2001-September-9 Jason Rohrer * Created. * * 2001-September-13 Jason Rohrer * Made an error message more verbose. */ #ifndef EXPRESSION_MUTATOR_INCLUDED #define EXPRESSION_MUTATOR_INCLUDED #include "minorGems/util/random/RandomSource.h" #include "Expression.h" #include "ConstantExpression.h" #include "InvertExpression.h" #include "ProductExpression.h" #include "PowerExpression.h" #include "SumExpression.h" #include "NegateExpression.h" #include "SinExpression.h" #include "FixedConstantExpression.h" #include "MultiConstantArgumentExpression.h" /** * Utility class for mutating expressions. * * Note that the number and position of constant expressions * within the expression will not change during mutation. Thus, * the structure of the expression remains constant while the operations * being performed at each node are mutated. * * @author Jason Rohrer */ class ExpressionMutator { public: /** * Mutates an expression. * * Note that this function's implementation is recursive. * * @param inExpression the expression to mutate. Will be destroyed * by this function (or if not destroyed, then passed back through * the return value). Only the return value, not inExpression, * can be accessed safely after this function returns. * @param inMutationProb the probability of mutations at each * node in inExpression. * @param inMaxMutation the fraction of a fixed constant's value * by which it can be mutated. For example, if a fixed constant * has the value 100, and inMaxMutation is 0.5, then the mutated * constant will be a random value in the range [50, 150]. * @param inRandSource the source of random numbers to use. * Must be destroyed by caller. * * @return a new expression that is a mutated version of inExpression. * (Note that the returned expression may be inExpression). */ static Expression *mutateExpression( Expression *inExpression, double inMutationProb, double inMaxMutation, RandomSource *inRandSource ); }; inline Expression *ExpressionMutator::mutateExpression( Expression *inExpression, double inMutationProb, double inMaxMutation, RandomSource *inRandSource ) { long expressionID = inExpression->getID(); // first, deal with constant case if( expressionID == ConstantExpression::staticGetID() ) { // mutate the constant's value ConstantExpression *c = (ConstantExpression *)inExpression; double value = c->getValue(); double maxMutationAmount = inMaxMutation * value; // a value in [-1, 1] double mutator = ( inRandSource->getRandomDouble() * 2.0 ) - 1.0; value = value + mutator * maxMutationAmount; c->setValue( value ); return c; } else if( expressionID == FixedConstantExpression::staticGetID() ) { // mutate the fixed constant's value FixedConstantExpression *c = (FixedConstantExpression *)inExpression; double value = c->getValue(); double maxMutationAmount = inMaxMutation * value; // a value in [-1, 1] double mutator = ( inRandSource->getRandomDouble() * 2.0 ) - 1.0; value = value + mutator * maxMutationAmount; delete c; return new FixedConstantExpression( value ); } // next deal with the multi-argument case else if( expressionID == MultiConstantArgumentExpression::staticGetID() ) { MultiConstantArgumentExpression *m = (MultiConstantArgumentExpression*)inExpression; Expression *wrappedExpression = m->extractWrappedExpression(); wrappedExpression = mutateExpression( wrappedExpression, inMutationProb, inMaxMutation, inRandSource ); m->setWrappedExpression( wrappedExpression ); return m; } else { // the general expression case Expression *newExpression = inExpression; if( inRandSource->getRandomDouble() <= inMutationProb ) { // we need to mutate this node long newID; if( expressionID == InvertExpression::staticGetID() || expressionID == NegateExpression::staticGetID() || expressionID == SinExpression::staticGetID() ) { // a unary expression // pick another expression type at random newID = expressionID; while( newID == expressionID ) { int randValue = inRandSource->getRandomBoundedInt( 0, 2 ); switch( randValue ) { case 0: newID = InvertExpression::staticGetID(); break; case 1: newID = NegateExpression::staticGetID(); break; case 2: newID = SinExpression::staticGetID(); break; default: // we should never hit this // note that this newID will cause a printed // error below newID = -1; break; } } } else { // a binary expression // pick another expression type at random newID = expressionID; while( newID == expressionID ) { int randValue = inRandSource->getRandomBoundedInt( 0, 2 ); switch( randValue ) { case 0: newID = PowerExpression::staticGetID(); break; case 1: newID = ProductExpression::staticGetID(); break; case 2: newID = SumExpression::staticGetID(); break; default: // we should never hit this // note that this newID will cause a printed // error below newID = -1; break; } } } // now build an expression based on newID if( newID == InvertExpression::staticGetID() ) { newExpression = new InvertExpression( NULL ); } else if( newID == NegateExpression::staticGetID() ) { newExpression = new NegateExpression( NULL ); } else if( newID == PowerExpression::staticGetID() ) { newExpression = new PowerExpression( NULL, NULL ); } else if( newID == ProductExpression::staticGetID() ) { newExpression = new ProductExpression( NULL, NULL ); } else if( newID == SinExpression::staticGetID() ) { newExpression = new SinExpression( NULL ); } else if( newID == SumExpression::staticGetID() ) { newExpression = new SumExpression( NULL, NULL ); } else { printf( "Error in ExpressionMutator: ID does not " ); printf( "match a known expression type: %d\n", newID ); } // at this point, we have constructed a new expression node // with the same number of arguments as the old node // we need to fill in the arguments from inExpression for( int i=0; igetNumArguments(); i++ ) { // use extractArgument so that the argument // won't be destroyed when inExpression is destroyed Expression *argument = inExpression->extractArgument( i ); newExpression->setArgument( i, argument ); } // destroy the old node delete inExpression; } // mutate the sub nodes for( int i=0; igetNumArguments(); i++ ) { Expression *argument = newExpression->extractArgument( i ); // mutate the argument argument = mutateExpression( argument, inMutationProb, inMaxMutation, inRandSource ); newExpression->setArgument( i, argument ); } return newExpression; } } #endif primrose-6+dfsg1.orig/minorGems/math/expression/PowerExpression.h0000644000175000017500000000356707252524064024112 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef POWER_EXPRESSION_INCLUDED #define POWER_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" #include /** * Expression implementation of a binary power operation. * Raises the first argument to the power of the second, * as in argA^argB. * * @author Jason Rohrer */ class PowerExpression : public BinaryOperationExpression { public: /** * Constructs a binary power operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ PowerExpression( Expression *inArgumentA, Expression *inArgumentB ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long PowerExpression::mID = 4; inline PowerExpression::PowerExpression( Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ) { } inline double PowerExpression::evaluate() { return pow( mArgumentA->evaluate(), mArgumentB->evaluate() ); } inline long PowerExpression::getID() { return mID; } inline long PowerExpression::staticGetID() { return mID; } inline void PowerExpression::print() { printf( "( " ); mArgumentA->print(); printf( " ^ " ); mArgumentB->print(); printf( " )" ); } inline Expression *PowerExpression::copy() { PowerExpression *copy = new PowerExpression( mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/TanExpression.h0000644000175000017500000000332107653343375023535 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef TAN_EXPRESSION_INCLUDED #define TAN_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary tan operation. * * @author Jason Rohrer */ class TanExpression : public UnaryOperationExpression { public: /** * Constructs a unary tan operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ TanExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long TanExpression::mID = 12; inline TanExpression::TanExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double TanExpression::evaluate() { return tan( mArgument->evaluate() ); } inline long TanExpression::getID() { return mID; } inline long TanExpression::staticGetID() { return mID; } inline void TanExpression::print() { printf( "( tan" ); mArgument->print(); printf( " )" ); } inline Expression *TanExpression::copy() { TanExpression *copy = new TanExpression( mArgument->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/BinaryOperationExpression.h0000644000175000017500000001045107347047600026112 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-September-4 Jason Rohrer * Changed the destructor to virtual to fix a memory leak. * * 2001-September-9 Jason Rohrer * Changed setArgument to be more intelligent about duplicated calls. * Added an extractArgument() implemenation. */ #ifndef BINARY_OPERATION_EXPRESSION_INCLUDED #define BINARY_OPERATION_EXPRESSION_INCLUDED #include "Expression.h" /** * Abstract base for an binary operation expression object. * * @author Jason Rohrer */ class BinaryOperationExpression : public Expression { public: /** * Constructs a binary operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. Defaults to NULL. * @param inArgumentA the first argument. Defaults to NULL. */ BinaryOperationExpression( Expression *inArgumentA = NULL, Expression *inArgumentB = NULL ); virtual ~BinaryOperationExpression(); /** * Sets the first argument for the operation. * * @param inArgument the first argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentA. */ void setArgumentA( Expression *inArgument ); /** * Sets the second argument for the operation. * * @param inArgument the second argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. */ void setArgumentB( Expression *inArgument ); /** * Gets the first argument for the operation. * * @return the first argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. Returns NULL if the * argument was never set. */ Expression *getArgumentA(); /** * Gets the second argument for the operation. * * @return the second argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. Returns NULL if the * argument was never set. */ Expression *getArgumentB(); // implements the Expression interface virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); protected: Expression *mArgumentA; Expression *mArgumentB; }; inline BinaryOperationExpression::BinaryOperationExpression( Expression *inArgumentA, Expression *inArgumentB ) : mArgumentA( inArgumentA ), mArgumentB( inArgumentB ) { } inline BinaryOperationExpression::~BinaryOperationExpression() { if( mArgumentA != NULL ) { delete mArgumentA; } if( mArgumentB != NULL ) { delete mArgumentB; } } inline void BinaryOperationExpression::setArgumentA( Expression *inArgument ) { if( mArgumentA != NULL && inArgument != mArgumentA ) { delete mArgumentA; } mArgumentA = inArgument; } inline void BinaryOperationExpression::setArgumentB( Expression *inArgument ) { if( mArgumentB != NULL && inArgument != mArgumentB ) { delete mArgumentB; } mArgumentB = inArgument; } inline Expression *BinaryOperationExpression::getArgumentA() { return mArgumentA; } inline Expression *BinaryOperationExpression::getArgumentB() { return mArgumentB; } inline long BinaryOperationExpression::getNumArguments() { return 2; } inline Expression *BinaryOperationExpression::getArgument( long inArgumentNumber ) { switch( inArgumentNumber ) { case 0: return getArgumentA(); break; case 1: return getArgumentB(); break; default: return NULL; break; } } inline void BinaryOperationExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { switch( inArgumentNumber ) { case 0: setArgumentA( inArgument ); return; break; case 1: setArgumentB( inArgument ); return; break; default: return; break; } } inline Expression *BinaryOperationExpression::extractArgument( long inArgumentNumber ) { Expression *returnArg; switch( inArgumentNumber ) { case 0: returnArg = mArgumentA; mArgumentA = NULL; return returnArg; break; case 1: returnArg = mArgumentB; mArgumentB = NULL; return returnArg; break; default: return NULL; break; } } #endif primrose-6+dfsg1.orig/minorGems/math/expression/MultiConstantArgumentExpression.h0000644000175000017500000002001207347050250027301 0ustar pabspabs/* * Modification History * * 2001-August-30 Jason Rohrer * Created. * * 2001-August-31 Jason Rohrer * Added public access to the wrapped expression. * Fixed a comment and some bugs. * Fixed a memory leak. * * 2001-September-9 Jason Rohrer * Added public function for setting the wrapped expression after * construction. * Added an extractArgument() implemenation. * Added an extractWrappedExpression() function to work * around some destruction issues. */ #ifndef MULTI_CONSTANT_ARGUMENT_EXPRESSION_INCLUDED #define MULTI_CONSTANT_ARGUMENT_EXPRESSION_INCLUDED #include "Expression.h" #include "ConstantExpression.h" #include "minorGems/util/SimpleVector.h" /** * An expression implementation that treats the constants * in another expression as assignable arguments. * * Most common usage pattern: * Set up an Expression containing one constant for each * assignable argument and pass this expression into * the constructor. * * Notes: * * getArugment() returns the actual constant expression * contained in the wrapped expression. It therefore * should not be destroyed by the caller. * * setArgument() evaluates the passed-in expression * and then sets the value of the constant expression to the * value produced by the evaluation. * The passed-in expression must be destroyed by the caller, * and it can be destroyed as soon as setArgument() returns. * * @author Jason Rohrer */ class MultiConstantArgumentExpression : public Expression { public: /** * Constructs a new MultiArgumentExpression. * * @param inExpression the expression to use as the * body of this new expression, where each constant in * inExpression will be used as an argument to the * new expression. Will be destroyed when this class * is destroyed. */ MultiConstantArgumentExpression( Expression *inExpression ); ~MultiConstantArgumentExpression(); /** * Sets the expression wrapped by this mult-argument expression. * * Note that calling this function destroys the currently wrapped * expression. * * @param inExpression the expression to use as the * body of this new expression, where each constant in * inExpression will be used as an argument to the * new expression. Will be destroyed when this class * is destroyed. */ void setWrappedExpression( Expression *inExpression ); /** * Gets the expression wrapped by this mult-argument expression. * * @return the expression wrapped by this expression. * Will be destroyed when this class is destroyed. */ Expression *getWrappedExpression(); /** * Gets the expression wrapped by this mult-argument expression, * and sets the internal expression to NULL (thus, the returned * argument will not be destroyed when this class is destroyed. * * @return the expression wrapped by this expression. Must * be destroyed by caller. */ Expression *extractWrappedExpression(); // these implement the Expression interface virtual double evaluate(); virtual long getID(); virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); // note that extractArgument() always returns NULL for this class virtual Expression *extractArgument( long inArgumentNumber ); virtual void print(); virtual Expression *copy(); /** * A static version of getID(). */ static long staticGetID(); protected: Expression *mExpression; static long mID; long mNumConstants; ConstantExpression **mConstants; /** * Finds the constants in an expression in a consistent way * (using depth-first, left-first search). * * @param inExpression the expression to search for constants in. * @param outExpressions a pointer where the array of found * expressions will be returned. * * @return the number of constants found. */ long findConstants( Expression *inExpression, ConstantExpression ***outExpressions ); /** * Recursive proceedure used by findConstants() * * @param inExpression the (sub)expression to find constants in. * @param inConstantVector the vector to add found constants to. */ void findConstantsRecursive( Expression *inExpression, SimpleVector *inConstantVector ); }; // static init long MultiConstantArgumentExpression::mID = 8; inline MultiConstantArgumentExpression:: MultiConstantArgumentExpression( Expression *inExpression ) : mExpression( NULL ), mConstants( NULL ) { setWrappedExpression( inExpression ); } inline MultiConstantArgumentExpression:: ~MultiConstantArgumentExpression() { delete [] mConstants; delete mExpression; } inline void MultiConstantArgumentExpression:: setWrappedExpression( Expression *inExpression ) { if( mExpression != NULL && mExpression != inExpression ) { delete mExpression; } mExpression = inExpression; if( mConstants != NULL ) { delete [] mConstants; } mNumConstants = findConstants( inExpression, &mConstants ); } inline Expression *MultiConstantArgumentExpression:: getWrappedExpression() { return mExpression; } inline Expression *MultiConstantArgumentExpression:: extractWrappedExpression() { Expression *wrappedExpression = mExpression; mExpression = NULL; return wrappedExpression; } inline double MultiConstantArgumentExpression::evaluate() { return mExpression->evaluate(); } inline long MultiConstantArgumentExpression::getID() { return mID; } inline long MultiConstantArgumentExpression::staticGetID() { return mID; } inline long MultiConstantArgumentExpression::getNumArguments() { return mNumConstants; } inline Expression *MultiConstantArgumentExpression::getArgument( long inArgumentNumber ) { if( inArgumentNumber >= 0 && inArgumentNumber < mNumConstants ) { return mConstants[inArgumentNumber]; } else { return NULL; } } inline void MultiConstantArgumentExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { Expression *expressionToSet = getArgument( inArgumentNumber ); if( expressionToSet != NULL ) { ConstantExpression *constantExpression = (ConstantExpression*)expressionToSet; // set the constant to the evaluation of inArgument constantExpression->setValue( inArgument->evaluate() ); } else { printf( "MultiConstantArgumentExpression: setting an out of range " ); printf( "argument number, %ld\n", inArgumentNumber ); } } inline Expression *MultiConstantArgumentExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline void MultiConstantArgumentExpression::print() { mExpression->print(); } inline Expression *MultiConstantArgumentExpression::copy() { return new MultiConstantArgumentExpression( mExpression->copy() ); } inline long MultiConstantArgumentExpression::findConstants( Expression *inExpression, ConstantExpression ***outExpressions ) { SimpleVector *constantVector = new SimpleVector(); findConstantsRecursive( inExpression, constantVector ); long numConstants = constantVector->size(); ConstantExpression **returnArray = new ConstantExpression*[ numConstants ]; for( int i=0; igetElement(i) ); } delete constantVector; // set passed-in pointer to our array *outExpressions = returnArray; return numConstants; } inline void MultiConstantArgumentExpression::findConstantsRecursive( Expression *inExpression, SimpleVector *inConstantVector ) { if( inExpression->getID() == ConstantExpression::staticGetID() ) { // the passed-in expression is a constant inConstantVector->push_back( (ConstantExpression *)inExpression ); return; } else { // call recursively on each argument for( int i=0; igetNumArguments(); i++ ) { Expression *argument = inExpression->getArgument( i ); findConstantsRecursive( argument, inConstantVector ); } return; } } #endif primrose-6+dfsg1.orig/minorGems/math/expression/LnExpression.h0000644000175000017500000000331607653343375023370 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef LN_EXPRESSION_INCLUDED #define LN_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary ln (natural log) operation. * * @author Jason Rohrer */ class LnExpression : public UnaryOperationExpression { public: /** * Constructs a unary ln operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ LnExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long LnExpression::mID = 10; inline LnExpression::LnExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double LnExpression::evaluate() { return log( mArgument->evaluate() ); } inline long LnExpression::getID() { return mID; } inline long LnExpression::staticGetID() { return mID; } inline void LnExpression::print() { printf( "( ln" ); mArgument->print(); printf( " )" ); } inline Expression *LnExpression::copy() { LnExpression *copy = new LnExpression( mArgument->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/SinExpression.h0000644000175000017500000000305307252524064023535 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef SIN_EXPRESSION_INCLUDED #define SIN_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary sin operation. * * @author Jason Rohrer */ class SinExpression : public UnaryOperationExpression { public: /** * Constructs a unary sin operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ SinExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long SinExpression::mID = 6; inline SinExpression::SinExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double SinExpression::evaluate() { return sin( mArgument->evaluate() ); } inline long SinExpression::getID() { return mID; } inline long SinExpression::staticGetID() { return mID; } inline void SinExpression::print() { printf( "( sin" ); mArgument->print(); printf( " )" ); } inline Expression *SinExpression::copy() { SinExpression *copy = new SinExpression( mArgument->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/Expression.h0000644000175000017500000000717407657013075023077 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-March-7 Jason Rohrer * Added a copy() function interface. * * 2001-September-4 Jason Rohrer * Added a virtual destructor to fix a major memory leak. * * 2001-September-9 Jason Rohrer * Added an extractArgument() function to work around some * object destruction issues. * * 2003-May-9 Jason Rohrer * Added support for replacing a variable. */ #ifndef EXPRESSION_INCLUDED #define EXPRESSION_INCLUDED #include #include "Variable.h" /** * Interface for an expression object. * * @author Jason Rohrer */ class Expression { public: virtual ~Expression(); /** * Evaluates this expression. * * @return the value of this expression. */ virtual double evaluate() = 0; /** * Gets the unique ID of this expression subtype. * * @return the ID of this subtype. */ virtual long getID() = 0; /** * Gets the number of arguments taken by this expression subtype. * * @return the number of arguments for this subtype. */ virtual long getNumArguments() = 0; /** * Gets a specified argument for this expression. * * @param inArgumentNumber the index of this argument. * * @return the specified argument. Will be destroyed * when this class is destroyed. Returns NULL if * the argument has not been set. */ virtual Expression *getArgument( long inArgumentNumber ) = 0; /** * Sets a specified argument for this expression. * * @param inArgumentNumber the index of this argument. * @param inArgument the specified argument. Will be destroyed * when this class is destroyed, or by another call to * setArgument. */ virtual void setArgument( long inArgumentNumber, Expression *inArgument ) = 0; /** * Extracts an argument from this expression. * * This is similar to getArgument(), except that internally * this expression's argument is set to NULL. In other words, * this allows you to setArgument( NULL ) without destroying * the argument. * * @param inArgumentNumber the argument to get. Must be destroyed * by caller. Returns NULL if the argument has not been set. */ virtual Expression *extractArgument( long inArgumentNumber ) = 0; /** * Prints this expression to standard out. */ virtual void print() = 0; /** * Makes a copy of this expression recursively. * * @return a copy of this expression. */ virtual Expression *copy() = 0; /** * Recursively replace a variable in this expression. * * Default implementation calls replacement recursively on each * argument. Expressions that actually deal with variables * should override this implementation. * * @param inTarget the target to replace. * Must be destroyed by caller. * @param inReplacement the variable to replace the target with. * Must be destroyed by caller after this expression is destroyed. */ virtual void replaceVariable( Variable *inTarget, Variable *inReplacement ); }; inline Expression::~Expression() { // do nothing } inline void Expression::replaceVariable( Variable *inTarget, Variable *inReplacement ) { // call recursively on each of our arguments int numArgs = getNumArguments(); for( int i=0; ireplaceVariable( inTarget, inReplacement ); } } #endif primrose-6+dfsg1.orig/minorGems/math/expression/RandomVariable.h0000644000175000017500000000265307655253371023626 0ustar pabspabs/* * Modification History * * 2003-May-4 Jason Rohrer * Created. */ #ifndef RANDOM_VARIABLE_INCLUDED #define RANDOM_VARIABLE_INCLUDED #include "minorGems/util/stringUtils.h" #include "minorGems/util/random/RandomSource.h" /** * Wrapper for a random-valued variable. * * @author Jason Rohrer */ class RandomVariable : public Variable{ public: /** * Constructs a variable * * @param inName the name of the variable. * Must be destroyed by caller if non-const. * @param inRandSource the source for random numbers. * Must be destroyed by caller after this class is destroyed. */ RandomVariable( char *inName, RandomSource *inRandSource ); virtual ~RandomVariable(); // overrides Variable functions virtual double getValue(); virtual void setValue( double inValue ); protected: RandomSource *mRandSource; }; inline RandomVariable::RandomVariable( char *inName, RandomSource *inRandSource ) : Variable( inName, 0 ), mRandSource( inRandSource ) { } inline RandomVariable::~RandomVariable() { } inline double RandomVariable::getValue() { return mRandSource->getRandomDouble(); } inline void RandomVariable::setValue( double inValue ) { // do nothing } #endif primrose-6+dfsg1.orig/minorGems/math/expression/RandomExpressionFactory.h0000644000175000017500000001005707345177105025561 0ustar pabspabs/* * Modification History * * 2001-August-30 Jason Rohrer * Created. * * 2001-August-31 Jason Rohrer * Finished implementation. * Fixed a compile bug. * * 2001-September-4 Jason Rohrer * Added support for FixedConstantExpressions. */ #ifndef RANDOM_EXPRESSION_FACTORY_INCLUDED #define RANDOM_EXPRESSION_FACTORY_INCLUDED #include "Expression.h" #include "ConstantExpression.h" #include "FixedConstantExpression.h" #include "InvertExpression.h" #include "ProductExpression.h" #include "PowerExpression.h" #include "SumExpression.h" #include "NegateExpression.h" #include "SinExpression.h" #include "minorGems/util/random/RandomSource.h" /** * Utility class for constructing random expressions. * * @author Jason Rohrer */ class RandomExpressionFactory { public: /** * Constructs a random expression factory. * * @param inRandSource the source for random numbers * to use while constructing expressions. * Must be destroyed by caller after this class is destroyed. */ RandomExpressionFactory( RandomSource *inRandSource ); /** * Recursively constructs a random expression with all parameters * filled. * * @param inProbOfStopping the probability of stopping at each * branch of the expression. Upon stopping on a certain branch * of the recursion, it simply returns a constant expression. * @param inProbOfFixedConstant the probability of a fixed * constant expression being inserted upon stopping (as opposed * to a (mutable) constant expression). * @param inMaxDepth if this is reached, the recursion * stops regardless of inProbOfStopping. * @param inConstantMax the maximum value for a constant expression. * * @return the constructed expression. */ Expression *constructRandomExpression( double inProbOfStopping, double inProbOfFixedConstant, int inMaxDepth, double inConstantMax ); protected: RandomSource *mRandSource; }; inline RandomExpressionFactory::RandomExpressionFactory( RandomSource *inRandSource ) : mRandSource( inRandSource ) { } inline Expression *RandomExpressionFactory::constructRandomExpression( double inProbOfStopping, double inProbOfFixedConstant, int inMaxDepth, double inConstantMax ) { // fill in constant expressions only at the leaves if( inMaxDepth == 0 || mRandSource->getRandomDouble() <= inProbOfStopping ) { // stop if( mRandSource->getRandomDouble() <= inProbOfFixedConstant ) { return new FixedConstantExpression( inConstantMax * ( mRandSource->getRandomDouble() ) ); } else { return new ConstantExpression( inConstantMax * ( mRandSource->getRandomDouble() ) ); } } else { // keep filling in non constant expressions randomly // FILL IN HERE // we have 6 expression types int randVal = mRandSource->getRandomBoundedInt( 0, 3 ); Expression *outExpression; // pick an expression type switch( randVal ) { case 0: outExpression = new NegateExpression( NULL ); break; case 1: outExpression = new ProductExpression( NULL, NULL ); break; case 2: outExpression = new SinExpression( NULL ); break; case 3: outExpression = new SumExpression( NULL, NULL ); break; default: // should never happen, but... printf( "RandomExpressionFactory: " ); printf( "Error while generating random expression\n" ); // default to a constant expression of 0 outExpression = new ConstantExpression( 0 ); break; } // now recursively fill in the arguments in succession for( int i=0; igetNumArguments(); i++ ) { // create a random expression as the argument // note that we decrement inMaxDepth here Expression *argument = constructRandomExpression( inProbOfStopping, inProbOfFixedConstant, inMaxDepth - 1, inConstantMax ); // set the argument into our expression outExpression->setArgument( i, argument ); } // now expression is complete. return outExpression; } // end of non-constant else case } // end of constructRandomExpression() #endif primrose-6+dfsg1.orig/minorGems/math/expression/NegateExpression.h0000644000175000017500000000306607252524064024213 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef NEGATE_EXPRESSION_INCLUDED #define NEGATE_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" /** * Expression implementation of a unary negate operation. * * @author Jason Rohrer */ class NegateExpression : public UnaryOperationExpression { public: /** * Constructs a unary negate operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ NegateExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long NegateExpression::mID = 3; inline NegateExpression::NegateExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double NegateExpression::evaluate() { return -( mArgument->evaluate() ); } inline long NegateExpression::getID() { return mID; } inline long NegateExpression::staticGetID() { return mID; } inline void NegateExpression::print() { printf( "( -" ); mArgument->print(); printf( " )" ); } inline Expression *NegateExpression::copy() { NegateExpression *copy = new NegateExpression( mArgument->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/FixedConstantExpression.h0000644000175000017500000000444607347050154025563 0ustar pabspabs/* * Modification History * * 2001-September-4 Jason Rohrer * Created. * * 2001-September-9 Jason Rohrer * Added an extractArgument() implemenation. */ #ifndef FIXED_CONSTANT_EXPRESSION_INCLUDED #define FIXED_CONSTANT_EXPRESSION_INCLUDED #include "Expression.h" /** * Expression implementation of a fixed constant. * * @author Jason Rohrer */ class FixedConstantExpression : public Expression { public: /** * Constructs a FixedConstant expression. * * @param inValue the constant value. */ FixedConstantExpression( double inValue ); /** * Gets the constant value. * * @return the constant value. */ double getValue(); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getNumArguments(); virtual long getID(); virtual Expression *copy(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); virtual void print(); protected: double mValue; static long mID; }; // static init long FixedConstantExpression::mID = 9; inline FixedConstantExpression::FixedConstantExpression( double inValue ) : mValue( inValue ) { } inline double FixedConstantExpression::getValue() { return mValue; } inline double FixedConstantExpression::evaluate() { return mValue; } long FixedConstantExpression::getNumArguments() { return 0; } inline long FixedConstantExpression::getID() { return mID; } inline Expression *FixedConstantExpression::getArgument( long inArgumentNumber ) { return NULL; } inline void FixedConstantExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { // do nothing return; } inline Expression *FixedConstantExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline Expression *FixedConstantExpression::copy() { FixedConstantExpression *copy = new FixedConstantExpression( mValue ); return copy; } inline long FixedConstantExpression::staticGetID() { return mID; } inline void FixedConstantExpression::print() { printf( "( %f )", mValue ); } #endif primrose-6+dfsg1.orig/minorGems/math/expression/CosExpression.h0000644000175000017500000000332107653343375023537 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef COS_EXPRESSION_INCLUDED #define COS_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary cos operation. * * @author Jason Rohrer */ class CosExpression : public UnaryOperationExpression { public: /** * Constructs a unary cos operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ CosExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long CosExpression::mID = 11; inline CosExpression::CosExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double CosExpression::evaluate() { return cos( mArgument->evaluate() ); } inline long CosExpression::getID() { return mID; } inline long CosExpression::staticGetID() { return mID; } inline void CosExpression::print() { printf( "( cos" ); mArgument->print(); printf( " )" ); } inline Expression *CosExpression::copy() { CosExpression *copy = new CosExpression( mArgument->copy() ); return copy; } #endif primrose-6+dfsg1.orig/minorGems/math/expression/VariableExpression.h0000644000175000017500000000633307657013075024541 0ustar pabspabs/* * Modification History * * 2003-April-29 Jason Rohrer * Created. * * 2003-May-9 Jason Rohrer * Added support for replacing a variable. */ #ifndef VARIABLE_EXPRESSION_INCLUDED #define VARIABLE_EXPRESSION_INCLUDED #include "Expression.h" #include "Variable.h" /** * Expression that contains a single variable. * * @author Jason Rohrer */ class VariableExpression : public Expression { public: /** * Constructs a variable expression. * * @param inVariable the variable. * Must be destroyed by caller after this class is destroyed. */ VariableExpression( Variable *inVariable ); /** * Gets this expression's variable. * * @return the variable. * Must not be destroyed by caller. */ Variable *getVariable(); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); // overrides the default implementation virtual void replaceVariable( Variable *inTarget, Variable *inReplacement ); protected: static long mID; Variable *mVariable; }; // static init long VariableExpression::mID = 14; inline VariableExpression::VariableExpression( Variable *inVariable ) : mVariable( inVariable ) { } inline Variable *VariableExpression::getVariable() { return mVariable; } inline double VariableExpression::evaluate() { return mVariable->getValue(); } inline long VariableExpression::getID() { return mID; } inline long VariableExpression::staticGetID() { return mID; } inline void VariableExpression::print() { char *varName = mVariable->getName(); printf( " %s ", varName ); delete [] varName; } inline Expression *VariableExpression::copy() { // don't copy our variable VariableExpression *copy = new VariableExpression( mVariable ); return copy; } long VariableExpression::getNumArguments() { return 0; } inline Expression *VariableExpression::getArgument( long inArgumentNumber ) { return NULL; } inline void VariableExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { // do nothing return; } inline Expression *VariableExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline void VariableExpression::replaceVariable( Variable *inTarget, Variable *inReplacement ) { if( mVariable == inTarget ) { mVariable = inReplacement; } } #endif primrose-6+dfsg1.orig/minorGems/math/expression/ExpressionSerializer.h0000644000175000017500000001374707360711032025121 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-7 Jason Rohrer * Removed and extra if statement from the deserialization function. * * 2001-August-31 Jason Rohrer * Added support for MultiConstantArgumentExpressions. * * 2001-September-4 Jason Rohrer * Added support for FixedConstantExpressions. * * 2001-October-9 Jason Rohrer * Fixed a bug in deserializing MultiConstantArgumentExpressions. */ #ifndef EXPRESSION_SERIALIZER_INCLUDED #define EXPRESSION_SERIALIZER_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include "BinaryOperationExpression.h" #include "ConstantExpression.h" #include "InvertExpression.h" #include "ProductExpression.h" #include "PowerExpression.h" #include "SumExpression.h" #include "NegateExpression.h" #include "SinExpression.h" #include "FixedConstantExpression.h" #include "MultiConstantArgumentExpression.h" #include "minorGems/io/OutputStream.h" #include "minorGems/io/InputStream.h" #include "minorGems/io/TypeIO.h" /** * Utility class for serializing expressions * * @author Jason Rohrer */ class ExpressionSerializer { public: /** * Serializes an expression onto a stream. * * @param inExpression the expression to serialize. * @param inOutputStream the stream to write to. * * @return the number of bytes written. */ static long serializeExpression( Expression *inExpression, OutputStream *inOutputStream ); /** * Deserializes an expression from a stream. * * @param outExpression a pointer to where the expression * pointer will be returned. A new expression is created, * and it must be destroyed by the caller. * @param inInputStream the stream to read from. * * @return the number of bytes read. */ static long deserializeExpression( Expression **outExpression, InputStream *inInputStream ); }; // these can both be implemented recursively... exciting! inline long ExpressionSerializer::serializeExpression( Expression *inExpression, OutputStream *inOutputStream ) { int numBytes = 0; long expressionID = inExpression->getID(); // write the expression ID numBytes += inOutputStream->writeLong( expressionID ); // first, deal with constant case if( expressionID == ConstantExpression::staticGetID() ) { // write the constant ConstantExpression *c = (ConstantExpression *)inExpression; numBytes += inOutputStream->writeDouble( c->getValue() ); } else if( expressionID == FixedConstantExpression::staticGetID() ) { // write the constant FixedConstantExpression *c = (FixedConstantExpression *)inExpression; numBytes += inOutputStream->writeDouble( c->getValue() ); } // next deal with the multi-argument case else if( expressionID == MultiConstantArgumentExpression::staticGetID() ) { MultiConstantArgumentExpression *m = (MultiConstantArgumentExpression*)inExpression; Expression *wrappedExpression = m->getWrappedExpression(); numBytes += serializeExpression( wrappedExpression, inOutputStream ); } // finally, deal with the general case else { // write each of the expression's arguments in succession for( int i=0; igetNumArguments(); i++ ) { // call serialize recursively numBytes += serializeExpression( inExpression->getArgument( i ), inOutputStream ); } } return numBytes; } inline long ExpressionSerializer::deserializeExpression( Expression **outExpression, InputStream *inInputStream ) { int numBytes = 0; long expressionID; // read the expression ID numBytes += inInputStream->readLong( &expressionID ); // first, deal with constant case if( expressionID == ConstantExpression::staticGetID() ) { double constantValue; numBytes += inInputStream->readDouble( &constantValue ); *outExpression = new ConstantExpression( constantValue ); } else if( expressionID == FixedConstantExpression::staticGetID() ) { double constantValue; numBytes += inInputStream->readDouble( &constantValue ); *outExpression = new FixedConstantExpression( constantValue ); } // next deal with the multi-argument case else if( expressionID == MultiConstantArgumentExpression::staticGetID() ) { // call deserialize recursively Expression *wrappedExpression; numBytes += deserializeExpression( &wrappedExpression, inInputStream ); MultiConstantArgumentExpression *m = new MultiConstantArgumentExpression( wrappedExpression ); *outExpression = (Expression *)m; } // finally, deal with the general case else { // switch based on expression type // note that we can't use switch/case here because // staticGetID doesn't return a constant if( expressionID == InvertExpression::staticGetID() ) { *outExpression = new InvertExpression( NULL ); } else if( expressionID == NegateExpression::staticGetID() ) { *outExpression = new NegateExpression( NULL ); } else if( expressionID == PowerExpression::staticGetID() ) { *outExpression = new PowerExpression( NULL, NULL ); } else if( expressionID == ProductExpression::staticGetID() ) { *outExpression = new ProductExpression( NULL, NULL ); } else if( expressionID == SinExpression::staticGetID() ) { *outExpression = new SinExpression( NULL ); } else if( expressionID == SumExpression::staticGetID() ) { *outExpression = new SumExpression( NULL, NULL ); } else { printf( "Unknown expression type %d read from stream\n", expressionID ); // default to a constant expression of 0 *outExpression = new ConstantExpression( 0 ); } // now deserialize the arguments // read each of the expression's arguments in succession for( int i=0; i<(*outExpression)->getNumArguments(); i++ ) { // call deserialize recursively Expression *argument; numBytes += deserializeExpression( &argument, inInputStream ); // set the argument into our expression (*outExpression)->setArgument( i, argument ); } } // end non-constant case return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/math/geometry/0000755000175000017500000000000011201637530020176 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/math/geometry/Angle3D.h0000644000175000017500000001106710476647514021611 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-14 Jason Rohrer * Added data members and constructors. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-January-15 Jason Rohrer * Added a print() function. * * 2001-February-10 Jason Rohrer * Added a linear sum function. * * 2001-March-11 Jason Rohrer * Added a scale function. * * 2004-February-13 Jason Rohrer * Added setComponents functions. * * 2006-September-3 Jason Rohrer * Added zero-angle constructor. */ #ifndef ANGLE_3D_INCLUDED #define ANGLE_3D_INCLUDED #include #include "minorGems/io/Serializable.h" /** * Angle in 3-space. * * @author Jason Rohrer */ class Angle3D : public Serializable { public: // rotations in radians around x, y, and z axis double mX, mY, mZ; /** * Constructs an Angle3D. */ Angle3D( double inX, double inY, double inZ ); /** * Constructs a zero angle. */ Angle3D(); /** * Constructs an Angle3D by copying the parameters from * another Angle3D. * * @param inOther angle to copy parameters from. */ Angle3D( Angle3D *inOther ); /** * Sets the components of this angle. */ void setComponents( double inX, double inY, double inZ ); /** * Sets components by copying the parameters from * another Angle3D. * * @param inOther vector to copy parameters from. * Must be destroyed by caller. */ void setComponents( Angle3D *inOther ); /** * Sums another angle with this angle. * * @param inOther angle to add to this angle. */ void add( Angle3D *inOther ); /** * Subtracts a angle from this angle. * * @param inOther angle to subtract from this angle. */ void subtract( Angle3D *inOther ); /** * Multiplies this angle by a scalar. * * @param inScalar scalar to multiply this angle by. */ void scale( double inScalar ); /** * Computes the linear weighted sum of two angles. * * @param inFirst the first angle. * @param inSecond the second angle. * @param inFirstWeight the weight given to the first angle in the * sum. The second angle is weighted (1-inFirstWeight). * * @return the sum angle. Must be destroyed by caller. */ static Angle3D *linearSum( Angle3D *inFirst, Angle3D *inSecond, double inFirstWeight ); /** * Prints this angle to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Angle3D::Angle3D( double inX, double inY, double inZ ) : mX( inX ), mY( inY ), mZ( inZ ) { } inline Angle3D::Angle3D() : mX( 0 ), mY( 0 ), mZ( 0 ) { } inline Angle3D::Angle3D( Angle3D *inOther ) : mX( inOther->mX ), mY( inOther->mY ), mZ( inOther->mZ ) { } inline void Angle3D::setComponents( double inX, double inY, double inZ ) { mX = inX; mY = inY; mZ = inZ; } inline void Angle3D::setComponents( Angle3D *inOther ) { setComponents( inOther->mX, inOther->mY, inOther->mZ ); } inline void Angle3D::add( Angle3D *inOther ) { mX += inOther->mX; mY += inOther->mY; mZ += inOther->mZ; } inline void Angle3D::subtract( Angle3D *inOther ) { mX -= inOther->mX; mY -= inOther->mY; mZ -= inOther->mZ; } inline void Angle3D::scale( double inScalar ) { mX *= inScalar; mY *= inScalar; mZ *= inScalar; } inline Angle3D *Angle3D::linearSum( Angle3D *inFirst, Angle3D *inSecond, double inFirstWeight ) { double secondWeight = 1 - inFirstWeight; double x = inFirstWeight * inFirst->mX + secondWeight * inSecond->mX; double y = inFirstWeight * inFirst->mY + secondWeight * inSecond->mY; double z = inFirstWeight * inFirst->mZ + secondWeight * inSecond->mZ; return new Angle3D( x, y, z ); } inline int Angle3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; numBytes += inOutputStream->writeDouble( mX ); numBytes += inOutputStream->writeDouble( mY ); numBytes += inOutputStream->writeDouble( mZ ); return numBytes; } inline int Angle3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; numBytes += inInputStream->readDouble( &( mX ) ); numBytes += inInputStream->readDouble( &( mY ) ); numBytes += inInputStream->readDouble( &( mZ ) ); return numBytes; } inline void Angle3D::print() { printf( "(%f, %f, %f)", mX, mY, mZ ); } #endif primrose-6+dfsg1.orig/minorGems/math/geometry/Transform3D.h0000644000175000017500000001757307237024761022540 0ustar pabspabs/* * Modification History * * 2001-January-16 Jason Rohrer * Created. * Added a missing getMatrix() function. * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. */ #ifndef TRANSFORM_3D_INCLUDED #define TRANSFORM_3D_INCLUDED #include #include #include "minorGems/io/Serializable.h" #include "Vector3D.h" #include "Angle3D.h" /** * An affine transformation in 3D. * * @author Jason Rohrer */ class Transform3D : public Serializable { public: /** * Creates a new identity transform. */ Transform3D(); /** * Creates a new transform by copying another transform. * * @param inOther the transform to copy. */ Transform3D( Transform3D *inOther ); /** * Adds a rotation to the end of this transform. Note that the * rotations specified by inAngle are applied in the following order: * rotX, rotY, rotZ * * @param inAngle angle rotation to add. Must be destructed by caller. */ void rotate( Angle3D *inAngle ); /** * Adds a scaling operation to the end of this transform. * * @param inScale the uniform scale factor. */ void scale( double inScale ); /** * Adds a scaling operation to the end of this transform. * * @param inScaleX the x direction scale factor. * @param inScaleY the y direction scale factor. * @param inScaleZ the z direction scale factor. */ void scale( double inScaleX, double inScaleY, double inScaleZ ); /** * Adds a translation to the end of this transform. * * @param inTranslation angle rotation to add. * Must be destructed by caller. */ void translate( Vector3D *inTranslation ); /** * Adds a transformation to the end of this transformation. * * @param inTransform the transform to add. inTransform is no * modified by this call, and must be destroyed by the caller. */ void transform( Transform3D *inTransform ); /** * Transforms a vector using the built-up transformation. * * @param inTarget the vector to transform. The object passed * in is modified directly, and must be destroyed by the caller. */ void apply( Vector3D *inTarget ); /** * Transforms a vector using the built-up transformation, but skips * the translation part of the transform. This is useful when * applying the transform to normals, when translations will screw * them up. * * @param inTarget the vector to transform. The object passed * in is modified directly, and must be destroyed by the caller. */ void applyNoTranslation( Vector3D *inTarget ); /** * Gets the transformation matrix underlying this transform. * * @return the transformation matrix. */ double *getMatrix(); /** * Prints the transformation matrix to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); private: double mMatrix[4][4]; /** * Multiplies mMatrix by inMatrix, i.e., mMatrix = inMatrix * mMatrix. * * Note that this reversed multiplication order works for concatonating * transformation matrices when we're using column vectors for our 3D * points. Thus, if after the above operation, we compute: * point = mMatrix * point, * we will be transformping point first by the original * mMatrix and then by inMatrix. * * @param inMatrix the matrix to multiply mMatrix by. */ void multiply( double inMatrix[][4] ); /** * Multiplies inMatrixA by inMatrixB, i.e., * inMatrixA = inMatrixA * inMatrixB. * * @param inMatrixA the first matrix in the multiplication, and * the destination of the result. * @param inMatrixB the second matrix in the multiplication. */ //void multiply( double[4][4] inMatrixA, double[4][4] inMatrixB ); }; inline Transform3D::Transform3D() { double tempM[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; memcpy( mMatrix, tempM, 16 * sizeof( double ) ); } inline Transform3D::Transform3D( Transform3D *inOther ) { memcpy( mMatrix, inOther->getMatrix(), 16 * sizeof( double ) ); } inline void Transform3D::rotate( Angle3D *inAngle ) { double aX = inAngle->mX; double rotX[4][4] = { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 1 } }; rotX[1][1] = cos( aX ); rotX[1][2] = -sin( aX ); rotX[2][1] = sin( aX ); rotX[2][2] = cos( aX ); double aY = inAngle->mY; double rotY[4][4] = { { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 1 } }; rotY[0][0] = cos( aY ); rotY[0][2] = sin( aY ); rotY[2][0] = -sin( aY ); rotY[2][2] = cos( aY ); double aZ = inAngle->mZ; double rotZ[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; rotZ[0][0] = cos( aZ ); rotZ[0][1] = -sin( aZ ); rotZ[1][0] = sin( aZ ); rotZ[1][1] = cos( aZ ); multiply( rotX ); multiply( rotY ); multiply( rotZ ); } inline void Transform3D::scale( double inScale ) { scale( inScale, inScale, inScale ); } inline void Transform3D::scale( double inScaleX, double inScaleY, double inScaleZ ) { double scaleM[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 1 } }; scaleM[0][0] = inScaleX; scaleM[1][1] = inScaleY; scaleM[2][2] = inScaleZ; multiply( scaleM ); } inline void Transform3D::translate( Vector3D *inTranslation ) { double translateM[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; translateM[0][3] = inTranslation->mX; translateM[1][3] = inTranslation->mY; translateM[2][3] = inTranslation->mZ; multiply( translateM ); } inline void Transform3D::transform( Transform3D *inTransform ) { double tempM[4][4]; memcpy( tempM, inTransform->getMatrix(), 16 * sizeof( double ) ); multiply( tempM ); } inline void Transform3D::apply( Vector3D *inTarget ) { double x = inTarget->mX; double y = inTarget->mY; double z = inTarget->mZ; inTarget->mX = mMatrix[0][0] * x + mMatrix[0][1] * y + mMatrix[0][2] * z + mMatrix[0][3]; inTarget->mY = mMatrix[1][0] * x + mMatrix[1][1] * y + mMatrix[1][2] * z + mMatrix[1][3]; inTarget->mZ = mMatrix[2][0] * x + mMatrix[2][1] * y + mMatrix[2][2] * z + mMatrix[2][3]; } inline void Transform3D::applyNoTranslation( Vector3D *inTarget ) { double x = inTarget->mX; double y = inTarget->mY; double z = inTarget->mZ; inTarget->mX = mMatrix[0][0] * x + mMatrix[0][1] * y + mMatrix[0][2] * z; inTarget->mY = mMatrix[1][0] * x + mMatrix[1][1] * y + mMatrix[1][2] * z; inTarget->mZ = mMatrix[2][0] * x + mMatrix[2][1] * y + mMatrix[2][2] * z; } inline void Transform3D::multiply( double inMatrix[][4] ) { double destM[4][4]; for( int dY=0; dY<4; dY++ ) { for( int dX=0; dX<4; dX++ ) { // take a row of inMatrix corresponding to dY // take a column of mMatrix corresponding to dX destM[dY][dX] = 0; for( int i=0; i<4; i++ ) { destM[dY][dX] += inMatrix[dY][i] * mMatrix[i][dX]; } } } memcpy( mMatrix, destM, 16 * sizeof( double ) ); } inline double *Transform3D::getMatrix() { return &( mMatrix[0][0] ); } inline void Transform3D::print() { for( int y=0; y<4; y++ ) { for( int x=0; x<4; x++ ) { printf( "%f ", mMatrix[y][x] ); } printf( "\n" ); } } inline int Transform3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; for( int y=0; y<4; y++ ) { for( int x=0; x<4; x++ ) { numBytes += inOutputStream->writeDouble( mMatrix[y][x] ); } } return numBytes; } inline int Transform3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; for( int y=0; y<4; y++ ) { for( int x=0; x<4; x++ ) { numBytes += inInputStream->readDouble( &( mMatrix[y][x] ) ); } } return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/math/geometry/GeometricObject3D.h0000644000175000017500000000230607216162537023617 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-13 Jason Rohrer * Added scale() and copy() functions. */ #ifndef GEOMETRIC_OBJECT_3D_INCLUDED #define GEOMETRIC_OBJECT_3D_INCLUDED #include "Vector3D.h" /** * Interface for any geometric objects in 3-space. * * @author Jason Rohrer */ class GeometricObject3D { public: /** * Moves the object. * * @param inVector a non-normalized vector describing the motion * of the object. */ virtual void move( Vector3D *inVector ) = 0; /** * Rotates the object about the origin. * * @param inAngle the angle to rotate the object by. */ virtual void rotate( Angle3D *inAngle ) = 0; /** * Rotates the object about the origin in reverse direction. * * @param inAngle the angle to rotate the object by * in reverse direction. */ virtual void reverseRotate( Angle3D *inAngle ) = 0; /** * Scales the object about the origin. * * @param inScalar value by which to scale. */ virtual void scale( double inScalar ) = 0; /** * Makes an identical copy of this geometric object. */ virtual GeometricObject3D *copy() = 0; }; #endif primrose-6+dfsg1.orig/minorGems/math/geometry/Triangle3D.h0000644000175000017500000001710510204365360022310 0ustar pabspabs/* * Modification History * * 2001-April-14 Jason Rohrer * Created. * * 2005-February-15 Jason Rohrer * Made destructor virtual to quell warnings. */ #ifndef TRIANGLE_3D_INCLUDED #define TRIANGLE_3D_INCLUDED #include "GeometricObject3D.h" #include "LineSegment3D.h" #include "minorGems/io/Serializable.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Triangle (in 3-space). * * @author Jason Rohrer */ class Triangle3D : public GeometricObject3D, public Serializable { public: Vector3D *mPoints[3]; /** * Constructs a triangle. * * The vectors are copied, so the caller * is responsible for deallocating the passed in vectors. * * @param inPointA the first point. * @param inPointB the second point. * @param inPointC the third point. * * The "front" face of this trangle is defined as the face * viewed when the above vertices are in counter-clockwise order. */ Triangle3D( Vector3D *inPointA, Vector3D *inPointB, Vector3D *inPointC); /** * Constructs a triangle by copying parameters * from another triangle. * * @param inOtherTriangle the triangle to copy. */ Triangle3D( Triangle3D *inOtherTriangle ); virtual ~Triangle3D(); /** * Gets a line segment from this triangle. * * @param inIndex the line segment to get, in [0,2]. * * @return a new line segment, or NULL if the index is out of range. * Must be destroyed by caller. */ LineSegment3D *getLineSegment( int inIndex ); /** * Gets the normal for the plane containing this triangle. * * @return the normal vector. Must be destroyed by caller. */ Vector3D *getNormal(); /** * Computes the normal projection of a point onto the plane * defined by this triangle. A point is returned even * if it is not inside the bounds of the triangle. * * @param inPoint the point to project. Must be destroyed by caller. * * @return a new vector representing the projection of the point. * Must be destroyed by caller. */ Vector3D *projectOntoPlane( Vector3D *inPoint ); /** * Checks if a point is inside the bounds of this triangle. * * @param inPoint the point to check. Must be destroyed by caller. * * @return true iff the point is in bounds. */ char isInBounds( Vector3D *inPoint ); // these implement the GeometricObject3D interface void move( Vector3D *inVector ); void rotate( Angle3D *inAngle ); void reverseRotate( Angle3D *inAngle ); void scale( double inScalar ); GeometricObject3D *copy(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Triangle3D::Triangle3D( Vector3D *inEndpointA, Vector3D *inEndpointB, Vector3D *inEndpointC ) { mPoints[0] = new Vector3D( inEndpointA ); mPoints[1] = new Vector3D( inEndpointB ); mPoints[2] = new Vector3D( inEndpointC ); } inline Triangle3D::Triangle3D( Triangle3D *inOtherTriangle ) { mPoints[0] = new Vector3D( inOtherTriangle->mPoints[0] ); mPoints[1] = new Vector3D( inOtherTriangle->mPoints[1] ); mPoints[2] = new Vector3D( inOtherTriangle->mPoints[2] ); } inline Triangle3D::~Triangle3D() { delete mPoints[0]; delete mPoints[1]; delete mPoints[2]; } inline LineSegment3D *Triangle3D::getLineSegment( int inIndex ) { if( inIndex < 0 || inIndex > 2 ) { return NULL; } else { // can pass in mPoints directly, since constructor copies them return new LineSegment3D( mPoints[inIndex], mPoints[ ( inIndex + 1 ) % 2 ] ); } } inline Vector3D *Triangle3D::getNormal() { // cross C-B with A-B to get a normal pointing towards // the viewer when seeing the points in counter-clockwise order Vector3D *firstLeg = new Vector3D( mPoints[2] ); firstLeg->subtract( mPoints[1] ); Vector3D *secondLeg = new Vector3D( mPoints[0] ); secondLeg->subtract( mPoints[1] ); Vector3D *normal = firstLeg->cross( secondLeg ); normal->normalize(); delete firstLeg; delete secondLeg; return normal; } inline Vector3D *Triangle3D::projectOntoPlane( Vector3D *inPoint ) { // formula found at: // http://astronomy.swin.edu.au/pbourke/geometry/pointplane/ //minimum distance = //(A (xa - xb) + B (ya - yb) + C (za - zb)) / sqrt(A^2 + B^2 + C^2) Vector3D *normal = getNormal(); double minDistance = normal->mX * ( inPoint->mX - mPoints[0]->mX ) + normal->mY * ( inPoint->mY - mPoints[0]->mY ) + normal->mZ * ( inPoint->mZ - mPoints[0]->mZ ); minDistance = minDistance / sqrt( normal->mX * normal->mX + normal->mY * normal->mY + normal->mZ * normal->mZ ); double dot = inPoint->dot( normal ); Vector3D *returnPoint = new Vector3D( inPoint ); if( dot > 0 ) { // inPoint on front side of plane normal->scale( -minDistance ); } else { // inPoint on back side of plane normal->scale( minDistance ); } returnPoint->add( normal ); delete normal; return returnPoint; } inline char Triangle3D::isInBounds( Vector3D *inPoint ) { // this is a nice formula, found at // http://astronomy.swin.edu.au/pbourke/geometry/insidepoly/ // compute the angle between inPoint and every pair of points in the // triangle (each edge). If the sum is 2*pi, then the point // is inside the triangle. // note that we have a hard-coded epsilon value here double epsilon = 0.000001; double angleSum = 0; Vector3D *firstLeg = new Vector3D( mPoints[0] ); firstLeg->subtract( inPoint ); Vector3D *secondLeg = new Vector3D( mPoints[1] ); secondLeg->subtract( inPoint ); Vector3D *thirdLeg = new Vector3D( mPoints[2] ); thirdLeg->subtract( inPoint ); angleSum += acos( firstLeg->dot( secondLeg ) / ( firstLeg->getLength() * secondLeg->getLength() ) ); angleSum += acos( secondLeg->dot( thirdLeg ) / ( secondLeg->getLength() * thirdLeg->getLength() ) ); angleSum += acos( thirdLeg->dot( firstLeg ) / ( thirdLeg->getLength() * firstLeg->getLength() ) ); delete firstLeg; delete secondLeg; delete thirdLeg; if( angleSum < ( 2 * M_PI - epsilon ) ) { // angle too small for point to be inside plane return false; } else { return true; } } inline void Triangle3D::move( Vector3D *inVector ) { mPoints[0]->add( inVector ); mPoints[1]->add( inVector ); mPoints[2]->add( inVector ); } inline void Triangle3D::rotate( Angle3D *inAngle ) { mPoints[0]->rotate( inAngle ); mPoints[1]->rotate( inAngle ); mPoints[2]->rotate( inAngle ); } inline void Triangle3D::reverseRotate( Angle3D *inAngle ) { mPoints[0]->reverseRotate( inAngle ); mPoints[1]->reverseRotate( inAngle ); mPoints[2]->reverseRotate( inAngle ); } inline void Triangle3D::scale( double inScalar ) { mPoints[0]->scale( inScalar ); mPoints[1]->scale( inScalar ); mPoints[2]->scale( inScalar ); } inline GeometricObject3D *Triangle3D::copy() { Triangle3D *copiedTriangle = new Triangle3D( this ); return (GeometricObject3D*)copiedTriangle; } inline int Triangle3D::serialize( OutputStream *inOutputStream ) { int numBytesWritten = 0; numBytesWritten += mPoints[0]->serialize( inOutputStream ); numBytesWritten += mPoints[1]->serialize( inOutputStream ); numBytesWritten += mPoints[2]->serialize( inOutputStream ); return numBytesWritten; } inline int Triangle3D::deserialize( InputStream *inInputStream ) { int numBytesRead = 0; numBytesRead += mPoints[0]->deserialize( inInputStream ); numBytesRead += mPoints[1]->deserialize( inInputStream ); numBytesRead += mPoints[2]->deserialize( inInputStream ); return numBytesRead; } #endif primrose-6+dfsg1.orig/minorGems/math/geometry/Vector3D.h0000644000175000017500000004320110465423012021777 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-13 Jason Rohrer * Added a function for getting the distance between two vectors. * Added implementations for current functions. * * 2000-December-17 Jason Rohrer * Added a normalize function. * * 2000-December-18 Jason Rohrer * Added a print function. * Added a length function. * * 2000-December-20 Jason Rohrer * Added a cross product function. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. * * 2001-February-10 Jason Rohrer * Added a linear sum function. * * 2003-June-20 Jason Rohrer * Added function for getting Z angle between vectors. * * 2005-February-4 Jason Rohrer * Added setCoordinates functions. * * 2005-February-6 Jason Rohrer * Added equals function. * * 2005-February-15 Jason Rohrer * Added function for getting Y angle between vectors. * * 2005-February-22 Jason Rohrer * Added function for getting X angle between vectors. * Added function for rotating about an arbitrary axis. * * 2005-February-25 Jason Rohrer * Fixed bugs in get_AngleTo functions when vectors are close to equal. * * 2005-February-28 Jason Rohrer * Fixed bug in getXAngleTo. * Fixed bugs in get_AngleTo functions when vectors are close to opposite. * * 2005-March-3 Jason Rohrer * Fixed bug in getAngleTo when vectors are close to equal or opposite. * * 2005-March-18 Jason Rohrer * Added a getXZDistance function. * * 2006-August-6 Jason Rohrer * Added a no-arg constructor. */ #ifndef VECTOR_3D_INCLUDED #define VECTOR_3D_INCLUDED #include #include #include "Angle3D.h" #include "minorGems/io/Serializable.h" /** * Geometric vector in 3-space. * * @author Jason Rohrer */ class Vector3D : public Serializable { public: double mX, mY, mZ; /** * Constructs a Vector3D. */ Vector3D( double inX, double inY, double inZ ); /** * Constructs a zero-filled Vector3D. */ Vector3D(); /** * Constructs a Vector3D by copying the parameters from * another Vector3D. * * @param inOther vector to copy parameters from. */ Vector3D( Vector3D *inOther ); /** * Sets the values in this vector */ void setCoordinates( double inX, double inY, double inZ ); /** * Sets coordinates by copying the parameters from * another Vector3D. * * @param inOther vector to copy parameters from. * Must be destroyed by caller. */ void setCoordinates( Vector3D *inOther ); /** * Normalizes this vector so that it has a length of 1. */ void normalize(); /** * Tests if another vector is equal to this vector. * * @param inOther vector to test for equality with this vector. * * @return true if equal, false if not. */ char equals( Vector3D *inOther ); /** * Sums another vector with this vector. * * @param inOther vector to add to this vector. */ void add( Vector3D *inOther ); /** * Subtracts a vector from this vector. * * @param inOther vector to subtract from this vector. */ void subtract( Vector3D *inOther ); /** * Computes a dot product of this vector with another. * * @param inOther vector to perform the dot product with. * * @return the dot product of the two vectors. */ double dot( Vector3D *inOther ); /** * Computes a cross product of this vector with another * ( this x other ). The cross computed is right handed. * * @param inOther vector to perform the cross product with. * * @return the cross product of the two vectors. Must be * destroyed by caller. */ Vector3D *cross( Vector3D *inOther ); /** * Computes the angle between this vector and another vector. * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in radians. * This angle is around the axis given by the cross of the two * vectors. * Must be destroyed by caller. */ double getAngleTo( Vector3D *inOther ); /** * Rotates this vector around an arbitrary axis. * * @param inAxis the axis of rotation. Must be normalized. * Must be destroyed by caller. * @param the angle in radians. */ void rotate( Vector3D *inAxis, double inAngle ); /** * Computes the angle between this vector and another vector in * the x-y plane (in other words, the z-axis rotation angle). * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in the x-y plane. * Must be destroyed by caller. */ Angle3D *getZAngleTo( Vector3D *inOther ); /** * Computes the angle between this vector and another vector in * the x-z plane (in other words, the y-axis rotation angle). * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in the x-z plane. * Must be destroyed by caller. */ Angle3D *getYAngleTo( Vector3D *inOther ); /** * Computes the angle between this vector and another vector in * the y-z plane (in other words, the x-axis rotation angle). * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in the y-z plane. * Must be destroyed by caller. */ Angle3D *getXAngleTo( Vector3D *inOther ); /** * Computes the linear weighted sum of two vectors. * * @param inFirst the first vector. * @param inSecond the second vector. * @param inFirstWeight the weight given to the first vector in the * sum. The second vector is weighted (1-inFirstWeight). * * @return the sum vector. Must be destroyed by caller. */ static Vector3D *linearSum( Vector3D *inFirst, Vector3D *inSecond, double inFirstWeight ); /** * Gets the length of this vector. * * @return this vector's length. */ double getLength(); /** * Multiplies this vector by a scalar. * * @param inScalar scalar to multiply this vector by. */ void scale( double inScalar ); /** * Gets the scalar distance between two vectors. * * @param inOther vector to compute the distance with. * * @return the distance between the two vectors. */ double getDistance( Vector3D *inOther ); /** * Gets the scalar distance between two vectors ignoring the y * components. * * @param inOther vector to compute the distance with. * * @return the xz distance between the two vectors. */ double getXZDistance( Vector3D *inOther ); /** * Rotates the vector about the origin. * * @param inAngle the angle to rotate the vector by. */ void rotate( Angle3D *inAngle ); /** * Rotates the vector about the origin in reverse direction. * * @param inAngle the angle to rotate the object by * in reverse direction. */ void reverseRotate( Angle3D *inAngle ); /** * Prints this vector to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Vector3D::Vector3D( double inX, double inY, double inZ ) : mX( inX ), mY( inY ), mZ( inZ ) { } inline Vector3D::Vector3D() : mX( 0 ), mY( 0 ), mZ( 0 ) { } inline Vector3D::Vector3D( Vector3D *inOther ) : mX( inOther->mX ), mY( inOther->mY ), mZ( inOther->mZ ) { } inline void Vector3D::setCoordinates( double inX, double inY, double inZ ) { mX = inX; mY = inY; mZ = inZ; } inline void Vector3D::setCoordinates( Vector3D *inOther ) { setCoordinates( inOther->mX, inOther->mY, inOther->mZ ); } inline void Vector3D::normalize() { scale( 1/sqrt( dot( this ) ) ); } inline char Vector3D::equals( Vector3D *inOther ) { return mX == inOther->mX && mY == inOther->mY && mZ == inOther->mZ; } inline void Vector3D::add( Vector3D *inOther ) { mX += inOther->mX; mY += inOther->mY; mZ += inOther->mZ; } inline void Vector3D::subtract( Vector3D *inOther ) { mX -= inOther->mX; mY -= inOther->mY; mZ -= inOther->mZ; } inline double Vector3D::dot( Vector3D *inOther ) { return mX * inOther->mX + mY * inOther->mY + mZ * inOther->mZ; } inline Vector3D *Vector3D::cross( Vector3D *inOther ) { double i = this->mY * inOther->mZ - this->mZ * inOther->mY; double j = this->mZ * inOther->mX - this->mX * inOther->mZ; double k = this->mX * inOther->mY - this->mY * inOther->mX; return new Vector3D( i, j, k ); } inline double Vector3D::getAngleTo( Vector3D *inOther ) { // normalize and remove z component Vector3D *normalThis = new Vector3D( this ); normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->normalize(); double cosineOfAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute cross product of vectors // the magnitude of the cross is the sine of the angle between the two // vectors Vector3D *crossVector = normalThis->cross( normalOther ); double sineOfAngle = crossVector->getLength(); delete crossVector; delete normalThis; delete normalOther; double angle = acos( cosineOfAngle ); if( sineOfAngle > 0 ) { angle = -angle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfAngle >= 1 ) { angle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfAngle <= -1 ) { angle = M_PI; } return angle; } inline void Vector3D::rotate( Vector3D *inAxis, double inAngle ) { // this formula found here: // http://www.gamedev.net/reference/articles/article1199.asp double c = cos( inAngle ); double s = sin( inAngle ); double t = 1 - c; // we assume inAxis is a unit vector (normalized) double x = inAxis->mX; double y = inAxis->mY; double z = inAxis->mZ; double sx = s * x; double sy = s * y; double sz = s * z; double tx = t * x; double ty = t * y; double txx = tx * x; double txy = tx * y; double txz = tx * z; double tyy = ty * y; double tyz = ty * z; double tzz = t * z * z; /* The rotation matrix is: (txx + c) (txy + sz) (txz - sy) (txy - sz) (tyy + c) (tyz + sx) (txz + sy) (tyz - sx) (tzz + c) */ double newX = (txx + c) * mX + (txy + sz) * mY + (txz - sy) * mZ; double newY = (txy - sz) * mX + (tyy + c) * mY + (tyz + sx) * mZ; double newZ = (txz + sy) * mX + (tyz - sx) * mY + (tzz + c) * mZ; mX = newX; mY = newY; mZ = newZ; } inline Angle3D *Vector3D::getZAngleTo( Vector3D *inOther ) { // normalize and remove z component Vector3D *normalThis = new Vector3D( this ); normalThis->mZ = 0; normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->mZ = 0; normalOther->normalize(); double cosineOfZAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute dot product with perpendicular vector to get sine // sign of sine will tell us whether angle is positive or negative Angle3D *rightAngleZ = new Angle3D( 0, 0, M_PI / 2 ); normalThis->rotate( rightAngleZ ); delete rightAngleZ; double sineOfZAngle = normalThis->dot( normalOther ); delete normalThis; delete normalOther; double zAngle = acos( cosineOfZAngle ); if( sineOfZAngle < 0 ) { zAngle = -zAngle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfZAngle >= 1 ) { zAngle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfZAngle <= -1 ) { zAngle = M_PI; } return new Angle3D( 0, 0, zAngle ); } inline Angle3D *Vector3D::getYAngleTo( Vector3D *inOther ) { // normalize and remove y component Vector3D *normalThis = new Vector3D( this ); normalThis->mY = 0; normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->mY = 0; normalOther->normalize(); double cosineOfYAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute dot product with perpendicular vector to get sine // sign of sine will tell us whether angle is positive or negative Angle3D *rightAngleY = new Angle3D( 0, M_PI / 2, 0 ); normalThis->rotate( rightAngleY ); delete rightAngleY; double sineOfYAngle = normalThis->dot( normalOther ); delete normalThis; delete normalOther; double yAngle = acos( cosineOfYAngle ); if( sineOfYAngle < 0 ) { yAngle = -yAngle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfYAngle >= 1 ) { yAngle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfYAngle <= -1 ) { yAngle = M_PI; } return new Angle3D( 0, yAngle, 0 ); } inline Angle3D *Vector3D::getXAngleTo( Vector3D *inOther ) { // normalize and remove y component Vector3D *normalThis = new Vector3D( this ); normalThis->mX = 0; normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->mX = 0; normalOther->normalize(); double cosineOfXAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute dot product with perpendicular vector to get sine // sign of sine will tell us whether angle is positive or negative Angle3D *rightAngleX = new Angle3D( M_PI / 2, 0, 0 ); normalThis->rotate( rightAngleX ); delete rightAngleX; double sineOfXAngle = normalThis->dot( normalOther ); delete normalThis; delete normalOther; double xAngle = acos( cosineOfXAngle ); if( sineOfXAngle < 0 ) { xAngle = -xAngle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfXAngle >= 1 ) { xAngle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfXAngle <= -1 ) { xAngle = M_PI; } return new Angle3D( xAngle, 0, 0 ); } inline Vector3D *Vector3D::linearSum( Vector3D *inFirst, Vector3D *inSecond, double inFirstWeight ) { double secondWeight = 1 - inFirstWeight; double x = inFirstWeight * inFirst->mX + secondWeight * inSecond->mX; double y = inFirstWeight * inFirst->mY + secondWeight * inSecond->mY; double z = inFirstWeight * inFirst->mZ + secondWeight * inSecond->mZ; return new Vector3D( x, y, z ); } inline double Vector3D::getLength() { return sqrt( dot( this ) ); } inline void Vector3D::scale( double inScalar ) { mX *= inScalar; mY *= inScalar; mZ *= inScalar; } inline double Vector3D::getDistance( Vector3D *inOther ) { double delX = mX - inOther->mX; double delY = mY - inOther->mY; double delZ = mZ - inOther->mZ; return sqrt( delX * delX + delY * delY + delZ * delZ ); } inline double Vector3D::getXZDistance( Vector3D *inOther ) { double delX = mX - inOther->mX; double delZ = mZ - inOther->mZ; return sqrt( delX * delX + delZ * delZ ); } inline void Vector3D::rotate( Angle3D *inAngle ) { if( inAngle->mX != 0 ) { double cosTheta = cos( inAngle->mX ); double sinTheta = sin( inAngle->mX ); double oldY = mY; mY = mY * cosTheta - mZ * sinTheta; mZ = oldY * sinTheta + mZ * cosTheta; } if( inAngle->mY != 0 ) { double cosTheta = cos( inAngle->mY ); double sinTheta = sin( inAngle->mY ); double oldX = mX; mX = cosTheta * mX + sinTheta * mZ; mZ = -sinTheta * oldX + cosTheta * mZ; } if( inAngle->mZ != 0 ) { double cosTheta = cos( inAngle->mZ ); double sinTheta = sin( inAngle->mZ ); double oldX = mX; mX = cosTheta * mX - sinTheta * mY; mY = sinTheta * oldX + cosTheta * mY; } } inline void Vector3D::reverseRotate( Angle3D *inAngle ) { Angle3D *actualAngle = new Angle3D( -inAngle->mX, -inAngle->mY, -inAngle->mZ ); rotate( actualAngle ); delete actualAngle; } inline void Vector3D::print() { printf( "(%f, %f, %f)", mX, mY, mZ ); } inline int Vector3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; numBytes += inOutputStream->writeDouble( mX ); numBytes += inOutputStream->writeDouble( mY ); numBytes += inOutputStream->writeDouble( mZ ); return numBytes; } inline int Vector3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; numBytes += inInputStream->readDouble( &( mX ) ); numBytes += inInputStream->readDouble( &( mY ) ); numBytes += inInputStream->readDouble( &( mZ ) ); return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/math/geometry/LineSegment3D.h0000644000175000017500000001134710204365360022757 0ustar pabspabs/* * Modification History * * 2001-April-14 Jason Rohrer * Created. * * 2005-February-15 Jason Rohrer * Made destructor virtual to quell warnings. */ #ifndef LINE_SEGMENT_3D_INCLUDED #define LINE_SEGMENT_3D_INCLUDED #include "GeometricObject3D.h" #include "minorGems/io/Serializable.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Line segment (in 3-space). * * @author Jason Rohrer */ class LineSegment3D : public GeometricObject3D, public Serializable { public: Vector3D *mEndpoints[2]; /** * Constructs a line segment. * * The vectors are copied, so the caller * is responsible for deallocating the passed in vectors. * * @param inEndpointA the first endpoint. * @param inEndpointB the second endpoint. */ LineSegment3D( Vector3D *inEndpointA, Vector3D *inEndpointB ); /** * Constructs a line segment by copying parameters * from another line segment. * * @param inOtherSegment the line segment to copy. */ LineSegment3D( LineSegment3D *inOtherSegment ); virtual ~LineSegment3D(); /** * Gets the projection of a point onto this line segment * * @param inPoint the point to project. Must be destroyed * by caller. * * @return a new vector representing the projected point, or * NULL if the projection is not on this line segment. */ Vector3D *projectPoint( Vector3D *inPoint ); // these implement the GeometricObject3D interface void move( Vector3D *inVector ); void rotate( Angle3D *inAngle ); void reverseRotate( Angle3D *inAngle ); void scale( double inScalar ); GeometricObject3D *copy(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline LineSegment3D::LineSegment3D( Vector3D *inEndpointA, Vector3D *inEndpointB ) { mEndpoints[0] = new Vector3D( inEndpointA ); mEndpoints[1] = new Vector3D( inEndpointB ); } inline LineSegment3D::LineSegment3D( LineSegment3D *inOtherSegment ) { mEndpoints[0] = new Vector3D( inOtherSegment->mEndpoints[0] ); mEndpoints[1] = new Vector3D( inOtherSegment->mEndpoints[1] ); } inline LineSegment3D::~LineSegment3D() { delete mEndpoints[0]; delete mEndpoints[1]; } inline Vector3D *LineSegment3D::projectPoint( Vector3D *inPoint ) { // compute the vector for the underlying line of this segment Vector3D *supportingVector = new Vector3D( mEndpoints[0] ); supportingVector->subtract( mEndpoints[1] ); supportingVector->normalize(); // now find the lengths of the projection of each endpoint // onto this supporting vector double lengthA = supportingVector->dot( mEndpoints[0] ); double lengthB = supportingVector->dot( mEndpoints[1] ); // find the length of the projection of inPoint double lengthInPoint = supportingVector->dot( inPoint ); // projection is off the segment if lengthInPoint is not // between lengthA and lengthB if( lengthInPoint > lengthA && lengthInPoint > lengthB ) { delete supportingVector; return NULL; } else if( lengthInPoint < lengthA && lengthInPoint < lengthB ) { delete supportingVector; return NULL; } else { // length is in between the two // compute difference from A's projection double difference = lengthInPoint - lengthA; Vector3D *returnVector = new Vector3D( mEndpoints[0] ); supportingVector->scale( difference ); returnVector->add( supportingVector ); delete supportingVector; return returnVector; } } inline void LineSegment3D::move( Vector3D *inVector ) { mEndpoints[0]->add( inVector ); mEndpoints[1]->add( inVector ); } inline void LineSegment3D::rotate( Angle3D *inAngle ) { mEndpoints[0]->rotate( inAngle ); mEndpoints[1]->rotate( inAngle ); } inline void LineSegment3D::reverseRotate( Angle3D *inAngle ) { mEndpoints[0]->reverseRotate( inAngle ); mEndpoints[1]->reverseRotate( inAngle ); } inline void LineSegment3D::scale( double inScalar ) { mEndpoints[0]->scale( inScalar ); mEndpoints[1]->scale( inScalar ); } inline GeometricObject3D *LineSegment3D::copy() { LineSegment3D *copiedSegment = new LineSegment3D( this ); return (GeometricObject3D*)copiedSegment; } inline int LineSegment3D::serialize( OutputStream *inOutputStream ) { int numBytesWritten = 0; numBytesWritten += mEndpoints[0]->serialize( inOutputStream ); numBytesWritten += mEndpoints[1]->serialize( inOutputStream ); return numBytesWritten; } inline int LineSegment3D::deserialize( InputStream *inInputStream ) { int numBytesRead = 0; numBytesRead += mEndpoints[0]->deserialize( inInputStream ); numBytesRead += mEndpoints[1]->deserialize( inInputStream ); return numBytesRead; } #endif primrose-6+dfsg1.orig/minorGems/math/geometry/Sphere.h0000644000175000017500000001702507266142706021616 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-14 Jason Rohrer * Added implementation for all member functions. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-January-24 Jason Rohrer * Fixed a bug in the deserialization function. * * 2001-February-2 Jason Rohrer * Added M_PI definition. * * 2001-April-14 Jason Rohrer * Added line segment and triangle intersection tests. */ #ifndef SPHERE_INCLUDED #define SPHERE_INCLUDED #include "GeometricObject3D.h" #include "LineSegment3D.h" #include "Triangle3D.h" #include "minorGems/io/Serializable.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Geometric sphere (in 3-space). * * @author Jason Rohrer */ class Sphere : public GeometricObject3D, public Serializable { public: Vector3D *mCenter; double mRadius; /** * Constructs a Sphere. * * @param inCenter a vector containing the coordinates of the * sphere's center. The vector is copied, so the caller * is responsible for deallocating the passed in vector. * * @param inRadius the radius of the sphere. */ Sphere( Vector3D *inCenter, double inRadius ); /** * Constructs a Sphere by copying parameters from another Sphere. * * @param inOtherSphere the sphere to copy. */ Sphere( Sphere *inOtherSphere ); ~Sphere(); /** * Gets whether this sphere intersects with another. * * @param inOtherSphere the sphere to test for intersection * with this sphere. * * @return true iff this sphere intersects with the other. */ char intersects( Sphere *inOtherSphere ); /** * Gets the normalized direction of intersection of this * sphere with another. * * @param inOtherSphere the sphere to test for intersection * with this sphere. * * @return a normalized vector direction of the intersection, * or NULL if there is no intersection. */ Vector3D *getIntersection( Sphere *inOtherSphere ); /** * Gets whether a line segment intersects or is inside this sphere. * * @param inSegment the segment to test. * * @return true if the segment intersects with or is contained by * this sphere. */ char intersects( LineSegment3D *inSegment ); /** * Gets whether a triangle intesects or is inside this sphere. * * * @param inTriangle the triangle to test. * * @return true if the triangle intersects with or is contained by * this sphere. */ char intersects( Triangle3D *inTriangle ); /** * Gets the volume of this sphere. * * @return the volume of this sphere. */ double getVolume(); // these implement the GeometricObject3D interface void move( Vector3D *inVector ); void rotate( Angle3D *inAngle ); void reverseRotate( Angle3D *inAngle ); void scale( double inScalar ); GeometricObject3D *copy(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Sphere::Sphere( Vector3D *inCenter, double inRadius ) : mCenter( new Vector3D( inCenter ) ), mRadius( inRadius ) { } inline Sphere::Sphere( Sphere *inOtherSphere ) : mCenter( new Vector3D( inOtherSphere->mCenter ) ), mRadius( inOtherSphere->mRadius ) { } inline Sphere::~Sphere() { delete mCenter; } inline char Sphere::intersects( Sphere *inOtherSphere ) { double distance = mCenter->getDistance( inOtherSphere->mCenter ); if( distance <= mRadius + inOtherSphere->mRadius ) { return true; } else { return false; } } inline Vector3D *Sphere::getIntersection( Sphere *inOtherSphere ) { if( intersects( inOtherSphere ) ) { Vector3D * returnVector = new Vector3D( inOtherSphere->mCenter ); returnVector->subtract( mCenter ); returnVector->normalize(); return returnVector; } else { return NULL; } } /* * These intersection algorithms were found in the following paper: * * ERIT -- A Collection of Efficient and Reliable Intersection Tests * by Martin Held * Journal of Graphics Tools */ inline char Sphere::intersects( LineSegment3D *inSegment ) { // first check if either endpoint is inside this sphere if( inSegment->mEndpoints[0]->getDistance( mCenter ) <= mRadius ) { return true; } else if( inSegment->mEndpoints[1]->getDistance( mCenter ) <= mRadius ) { return true; } else { // both endpoints outside // project center onto the line Vector3D *projectedCenter = inSegment->projectPoint( mCenter ); if( projectedCenter == NULL ) { // projection is outside of the segment return false; } else { // projection is inside of the segment // check distance from center double distance = projectedCenter->getDistance( mCenter ); delete projectedCenter; if( distance <= mRadius ) { return true; } else { return false; } } } } inline char Sphere::intersects( Triangle3D *inTriangle ) { char intersectionFound; // first, check each triangle edge segment for intersection LineSegment3D *segmentA = inTriangle->getLineSegment( 0 ); intersectionFound = intersects( segmentA ); delete segmentA; if( intersectionFound ) { return true; } LineSegment3D *segmentB = inTriangle->getLineSegment( 1 ); intersectionFound = intersects( segmentB ); delete segmentB; if( intersectionFound ) { return true; } LineSegment3D *segmentC = inTriangle->getLineSegment( 2 ); intersectionFound = intersects( segmentC ); delete segmentC; if( intersectionFound ) { return true; } // if we're at this point, none of the edges intersected. // we still need to check if the interior region of the triangle // is inside the sphere Vector3D *projectedCenter = inTriangle->projectOntoPlane( mCenter ); if( inTriangle->isInBounds( projectedCenter ) ) { if( projectedCenter->getDistance( mCenter ) <= mRadius ) { // the projected center is inside the triangle and // inside the sphere intersectionFound = true; } else { // the projected center is inside the triangle, but outside // the sphere intersectionFound = false; } } else { // center projection not even in triangle bounds, so no intersection intersectionFound = false; } delete projectedCenter; return intersectionFound; } inline double Sphere::getVolume() { return (4/3) * M_PI * mRadius * mRadius * mRadius; } inline void Sphere::move( Vector3D *inVector ) { mCenter->add( inVector ); } inline void Sphere::rotate( Angle3D *inAngle ) { mCenter->rotate( inAngle ); } inline void Sphere::reverseRotate( Angle3D *inAngle ) { mCenter->reverseRotate( inAngle ); } inline void Sphere::scale( double inScalar ) { mCenter->scale( inScalar ); mRadius *= inScalar; } inline GeometricObject3D *Sphere::copy() { Sphere *copiedSphere = new Sphere( this ); return (GeometricObject3D*)copiedSphere; } inline int Sphere::serialize( OutputStream *inOutputStream ) { int numBytesWritten = 0; numBytesWritten += mCenter->serialize( inOutputStream ); unsigned char* doublePointer = (unsigned char *)( &mRadius ); numBytesWritten += inOutputStream->write( doublePointer, sizeof( double ) ); return numBytesWritten; } inline int Sphere::deserialize( InputStream *inInputStream ) { int numBytesRead = 0; numBytesRead += mCenter->deserialize( inInputStream ); unsigned char* doublePointer = (unsigned char *)( &mRadius ); numBytesRead += inInputStream->read( doublePointer, sizeof( double ) ); return numBytesRead; } #endif primrose-6+dfsg1.orig/minorGems/math/probability/0000755000175000017500000000000011201637530020663 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/math/probability/ProbabilityMassFunction.h0000644000175000017500000002034707376065743025677 0ustar pabspabs/* * Modification History * * 2001-November-17 Jason Rohrer * Created. * Added a constructor for explicit initialization of elements. * Made serializable. * * 2001-November-18 Jason Rohrer * Added function for finding the minimum probability value. * Added a print function. */ #ifndef PROBABILITY_MASS_FUNCTION_INCLUDED #define PROBABILITY_MASS_FUNCTION_INCLUDED #include "minorGems/util/SimpleVector.h" #include "minorGems/util/random/RandomSource.h" #include "minorGems/io/Serializable.h" /** * A discrete probability distribution. * All probabilities are constrained to sum to 1. * * @author Jason Rohrer */ class ProbabilityMassFunction : public Serializable { public: /** * Constructs a probability mass function. * * @param inRandSource the random source to use when * sampling from this function. * Must be destroyed by caller after this class is destroyed. */ ProbabilityMassFunction( RandomSource *inRandSource ); /** * Constructs a probability mass function with elements * already inserted. * * @param inRandSource the random source to use when * sampling from this function. * Must be destroyed by caller after this class is destroyed. * @param inNumElements the number of elements * this PMF should be initialized with. * @param inProbabilities the probabilities to start with. * Note that these values will be normalized before * being stored. * Will be destroyed by this constructor. */ ProbabilityMassFunction( RandomSource *inRandSource, int inNumElements, double *inProbabilities ); virtual ~ProbabilityMassFunction(); /** * Adds an element and a probability to * this mass function. * * Note that since the distribution * always sums to 1, inProbability will * be normalized and thus the value set will likely * not exactly equal the value specified by the caller. * * @param inProbability the probability of the new element. * * @return the index of the new element in the distribution/ * Note that the actual index of this element * may change in the future as elements are added to * and removed from this mass function. */ virtual unsigned long addElement( double inProbability ); /** * Removes an element from this mass function. * * @param inIndex the index of the element. */ virtual void removeElement( unsigned long inIndex ); /** * Gets the probability of an element. * * @param inIndex the index of the element. * * @return the probability of the element at inIndex, * or 0 if inIndex is not a valid index. */ virtual double getProbability( unsigned long inIndex ); /** * Sets the probability of an element. * * Note that since the distribution * always sums to 1, inProbability will * be normalized and thus the value set will likely * not exactly equal the value specified by the caller. * * @param inIndex the index of the element. * @param inProbability the probability of the element at inIndex. */ virtual void setProbability( unsigned long inIndex, double inProbability ); /** * Samples an element at random according to this distribution. * * @return the index of the sampled element. */ virtual unsigned long sampleElement(); /** * Gets the minimum probability value of this function. * * @return the minimum probability value. */ virtual double getMinimumProbability(); /** * Prints the probabilities in this mass function to standard out. */ virtual void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); protected: RandomSource *mRandSource; SimpleVector< double > *mProbabilityVector; /** * Normalizes this distribution so that it sums to 1. */ virtual void normalize(); /** * Gets the net sum of this probability distribution. * * @return the sum of this distribution. */ virtual double getProbabilitySum(); }; inline ProbabilityMassFunction::ProbabilityMassFunction( RandomSource *inRandSource ) : mRandSource( inRandSource ), mProbabilityVector( new SimpleVector< double >() ) { } inline ProbabilityMassFunction::ProbabilityMassFunction( RandomSource *inRandSource, int inNumElements, double *inProbabilities ) : mRandSource( inRandSource ), mProbabilityVector( new SimpleVector< double >( inNumElements ) ){ for( int i=0; ipush_back( inProbabilities[i] ); } normalize(); } inline ProbabilityMassFunction::~ProbabilityMassFunction() { // we can simply delete this vector, since its elements are primitives delete mProbabilityVector; } inline unsigned long ProbabilityMassFunction::addElement( double inProbability ) { mProbabilityVector->push_back( inProbability ); normalize(); return mProbabilityVector->size(); } inline void ProbabilityMassFunction::removeElement( unsigned long inIndex ) { mProbabilityVector->deleteElement( (int)inIndex ); normalize(); } inline double ProbabilityMassFunction::getProbability( unsigned long inIndex ) { if( inIndex >= 0 && inIndex < mProbabilityVector->size() ) { return *( mProbabilityVector->getElement( inIndex ) ); } else { return 0; } } inline void ProbabilityMassFunction::setProbability( unsigned long inIndex, double inProbability ) { if( inIndex >= 0 && inIndex < mProbabilityVector->size() ) { *( mProbabilityVector->getElement( inIndex ) ) = inProbability; normalize(); } } inline unsigned long ProbabilityMassFunction::sampleElement() { double randVal = mRandSource->getRandomDouble(); // compute a running CDF value until we surpass randVal double currentCDFVal = 0; int currentIndex = -1; while( currentCDFVal < randVal ) { currentIndex++; double currentProb = *( mProbabilityVector->getElement( currentIndex ) ); currentCDFVal += currentProb; } // when we exit the while loop, we are at the index of the // element whose probability pushed the CDF past randVal if( currentIndex == -1 ) { // randVal was 0 return 0; } else { return currentIndex; } } inline double ProbabilityMassFunction::getMinimumProbability() { // works, since all values <= 1 double minValue = 2; int numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ) ); if( prob < minValue ) { minValue = prob; } } return minValue; } inline void ProbabilityMassFunction::normalize() { double currentSum = getProbabilitySum(); if( currentSum != 1 ) { double invCurrentSum = 1.0 / currentSum; int numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ); *prob = (*prob) * invCurrentSum; } double newSum = getProbabilitySum(); } } inline double ProbabilityMassFunction::getProbabilitySum() { double sum = 0; int numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ) ); } return sum; } inline void ProbabilityMassFunction::print() { long numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ) ); printf( "%lf ", prob ); } } inline int ProbabilityMassFunction::serialize( OutputStream *inOutputStream ) { int numBytes = 0; long numElements = mProbabilityVector->size(); numBytes += inOutputStream->writeLong( numElements ); for( int i=0; iwriteDouble( *( mProbabilityVector->getElement( i ) ) ); } return numBytes; } inline int ProbabilityMassFunction::deserialize( InputStream *inInputStream ) { int numBytes = 0; delete mProbabilityVector; long numElements; numBytes += inInputStream->readLong( &numElements ); mProbabilityVector = new SimpleVector< double >( numElements ); for( int i=0; ireadDouble( &prob ); mProbabilityVector->push_back( prob ); } normalize(); return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/math/BigInt.cpp0000644000175000017500000003336107474074412020244 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * Changed to remove extra zeros when subtracting. */ #include "BigInt.h" #include "minorGems/util/stringUtils.h" #include #include BigInt::BigInt( int inSign, int inNumBytes, unsigned char *inBytes ) : mSign( inSign ), mNumBytes( inNumBytes ), mBytes( new unsigned char[ inNumBytes ] ) { memcpy( mBytes, inBytes, mNumBytes ); } BigInt::BigInt( int inInt ) { if( inInt > 0 ) { mSign = 1; } else if( inInt == 0 ) { mSign = 0; } else { mSign = -1; // flip sign so conversion works inInt *= -1; } mNumBytes = 4; int bytesToSkip = 0; int baseFactor = 1; mBytes = new unsigned char[ 4 ]; int i; for( i=mNumBytes-1; i>=mNumBytes-4; i-- ) { mBytes[i] = 0xFF & ( inInt / baseFactor ); baseFactor *= 256; } if( mBytes[0] == 0 ) { bytesToSkip++; if( mBytes[1] == 0 ) { bytesToSkip++; if( mBytes[2] == 0 ) { bytesToSkip++; if( mBytes[3] == 0 ) { bytesToSkip++; } } } } mNumBytes -= bytesToSkip; unsigned char *temp = new unsigned char[ mNumBytes ]; memcpy( temp, &( mBytes[ bytesToSkip ] ), mNumBytes ); delete [] mBytes; mBytes = temp; } BigInt::~BigInt() { delete [] mBytes; } BigInt *BigInt::add( BigInt *inOtherInt ) { //char *stringA = convertToHexString(); //char *stringB = inOtherInt->convertToHexString(); //printf( "Adding %s to %s\n", stringA, stringB ); //delete [] stringA; //delete [] stringB; if( mSign == 0 && inOtherInt->mSign == 0 ) { return getZero(); } else if( mSign == 0 && inOtherInt->mSign != 0 ) { return inOtherInt->copy(); } else if( mSign != 0 && inOtherInt->mSign == 0 ) { return copy(); } else if( mSign == -1 && inOtherInt->mSign == -1 ) { // adding two negatives // add them as positives, then flip sign of result BigInt *copyA = copy(); BigInt *copyB = inOtherInt->copy(); copyA->mSign = 1; copyB->mSign = 1; BigInt *result = copyA->add( copyB ); delete copyA; delete copyB; result->mSign = -1; return result; } else if( mSign == 1 && inOtherInt->mSign == -1 ) { // flip other sign and subtract BigInt *copy = inOtherInt->copy(); copy->mSign = 1; BigInt *result = subtract( copy ); delete copy; return result; } else if( mSign == -1 && inOtherInt->mSign == 1 ) { // flip our sign and subtract BigInt *copy = this->copy(); copy->mSign = 1; BigInt *result = inOtherInt->subtract( copy ); delete copy; return result; } else { // both this int and arg int are positive int maxLength = mNumBytes; if( maxLength < inOtherInt->mNumBytes ) { maxLength = inOtherInt->mNumBytes; } // leave room for carry unsigned char *result = new unsigned char[ maxLength + 1 ]; // flip to little-endian order to make adding easier BigInt *intA = flipByteOrder(); BigInt *intB = inOtherInt->flipByteOrder(); int sum = 0; for( int i=0; imNumBytes ) { byteA = intA->mBytes[i]; } if( i < intB->mNumBytes ) { byteB = intB->mBytes[i]; } // add in high-order bits from last sum sum = byteA + byteB + ( sum >> 8 ); // truncate to low-order bits result[i] = (unsigned char)sum; } // stick remaining carry into last byte result[maxLength] = (unsigned char)( sum >> 8 ); BigInt *resultInt; if( result[maxLength] == 0 ) { // result array will be copied skipping carry byte resultInt = new BigInt( 1, maxLength, result ); } else { // keep carry byte resultInt = new BigInt( 1, maxLength + 1, result ); } BigInt *flippedResult = resultInt->flipByteOrder(); delete intA; delete intB; delete resultInt; delete [] result; return flippedResult; } } BigInt *BigInt::subtract( BigInt *inOtherInt ) { //char *stringA = convertToHexString(); //char *stringB = inOtherInt->convertToHexString(); //printf( "Subtracting %s from %s\n", stringB, stringA ); //delete [] stringA; //delete [] stringB; if( mSign == 0 && inOtherInt->mSign == 0 ) { return getZero(); } else if( mSign != 0 && inOtherInt->mSign == 0 ) { return copy(); } else if( mSign == 0 && inOtherInt->mSign != 0 ) { BigInt *copy = inOtherInt->copy(); // flip sign copy->mSign = -( copy->mSign ); return copy; } else if( isEqualTo( inOtherInt ) ) { return getZero(); } else if( inOtherInt->mSign == -1 ) { // flip sign and add BigInt *copy = inOtherInt->copy(); copy->mSign = 1; BigInt *result = add( copy ); delete copy; return result; } else if( mSign == -1 ) { // flip our sign and add BigInt *copy = this->copy(); copy->mSign = 1; BigInt *result = inOtherInt->add( copy ); delete copy; // flip sign of result result->mSign = -1; return result; } else if( isLessThan( inOtherInt ) ) { // trying to subtract a larger number // flip subtraction order, then flip sign of result BigInt *result = inOtherInt->subtract( this ); result->mSign = -( result->mSign ); return result; } else { // we're subtracting a smaller positive number from // a larger positive number int maxLength = mNumBytes; if( maxLength < inOtherInt->mNumBytes ) { maxLength = inOtherInt->mNumBytes; } // result cannot be longer than the larger number unsigned char *result = new unsigned char[ maxLength ]; // flip to little-endian order to make subtracting easier BigInt *intA = this->flipByteOrder(); BigInt *intB = inOtherInt->flipByteOrder(); int borrow = 0; for( int i=0; imNumBytes ) { byteA = intA->mBytes[i]; } if( i < intB->mNumBytes ) { byteB = intB->mBytes[i]; } int diff = byteA - byteB - borrow; // compute next borrow borrow = 0; while( diff < 0 ) { borrow++; diff += 256; } result[i] = (unsigned char)diff; } BigInt *resultInt; if( borrow == 0 ) { // skip any trailing 0 bytes int bytesToSkip = 0; int index = maxLength - 1; while( index >= 0 && result[index] == 0 ) { bytesToSkip ++; index--; } // result array will be copied skipping borrow byte // and skipping any trailing 0 bytes resultInt = new BigInt( true, maxLength - bytesToSkip, result ); } else { printf( "Error: final borrow not zero: %d\n", borrow ); resultInt = getZero(); } BigInt *flippedResult = resultInt->flipByteOrder(); delete intA; delete intB; delete resultInt; delete [] result; return flippedResult; } } char BigInt::isLessThan( BigInt *inOtherInt ) { if( mSign > inOtherInt->mSign ) { return false; } else if( mSign < inOtherInt->mSign ) { return true; } else { // signs are equal if( mSign == 0 ) { return false; } else if( mSign == -1 && mNumBytes > inOtherInt->mNumBytes ) { return true; } else if( mSign == 1 && mNumBytes > inOtherInt->mNumBytes ) { return false; } else if( mSign == 1 && mNumBytes < inOtherInt->mNumBytes ) { return true; } else if( mSign == -1 && mNumBytes < inOtherInt->mNumBytes ) { return false; } else if( isEqualTo( inOtherInt ) ) { return false; } else { // numbers are the same length but are not equal // start with high-order bytes for( int i=0; i inOtherInt->mBytes[i] ) { if( mSign == 1 ) { return false; } else { return true; } } else if ( mBytes[i] < inOtherInt->mBytes[i] ) { if( mSign == 1 ) { return true; } else { return false; } } } // if we made it here, the numbers are equal... // but we tested for equality above: must be an error printf( "Error: equality test in isLessThan failed\n" ); return false; } } } char BigInt::isEqualTo( BigInt *inOtherInt ) { if( mSign != inOtherInt->mSign ) { return false; } else if( mNumBytes != inOtherInt->mNumBytes ) { return false; } else { // same length, same sign for( int i=0; imBytes[i] ) { // mismatch found return false; } } // no mismatch found return true; } } BigInt *BigInt::copy() { return new BigInt( mSign, mNumBytes, mBytes ); } BigInt *BigInt::getZero() { unsigned char bytes[0]; return new BigInt( 0, 0, bytes ); } /* THIS DOES NOT WORK! char *BigInt::convertToDecimalString() { char *tempString = new char[4]; char *resultString = new char[ mNumBytes * 3 + 1 ]; int stringIndex = 0; for( int i=0; i> 4 ); int lowBits = 0xF & ( currentByte ); resultHexString[ hexStringIndex ] = fourBitIntToHex( highBits ); hexStringIndex++; resultHexString[ hexStringIndex ] = fourBitIntToHex( lowBits ); hexStringIndex++; } resultHexString[ hexStringIndex ] = '\0'; return resultHexString; } } int BigInt::convertToInt() { int result = 0; int baseFactor = 1; for( int i=mNumBytes-1; i>=mNumBytes-4; i-- ) { if( i >=0 ) { result += mBytes[i] * baseFactor; } baseFactor *= 256; } return mSign * result; } BigInt *BigInt::flipByteOrder() { BigInt *returnInt = copy(); unsigned char *newBytes = returnInt->mBytes; int newIndex = mNumBytes - 1; for( int i=0; i int main() { unsigned char intA[] = { 100, 200, 99, 23, 89, 100, 233 }; unsigned char intB[] = { 10, 78, 243, 9, 0 }; BigInt *bigIntA = new BigInt( 1, 7, intA ); BigInt *bigIntB = new BigInt( -1, 5, intB ); char *hexA = bigIntA->convertToHexString(); char *hexB = bigIntB->convertToHexString(); printf( "A = %s\n", hexA ); printf( "B = %s\n", hexB ); BigInt *sum = bigIntA->subtract( bigIntB ); char *hexSum = sum->convertToHexString(); printf( "Sum = %s\n", hexSum ); delete [] hexA; delete [] hexB; delete [] hexSum; delete bigIntA; delete bigIntB; delete sum; int c = 0x58B11F; BigInt *intC = new BigInt( c ); char *hexC = intC->convertToHexString(); printf( "C = %s\n", hexC ); int extractedC = intC->convertToInt(); if( extractedC == c ) { printf( "equal\n" ); } else { printf( "not equal\n" ); } delete [] hexC; delete intC; int limit = 300; printf( "Testing pair operations for all pairs in -%d..%d ...\n", limit, limit ); char failed = false; for( int i=-limit; iadd( intJ ); BigInt *intDiff = intI->subtract( intJ ); int sum = i + j; int diff = i - j; if( sum != intSum->convertToInt() ) { printf( "sum test failed for %d, %d\n", i, j ); printf( " real sum = %d, computed sum = %d\n", sum, intSum->convertToInt() ); failed = true; } if( diff != intDiff->convertToInt() ) { printf( "diff test failed for %d, %d\n", i, j ); printf( " real diff = %d, computed diff = %d\n", diff, intDiff->convertToInt() ); failed = true; } if( intI->isLessThan( intJ ) && ( i >= j ) ) { printf( "first less than test failed for %d, %d\n", i, j ); failed = true; } if( intJ->isLessThan( intI ) && ( j >= i ) ) { printf( "second less than test failed for %d, %d\n", i, j ); failed = true; } if( intI->isEqualTo( intJ ) && ( i != j ) ) { printf( "equality test failed for %d, %d\n", i, j ); failed = true; } delete intSum; delete intDiff; delete intJ; } delete intI; } if( !failed ) { printf( "test passed\n" ); } return 0; } primrose-6+dfsg1.orig/minorGems/common.h0000644000175000017500000000033707554101512017060 0ustar pabspabs/* * Modification History * * 2002-October-18 Jason Rohrer * Created. */ #ifndef MINOR_GEMS_COMMON_INCLUDED #define MINOR_GEMS_COMMON_INCLUDED #include "minorGems/util/development/memory/debugMemory.h" #endif primrose-6+dfsg1.orig/minorGems/build/0000755000175000017500000000000011201637525016515 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/build/Makefile.minorGems0000644000175000017500000003014711103254627022120 0ustar pabspabs# # Modification History # # 2004-November-19 Jason Rohrer # Copied from Primrose source. # # 2004-November-21 Jason Rohrer # Added multi-source downloader. # # 2004-December-13 Jason Rohrer # Added socket manager. # # 2005-February-4 Jason Rohrer # Added ScreenGL. # # 2005-February-21 Jason Rohrer # Added SingleTextureGL. # # 2006-November-21 Jason Rohrer # Added PNGImageConverter. # ## # The common portion of Makefiles for all targets that use minorGems, # supplying variable definitions for minorGems. # # Should not be made manually---used by project-specific configure scripts to # build Makefiles. ## # This file is intended to be included in another makefile. # The following variables need to be defined: # # ROOT_PATH the path to the directory containing the minorGems directory # PLATFORM_PATH # PLATFORM # DIRECTORY_PLATFORM_PATH # DIRECTORY_PLATFORM # TIME_PLATFORM_PATH # TIME_PLATFORM # SOCKET_UDP_PLATFORM_PATH # SOCKET_UDP_PLATFORM # Makefile Usage: # -- Include this file # -- Define your project-specific targets and rules # -- Include Makefile.minorGems_targets PLATFORM_DIRECTORY = ${ROOT_PATH}/minorGems/io/file/${DIRECTORY_PLATFORM_PATH}/Directory${DIRECTORY_PLATFORM} PLATFORM_TIME = ${ROOT_PATH}/minorGems/system/${TIME_PLATFORM_PATH}/Time${TIME_PLATFORM} PLATFORM_HOST_ADDRESS = ${ROOT_PATH}/minorGems/network/${PLATFORM_PATH}/HostAddress${PLATFORM} PLATFORM_SOCKET = ${ROOT_PATH}/minorGems/network/${PLATFORM_PATH}/Socket${PLATFORM} PLATFORM_SOCKET_CLIENT = ${ROOT_PATH}/minorGems/network/${PLATFORM_PATH}/SocketClient${PLATFORM} PLATFORM_SOCKET_SERVER = ${ROOT_PATH}/minorGems/network/${PLATFORM_PATH}/SocketServer${PLATFORM} PLATFORM_SOCKET_UDP = ${ROOT_PATH}/minorGems/network/${SOCKET_UDP_PLATFORM_PATH}/SocketUDP${SOCKET_UDP_PLATFORM} PLATFORM_TYPE_IO = ${ROOT_PATH}/minorGems/io/${PLATFORM_PATH}/TypeIO${PLATFORM} PLATFORM_THREAD = ${ROOT_PATH}/minorGems/system/${PLATFORM_PATH}/Thread${PLATFORM} PLATFORM_MUTEX_LOCK = ${ROOT_PATH}/minorGems/system/${PLATFORM_PATH}/MutexLock${PLATFORM} PLATFORM_BINARY_SEMAPHORE = ${ROOT_PATH}/minorGems/system/${PLATFORM_PATH}/BinarySemaphore${PLATFORM} ## # Header, source, and object files. ## SIMPLE_VECTOR_H = ${ROOT_PATH}/minorGems/util/SimpleVector.h OUTPUT_STREAM_H = ${ROOT_PATH}/minorGems/io/OutputStream.h INPUT_STREAM_H = ${ROOT_PATH}/minorGems/io/InputStream.h HOST_ADDRESS_H = ${ROOT_PATH}/minorGems/network/HostAddress.h HOST_ADDRESS_CPP = ${PLATFORM_HOST_ADDRESS}.cpp HOST_ADDRESS_O = ${PLATFORM_HOST_ADDRESS}.o SOCKET_H = ${ROOT_PATH}/minorGems/network/Socket.h SOCKET_CPP = ${PLATFORM_SOCKET}.cpp SOCKET_O = ${PLATFORM_SOCKET}.o SOCKET_CLIENT_H = ${ROOT_PATH}/minorGems/network/SocketClient.h SOCKET_CLIENT_CPP = ${PLATFORM_SOCKET_CLIENT}.cpp SOCKET_CLIENT_O = ${PLATFORM_SOCKET_CLIENT}.o SOCKET_SERVER_H = ${ROOT_PATH}/minorGems/network/SocketServer.h SOCKET_SERVER_CPP = ${PLATFORM_SOCKET_SERVER}.cpp SOCKET_SERVER_O = ${PLATFORM_SOCKET_SERVER}.o SOCKET_UDP_H = ${ROOT_PATH}/minorGems/network/SocketUDP.h SOCKET_UDP_CPP = ${PLATFORM_SOCKET_UDP}.cpp SOCKET_UDP_O = ${PLATFORM_SOCKET_UDP}.o SOCKET_STREAM_H = ${ROOT_PATH}/minorGems/network/SocketStream.h NETWORK_FUNCTION_LOCKS = ${ROOT_PATH}/minorGems/network/NetworkFunctionLocks NETWORK_FUNCTION_LOCKS_H = ${NETWORK_FUNCTION_LOCKS}.h NETWORK_FUNCTION_LOCKS_CPP = ${NETWORK_FUNCTION_LOCKS}.cpp NETWORK_FUNCTION_LOCKS_O = ${NETWORK_FUNCTION_LOCKS}.o SOCKET_MANAGER = ${ROOT_PATH}/minorGems/network/SocketManager SOCKET_MANAGER_H = ${SOCKET_MANAGER}.h SOCKET_MANAGER_CPP = ${SOCKET_MANAGER}.cpp SOCKET_MANAGER_O = ${SOCKET_MANAGER}.o LOOKUP_THREAD = ${ROOT_PATH}/minorGems/network/LookupThread LOOKUP_THREAD_H = ${LOOKUP_THREAD}.h LOOKUP_THREAD_CPP = ${LOOKUP_THREAD}.cpp LOOKUP_THREAD_O = ${LOOKUP_THREAD}.o PATH_H = ${ROOT_PATH}/minorGems/io/file/Path.h PATH_CPP = ${ROOT_PATH}/minorGems/io/file/${PLATFORM_PATH}/Path${PLATFORM}.cpp PATH_O = ${ROOT_PATH}/minorGems/io/file/${PLATFORM_PATH}/Path${PLATFORM}.o FILE_H = ${ROOT_PATH}/minorGems/io/file/File.h FILE_OUTPUT_STREAM_H = ${ROOT_PATH}/minorGems/io/file/FileOutputStream.h FILE_INPUT_STREAM_H = ${ROOT_PATH}/minorGems/io/file/FileInputStream.h DIRECTORY_H = ${ROOT_PATH}/minorGems/io/file/Directory.h DIRECTORY_CPP = ${PLATFORM_DIRECTORY}.cpp DIRECTORY_O = ${PLATFORM_DIRECTORY}.o TYPE_IO_H = ${ROOT_PATH}/minorGems/io/TypeIO.h TYPE_IO_CPP = ${PLATFORM_TYPE_IO}.cpp TYPE_IO_O = ${PLATFORM_TYPE_IO}.o TIME_H = ${ROOT_PATH}/minorGems/system/Time.h TIME_CPP = ${PLATFORM_TIME}.cpp TIME_O = ${PLATFORM_TIME}.o THREAD_H = ${ROOT_PATH}/minorGems/system/Thread.h THREAD_CPP = ${PLATFORM_THREAD}.cpp THREAD_O = ${PLATFORM_THREAD}.o MUTEX_LOCK_H = ${ROOT_PATH}/minorGems/system/MutexLock.h MUTEX_LOCK_CPP = ${PLATFORM_MUTEX_LOCK}.cpp MUTEX_LOCK_O = ${PLATFORM_MUTEX_LOCK}.o BINARY_SEMAPHORE_H = ${ROOT_PATH}/minorGems/system/BinarySemaphore.h BINARY_SEMAPHORE_CPP = ${PLATFORM_BINARY_SEMAPHORE}.cpp BINARY_SEMAPHORE_O = ${PLATFORM_BINARY_SEMAPHORE}.o SEMAPHORE_H = ${ROOT_PATH}/minorGems/system/Semaphore.h APP_LOG_H = ${ROOT_PATH}/minorGems/util/log/AppLog.h APP_LOG_CPP = ${ROOT_PATH}/minorGems/util/log/AppLog.cpp APP_LOG_O = ${ROOT_PATH}/minorGems/util/log/AppLog.o PRINT_LOG_H = ${ROOT_PATH}/minorGems/util/log/PrintLog.h PRINT_LOG_CPP = ${ROOT_PATH}/minorGems/util/log/PrintLog.cpp PRINT_LOG_O = ${ROOT_PATH}/minorGems/util/log/PrintLog.o FILE_LOG_H = ${ROOT_PATH}/minorGems/util/log/FileLog.h FILE_LOG_CPP = ${ROOT_PATH}/minorGems/util/log/FileLog.cpp FILE_LOG_O = ${ROOT_PATH}/minorGems/util/log/FileLog.o LOG_H = ${ROOT_PATH}/minorGems/util/log/Log.h LOG_CPP = ${ROOT_PATH}/minorGems/util/log/Log.cpp LOG_O = ${ROOT_PATH}/minorGems/util/log/Log.o PRINT_UTILS_H = ${ROOT_PATH}/minorGems/util/printUtils.h PRINT_UTILS_CPP = ${ROOT_PATH}/minorGems/util/printUtils.cpp PRINT_UTILS_O = ${ROOT_PATH}/minorGems/util/printUtils.o WEB_CLIENT_H = ${ROOT_PATH}/minorGems/network/web/WebClient.h WEB_CLIENT_CPP = ${ROOT_PATH}/minorGems/network/web/WebClient.cpp WEB_CLIENT_O = ${ROOT_PATH}/minorGems/network/web/WebClient.o URL_UTILS_H = ${ROOT_PATH}/minorGems/network/web/URLUtils.h URL_UTILS_CPP = ${ROOT_PATH}/minorGems/network/web/URLUtils.cpp URL_UTILS_O = ${ROOT_PATH}/minorGems/network/web/URLUtils.o MIME_TYPER = ${ROOT_PATH}/minorGems/network/web/MimeTyper MIME_TYPER_H = ${MIME_TYPER}.h MIME_TYPER_CPP = ${MIME_TYPER}.cpp MIME_TYPER_O = ${MIME_TYPER}.o WEB_SERVER_PATH = ${ROOT_PATH}/minorGems/network/web/server WEB_SERVER = ${WEB_SERVER_PATH}/WebServer WEB_SERVER_H = ${WEB_SERVER}.h WEB_SERVER_CPP = ${WEB_SERVER}.cpp WEB_SERVER_O = ${WEB_SERVER}.o REQUEST_HANDLING_THREAD = ${WEB_SERVER_PATH}/RequestHandlingThread REQUEST_HANDLING_THREAD_H = ${REQUEST_HANDLING_THREAD}.h REQUEST_HANDLING_THREAD_CPP = ${REQUEST_HANDLING_THREAD}.cpp REQUEST_HANDLING_THREAD_O = ${REQUEST_HANDLING_THREAD}.o THREAD_HANDLING_THREAD = ${WEB_SERVER_PATH}/ThreadHandlingThread THREAD_HANDLING_THREAD_H = ${THREAD_HANDLING_THREAD}.h THREAD_HANDLING_THREAD_CPP = ${THREAD_HANDLING_THREAD}.cpp THREAD_HANDLING_THREAD_O = ${THREAD_HANDLING_THREAD}.o CONNECTION_PERMISSION_HANDLER = ${WEB_SERVER_PATH}/ConnectionPermissionHandler CONNECTION_PERMISSION_HANDLER_H = ${CONNECTION_PERMISSION_HANDLER}.h CONNECTION_PERMISSION_HANDLER_CPP = ${CONNECTION_PERMISSION_HANDLER}.cpp CONNECTION_PERMISSION_HANDLER_O = ${CONNECTION_PERMISSION_HANDLER}.o STOP_SIGNAL_THREAD = ${ROOT_PATH}/minorGems/system/StopSignalThread STOP_SIGNAL_THREAD_H = ${STOP_SIGNAL_THREAD}.h STOP_SIGNAL_THREAD_CPP = ${STOP_SIGNAL_THREAD}.cpp STOP_SIGNAL_THREAD_O = ${STOP_SIGNAL_THREAD}.o FINISHED_SIGNAL_THREAD = ${ROOT_PATH}/minorGems/system/FinishedSignalThread FINISHED_SIGNAL_THREAD_H = ${FINISHED_SIGNAL_THREAD}.h FINISHED_SIGNAL_THREAD_CPP = ${FINISHED_SIGNAL_THREAD}.cpp FINISHED_SIGNAL_THREAD_O = ${FINISHED_SIGNAL_THREAD}.o FINISHED_SIGNAL_THREAD_MANAGER = ${ROOT_PATH}/minorGems/system/FinishedSignalThreadManager FINISHED_SIGNAL_THREAD_MANAGER_H = ${FINISHED_SIGNAL_THREAD_MANAGER}.h FINISHED_SIGNAL_THREAD_MANAGER_CPP = ${FINISHED_SIGNAL_THREAD_MANAGER}.cpp FINISHED_SIGNAL_THREAD_MANAGER_O = ${FINISHED_SIGNAL_THREAD_MANAGER}.o STRING_BUFFER_OUTPUT_STREAM_H = ${ROOT_PATH}/minorGems/util/StringBufferOutputStream.h STRING_BUFFER_OUTPUT_STREAM_CPP = ${ROOT_PATH}/minorGems/util/StringBufferOutputStream.cpp STRING_BUFFER_OUTPUT_STREAM_O = ${ROOT_PATH}/minorGems/util/StringBufferOutputStream.o XML_UTILS_H = ${ROOT_PATH}/minorGems/formats/xml/XMLUtils.h XML_UTILS_CPP = ${ROOT_PATH}/minorGems/formats/xml/XMLUtils.cpp XML_UTILS_O = ${ROOT_PATH}/minorGems/formats/xml/XMLUtils.o HTML_UTILS_H = ${ROOT_PATH}/minorGems/formats/html/HTMLUtils.h HTML_UTILS_CPP = ${ROOT_PATH}/minorGems/formats/html/HTMLUtils.cpp HTML_UTILS_O = ${ROOT_PATH}/minorGems/formats/html/HTMLUtils.o SETTINGS_MANAGER_H = ${ROOT_PATH}/minorGems/util/SettingsManager.h SETTINGS_MANAGER_CPP = ${ROOT_PATH}/minorGems/util/SettingsManager.cpp SETTINGS_MANAGER_O = ${ROOT_PATH}/minorGems/util/SettingsManager.o TRANSLATION_MANAGER_H = ${ROOT_PATH}/minorGems/util/TranslationManager.h TRANSLATION_MANAGER_CPP = ${ROOT_PATH}/minorGems/util/TranslationManager.cpp TRANSLATION_MANAGER_O = ${ROOT_PATH}/minorGems/util/TranslationManager.o STRING_UTILS = ${ROOT_PATH}/minorGems/util/stringUtils STRING_UTILS_H = ${STRING_UTILS}.h STRING_UTILS_CPP = ${STRING_UTILS}.cpp STRING_UTILS_O = ${STRING_UTILS}.o SHA1 = ${ROOT_PATH}/minorGems/crypto/hashes/sha1 SHA1_H = ${SHA1}.h SHA1_CPP = ${SHA1}.cpp SHA1_O = ${SHA1}.o MEMORY_TRACK_H = ${ROOT_PATH}/minorGems/util/development/memory/MemoryTrack.h MEMORY_TRACK_CPP = ${ROOT_PATH}/minorGems/util/development/memory/MemoryTrack.cpp MEMORY_TRACK_O = ${ROOT_PATH}/minorGems/util/development/memory/MemoryTrack.o DEBUG_MEMORY = ${ROOT_PATH}/minorGems/util/development/memory/debugMemory DEBUG_MEMORY_H = ${DEBUG_MEMORY}.h DEBUG_MEMORY_CPP = ${DEBUG_MEMORY}.cpp DEBUG_MEMORY_O = ${DEBUG_MEMORY}.o # variable pointing to both necessary .o files for memory tracking MEMORY_TRACKER_O = ${MEMORY_TRACK_O} ${DEBUG_MEMORY_O} # p2p parts HOST_CATCHER = ${ROOT_PATH}/minorGems/network/p2pParts/HostCatcher HOST_CATCHER_H = ${HOST_CATCHER}.h HOST_CATCHER_CPP = ${HOST_CATCHER}.cpp HOST_CATCHER_O = ${HOST_CATCHER}.o OUTBOUND_CHANNEL = ${ROOT_PATH}/minorGems/network/p2pParts/OutboundChannel OUTBOUND_CHANNEL_H = ${OUTBOUND_CHANNEL}.h OUTBOUND_CHANNEL_CPP = ${OUTBOUND_CHANNEL}.cpp OUTBOUND_CHANNEL_O = ${OUTBOUND_CHANNEL}.o DUPLICATE_MESSAGE_DETECTOR = ${ROOT_PATH}/minorGems/network/p2pParts/DuplicateMessageDetector DUPLICATE_MESSAGE_DETECTOR_H = ${DUPLICATE_MESSAGE_DETECTOR}.h DUPLICATE_MESSAGE_DETECTOR_CPP = ${DUPLICATE_MESSAGE_DETECTOR}.cpp DUPLICATE_MESSAGE_DETECTOR_O = ${DUPLICATE_MESSAGE_DETECTOR}.o PROTOCOL_UTILS = ${ROOT_PATH}/minorGems/network/p2pParts/protocolUtils PROTOCOL_UTILS_H = ${PROTOCOL_UTILS}.h PROTOCOL_UTILS_CPP = ${PROTOCOL_UTILS}.cpp PROTOCOL_UTILS_O = ${PROTOCOL_UTILS}.o MESSAGE_PER_SECOND_LIMITER = ${ROOT_PATH}/minorGems/network/p2pParts/MessagePerSecondLimiter MESSAGE_PER_SECOND_LIMITER_H = ${MESSAGE_PER_SECOND_LIMITER}.h MESSAGE_PER_SECOND_LIMITER_CPP = ${MESSAGE_PER_SECOND_LIMITER}.cpp MESSAGE_PER_SECOND_LIMITER_O = ${MESSAGE_PER_SECOND_LIMITER}.o MULTI_SOURCE_DOWNLOADER = ${ROOT_PATH}/minorGems/network/p2pParts/MultiSourceDownloader MULTI_SOURCE_DOWNLOADER_H = ${MULTI_SOURCE_DOWNLOADER}.h MULTI_SOURCE_DOWNLOADER_CPP = ${MULTI_SOURCE_DOWNLOADER}.cpp MULTI_SOURCE_DOWNLOADER_O = ${MULTI_SOURCE_DOWNLOADER}.o ENCODING_UTILS = ${ROOT_PATH}/minorGems/formats/encodingUtils ENCODING_UTILS_H = ${ENCODING_UTILS}.h ENCODING_UTILS_CPP = ${ENCODING_UTILS}.cpp ENCODING_UTILS_O = ${ENCODING_UTILS}.o SCREEN_GL = ${ROOT_PATH}/minorGems/graphics/openGL/ScreenGL SCREEN_GL_H = ${SCREEN_GL}.h SCREEN_GL_CPP = ${SCREEN_GL}.cpp SCREEN_GL_O = ${SCREEN_GL}.o SCREEN_GL_SDL_CPP = ${SCREEN_GL}_SDL.cpp SCREEN_GL_SDL_O = ${SCREEN_GL}_SDL.o SINGLE_TEXTURE_GL = ${ROOT_PATH}/minorGems/graphics/openGL/SingleTextureGL SINGLE_TEXTURE_GL_H = ${SINGLE_TEXTURE_GL}.h SINGLE_TEXTURE_GL_CPP = ${SINGLE_TEXTURE_GL}.cpp SINGLE_TEXTURE_GL_O = ${SINGLE_TEXTURE_GL}.o PNG_IMAGE_CONVERTER = ${ROOT_PATH}/minorGems/graphics/converters/PNGImageConverter PNG_IMAGE_CONVERTER_H = ${PNG_IMAGE_CONVERTER}.h PNG_IMAGE_CONVERTER_CPP = ${PNG_IMAGE_CONVERTER}.cpp PNG_IMAGE_CONVERTER_O = ${PNG_IMAGE_CONVERTER}.oprimrose-6+dfsg1.orig/minorGems/build/Makefile.minorGems_targets0000644000175000017500000001420611103254627023647 0ustar pabspabs# # Modification History # # 2004-November-19 Jason Rohrer # Copied from Primrose source. # # 2004-November-21 Jason Rohrer # Added multi-source downloader. # # 2004-December-13 Jason Rohrer # Added socket manager. # # 2005-February-4 Jason Rohrer # Added ScreenGL. # # 2005-February-21 Jason Rohrer # Added SingleTextureGL. # # 2006-April-24 Jason Rohrer # Added conditional compilation of files that depend on OpenGL/GLUT. # # 2006-November-21 Jason Rohrer # Added PNGImageConverter. # # 2007-April-23 Jason Rohrer # Changed to make compilation of all objects individually conditional using # NEEDED_MINOR_GEMS_OBJECTS variable. # ## # The common portion of Makefiles for all targets that use minorGems, # supplying target dependencies for minorGems targets. # # # Should not be made manually---used by project-specific configure scripts to # build Makefiles. ## # Makefile Usage (these must be in your Makefile in the following order): # -- Include Makefile.minorGems # -- List the desired minorGems objects in NEEDED_MINOR_GEMS_OBJECTS # Example: # NEEDED_MINOR_GEMS_OBJECTS = \ # ${SOCKET_O} \ # ${SOCKET_CLIENT_O} \ # ${SOCKET_SERVER_O} \ # ${HOST_ADDRESS_O} # -- Define your project-specific targets and rules # -- Include this file ## # Dependencies for minorGems objects. ## # first, take the object list and turn it into a source list MINOR_GEMS_SOURCE = ${NEEDED_MINOR_GEMS_OBJECTS:.o=.cpp} # Here is what the old, manual list looked like, for reference: # # MINOR_GEMS_SOURCE = \ # ${HOST_ADDRESS_CPP} \ # ${SOCKET_CPP} \ # ${SOCKET_SERVER_CPP} \ # ${SOCKET_CLIENT_CPP} \ # ${SOCKET_UDP_CPP} \ # ${NETWORK_FUNCTION_LOCKS_CPP} \ # ${SOCKET_MANAGER_CPP} \ # ${PATH_CPP} \ # ${DIRECTORY_CPP} \ # ${TYPE_IO_CPP} \ # ${TIME_CPP} \ # ${THREAD_CPP} \ # ${MUTEX_LOCK_CPP} \ # ${BINARY_SEMAPHORE_CPP} \ # ${APP_LOG_CPP} \ # ${PRINT_LOG_CPP} \ # ${FILE_LOG_CPP} \ # ${LOG_CPP} \ # ${PRINT_UTILS_CPP} \ # ${WEB_CLIENT_CPP} \ # ${URL_UTILS_CPP} \ # ${MIME_TYPER_CPP} \ # ${STRING_BUFFER_OUTPUT_STREAM_CPP} \ # ${XML_UTILS_CPP} \ # ${HTML_UTILS_CPP} \ # ${SETTINGS_MANAGER_CPP} \ # ${TRANSLATION_MANAGER_CPP} \ # ${STRING_UTILS_CPP} \ # ${SHA1_CPP} \ # ${MEMORY_TRACK_CPP} \ # ${DEBUG_MEMORY_CPP} \ # ${HOST_CATCHER_CPP} \ # ${OUTBOUND_CHANNEL_CPP} \ # ${DUPLICATE_MESSAGE_DETECTOR_CPP} \ # ${PROTOCOL_UTILS_CPP} \ # ${MESSAGE_PER_SECOND_LIMITER_CPP} \ # ${MULTI_SOURCE_DOWNLOADER_CPP} \ # ${ENCODING_UTILS_CPP} \ # ${WEB_SERVER_CPP} \ # ${REQUEST_HANDLING_THREAD_CPP} \ # ${THREAD_HANDLING_THREAD_CPP} \ # ${CONNECTION_PERMISSION_HANDLER_CPP} \ # ${STOP_SIGNAL_THREAD_CPP} \ # ${FINISHED_SIGNAL_THREAD_CPP} \ # ${FINISHED_SIGNAL_THREAD_MANAGER_CPP} \ # ${OPEN_GL_CPP_FILES} \ # ${PNG_IMAGE_CONVERTER_CPP} # next, generate dependencies using g++ # sed command for fixing up the dependencies generated by g++ # g++ (pre-3.0) leaves the path off of the .o target # look for a .o file at the beginning of a line (in other words, one # without a path), and replace it with the full-path version. # This should be compatible with g++ 3.0, since we only replace .o names # that occur at the beginning of a line (using the "^" modifier) # Split into two parts because sed (on certain platforms) cannot process # a string of commands as one long argument MINOR_GEMS_SED_FIX_COMMAND_A = sed ' \ s/^HostAddress.*\.o/$${HOST_ADDRESS_O}/; \ s/^SocketServer.*\.o/$${SOCKET_SERVER_O}/; \ s/^SocketClient.*\.o/$${SOCKET_CLIENT_O}/; \ s/^SocketUDP.*\.o/$${SOCKET_UDP_O}/; \ s/^SocketManager.*\.o/$${SOCKET_MANAGER_O}/; \ s/^Socket.*\.o/$${SOCKET_O}/; \ s/^NetworkFunctionLocks.*\.o/$${NETWORK_FUNCTION_LOCKS_O}/; \ s/^LookupThread.*\.o/$${LOOKUP_THREAD_O}/; \ s/^Path.*\.o/$${PATH_O}/; \ s/^Directory.*\.o/$${DIRECTORY_O}/; \ s/^TypeIO.*\.o/$${TYPE_IO_O}/; \ s/^Time.*\.o/$${TIME_O}/; \ s/^MutexLock.*\.o/$${MUTEX_LOCK_O}/; \ s/^BinarySemaphore.*\.o/$${BINARY_SEMAPHORE_O}/; \ s/^AppLog.*\.o/$${APP_LOG_O}/; \ s/^PrintLog.*\.o/$${PRINT_LOG_O}/; \ s/^FileLog.*\.o/$${FILE_LOG_O}/; \ s/^Log.*\.o/$${LOG_O}/; \ s/^PrintUtils.*\.o/$${PRINT_UTILS_O}/; \ s/^WebClient.*\.o/$${WEB_CLIENT_O}/; \ s/^URLUtils.*\.o/$${URL_UTILS_O}/; \ s/^MimeTyper.*\.o/$${MIME_TYPER_O}/; \ s/^StringBufferOutputStream.*\.o/$${STRING_BUFFER_OUTPUT_STREAM_O}/; \ s/^XMLUtils.*\.o/$${XML_UTILS_O}/; \ s/^HTMLUtils.*\.o/$${HTML_UTILS_O}/; \ s/^SettingsManager.*\.o/$${SETTINGS_MANAGER_O}/; \ s/^TranslationManager.*\.o/$${TRANSLATION_MANAGER_O}/; \ s/^stringUtils.*\.o/$${STRING_UTILS_O}/; \ s/^sha1.*\.o/$${SHA1_O}/; \ ' MINOR_GEMS_SED_FIX_COMMAND_B = sed ' \ s/^MemoryTrack.*\.o/$${MEMORY_TRACK_O}/; \ s/^DebugMemory.*\.o/$${DEBUG_MEMORY_O}/; \ s/^HostCatcher.*\.o/$${HOST_CATCHER_O}/; \ s/^OutboundChannel.*\.o/$${OUTBOUND_CHANNEL_O}/; \ s/^DuplicateMessageDetector.*\.o/$${DUPLICATE_MESSAGE_DETECTOR_O}/; \ s/^protocolUtils.*\.o/$${PROTOCOL_UTILS_O}/; \ s/^MessagePerSecondLimiter.*\.o/$${MESSAGE_PER_SECOND_LIMITER_O}/; \ s/^MultiSourceDownloader.*\.o/$${MULTI_SOURCE_DOWNLOADER_O}/; \ s/^encodingUtils.*\.o/$${ENCODING_UTILS_O}/; \ s/^WebServer.*\.o/$${WEB_SERVER_O }/; \ s/^RequestHandlingThread.*\.o/$${REQUEST_HANDLING_THREAD_O}/; \ s/^ThreadHandlingThread.*\.o/$${THREAD_HANDLING_THREAD_O}/; \ s/^Thread.*\.o/$${THREAD_O}/; \ s/^ConnectionPermissionHandler.*\.o/$${CONNECTION_PERMISSION_HANDLER_O}/; \ s/^StopSignalThread.*\.o/$${STOP_SIGNAL_THREAD_O}/; \ s/^FinishedSignalThreadManager.*\.o/$${FINISHED_SIGNAL_THREAD_MANAGER_O}/; \ s/^FinishedSignalThread.*\.o/$${FINISHED_SIGNAL_THREAD_O}/; \ s/^ScreenGL.*\.o/$${SCREEN_GL_O}/; \ s/^ScreenGLSDL.*\.o/$${SCREEN_GL_SDL_O}/; \ s/^SingleTextureGL.*\.o/$${SINGLE_TEXTURE_GL_O}/; \ s/^PNGImageConverter.*\.o/$${PNG_IMAGE_CONVERTER_O}/; \ ' MINOR_GEMS_DEPENDENCY_FILE = Makefile.minorGems_dependencies # build the dependency file ${MINOR_GEMS_DEPENDENCY_FILE}: ${MINOR_GEMS_SOURCE} rm -f ${MINOR_GEMS_DEPENDENCY_FILE} ${COMPILE} -I${ROOT_PATH} -MM ${MINOR_GEMS_SOURCE} >> ${MINOR_GEMS_DEPENDENCY_FILE}.temp cat ${MINOR_GEMS_DEPENDENCY_FILE}.temp | ${MINOR_GEMS_SED_FIX_COMMAND_A} | ${MINOR_GEMS_SED_FIX_COMMAND_B} >> ${MINOR_GEMS_DEPENDENCY_FILE} rm -f ${MINOR_GEMS_DEPENDENCY_FILE}.temp include ${MINOR_GEMS_DEPENDENCY_FILE} primrose-6+dfsg1.orig/minorGems/io/0000755000175000017500000000000011201637530016021 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/Serializable.h0000644000175000017500000000345610340437222020607 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * Added untility functions for converting integers to and from byte arrays. * * 2001-January-15 Jason Rohrer * Made utility functions static. * Fixed a major bug in the longToBytes function. * * 2001-February-3 Jason Rohrer * Removed the long io functions, which are now contained in the * input- and outputStream classes. * * 2005-November-21 Jason Rohrer * Fixed a warning by adding a virtual destructor. */ #include "minorGems/common.h" #ifndef SERIALIZABLE_CLASS_INCLUDED #define SERIALIZABLE_CLASS_INCLUDED #include "InputStream.h" #include "OutputStream.h" /** * Interface for an object that can be serialized to and deserialized * from a stream. * * Note that the deserialize function is meant to be called from an already * constructed object (to set object parameters using data read from the * stream), and is not a method of obtaining an object. * * All multi-byte data members should be encoded in using a big endian format. * * @author Jason Rohrer */ class Serializable { public: /** * Writes this object out to a stream. * * @param inOutputStream the stream to write to. * * @return the number of bytes written successfully, * or -1 for a stream error. */ virtual int serialize( OutputStream *inOutputStream ) = 0; /** * Reads this object in from a stream. * * @param inInputStream the stream to read from. * * @return the number of bytes read successfully, * or -1 for a stream error. */ virtual int deserialize( InputStream *inInputStream ) = 0; virtual ~Serializable(); }; inline Serializable::~Serializable() { // does nothing // exists to ensure that subclass destructors are called } #endif primrose-6+dfsg1.orig/minorGems/io/file/0000755000175000017500000000000011201637530016740 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/file/unix/0000755000175000017500000000000011201637530017723 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/file/unix/DirectoryUnix.cpp0000644000175000017500000000141207753761036023255 0ustar pabspabs/* * Modification History * * 2003-January-23 Jason Rohrer * Created. * * 2003-November-10 Jason Rohrer * Added makeDirectory function. */ #include "minorGems/io/file/Directory.h" #include char Directory::removeDirectory( File *inFile ) { char *fileName = inFile->getFullFileName(); int result = rmdir( fileName ); delete [] fileName; if( result == 0 ) { return true; } else { return false; } } char Directory::makeDirectory( File *inFile ) { char *stringName = inFile->getFullFileName(); int result = mkdir( stringName, 0xFFFF ); delete [] stringName; if( 0 == result ) { return true; } else { return false; } } primrose-6+dfsg1.orig/minorGems/io/file/FileInputStream.h0000644000175000017500000000666410531416601022177 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-April-12 Jason Rohrer * Changed so that File is not destroyed when this stream is destroyed. * * 2001-April-29 Jason Rohrer * Fixed a bug in the use of fread * (num elements and element size swapped). * Fixed a memory leak in the error message handling. * * 2006-November-23 Jason Rohrer * Fixed a memory leak in error message handling. */ #include "minorGems/common.h" #ifndef FILE_INPUT_STREAM_CLASS_INCLUDED #define FILE_INPUT_STREAM_CLASS_INCLUDED #include "minorGems/io/InputStream.h" #include "File.h" #include /** * File implementation of an InputStream. * * @author Jason Rohrer */ class FileInputStream : public InputStream { public: /** * Constructs an input stream. * * @param inFile the file to open for reading. * If the file does not exist, all calls to read will fail. * inFile is NOT destroyed when this class is destroyed. */ FileInputStream( File *inFile ); /** * Destroys this stream and closes the file. */ ~FileInputStream(); /** * Gets the file attached to this stream. * * @return the file used by this stream. * Should not be modified or destroyed by caller until after * this class is destroyed. */ File *getFile(); // implementst InputStream interface virtual long read( unsigned char *inBuffer, long inNumBytes ); private: File *mFile; FILE *mUnderlyingFile; }; inline FileInputStream::FileInputStream( File *inFile ) : mFile( inFile ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); mUnderlyingFile = fopen( fileName, "rb" ); if( mUnderlyingFile == NULL ) { // file open failed. char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Opening file %s failed.", fileName ); setNewLastError( stringBuffer ); } delete [] fileName; } inline FileInputStream::~FileInputStream() { if( mUnderlyingFile != NULL ) { fclose( mUnderlyingFile ); } } inline File *FileInputStream::getFile() { return mFile; } inline long FileInputStream::read( unsigned char *inBuffer, long inNumBytes ) { if( mUnderlyingFile != NULL ) { long numRead = fread( inBuffer, 1, inNumBytes, mUnderlyingFile ); if( numRead < inNumBytes ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); if( feof( mUnderlyingFile ) ) { // we reached the end of the file. char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Reached end of file %s on read.", fileName ); setNewLastError( stringBuffer ); delete [] fileName; } else { // some other kind of error occured char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Reading from file %s failed.", fileName ); setNewLastError( stringBuffer ); delete [] fileName; if( numRead == 0 ) { // a complete read failure return -1; } } } return numRead; } else { // file was not opened properly int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "File %s was not opened properly before reading.", fileName ); delete [] fileName; setNewLastError( stringBuffer ); return -1; } } #endif primrose-6+dfsg1.orig/minorGems/io/file/FileOutputStream.h0000644000175000017500000000653410472613200022372 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-April-12 Jason Rohrer * Changed so that File is not destroyed when this stream is destroyed. * * 2001-April-29 Jason Rohrer * Fixed a bug in the use of fwrite * (num elements and element size swapped). * Fixed a memory leak in the error message handling. * * 2006-August-22 Jason Rohrer * Fixed include order bug. */ #include "minorGems/common.h" #include "File.h" #ifndef FILE_OUTPUT_STREAM_CLASS_INCLUDED #define FILE_OUTPUT_STREAM_CLASS_INCLUDED #include "minorGems/io/OutputStream.h" #include /** * File implementation of an OutputStream. * * @author Jason Rohrer */ class FileOutputStream : public OutputStream { public: /** * Constructs an output stream. * * @param inFile the file to open for writing. * If the file does not exist, it will be created. * inFile is NOT destroyed when this class is destroyed. * @param inAppend set to true to append to file. If * file does not exist, file is still created. Defaults * to false. */ FileOutputStream( File *inFile, char inAppend = false ); /** * Destroys this stream and closes the file. */ ~FileOutputStream(); /** * Gets the file attached to this stream. * * @return the file used by this stream. * Should not be modified or destroyed by caller until after * this class is destroyed. */ File *getFile(); // implementst OutputStream interface virtual long write( unsigned char *inBuffer, long inNumBytes ); private: File *mFile; FILE *mUnderlyingFile; }; inline FileOutputStream::FileOutputStream( File *inFile, char inAppend ) : mFile( inFile ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); if( inAppend ) { mUnderlyingFile = fopen( fileName, "ab" ); } else { mUnderlyingFile = fopen( fileName, "wb" ); } if( mUnderlyingFile == NULL ) { // file open failed. char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Opening file %s failed.", fileName ); setNewLastError( stringBuffer ); } delete [] fileName; } inline FileOutputStream::~FileOutputStream() { if( mUnderlyingFile != NULL ) { fclose( mUnderlyingFile ); } } inline File *FileOutputStream::getFile() { return mFile; } inline long FileOutputStream::write( unsigned char *inBuffer, long inNumBytes ) { if( mUnderlyingFile != NULL ) { long numWritten = fwrite( inBuffer, 1, inNumBytes, mUnderlyingFile ); if( numWritten < inNumBytes ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); // some other kind of error occured char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Writing to file %s failed.", fileName ); setNewLastError( stringBuffer ); delete [] fileName; if( numWritten == 0 ) { // a complete write failure return -1; } } return numWritten; } else { // file was not opened properly int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "File %s was not opened properly before writing.", fileName ); setNewLastError( stringBuffer ); return -1; } } #endif primrose-6+dfsg1.orig/minorGems/io/file/testPath.cpp0000644000175000017500000000112207522316361021243 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. */ #include "Path.h" #include int main() { char *pathString = "/test/this/thing"; printf( "using path string = %s\n", pathString ); printf( "Constructing path.\n" ); Path *path = new Path( pathString ); printf( "Extracting path string.\n" ); char *extractedPathString = path->getPathStringTerminated(); printf( "extracted path string = %s\n", extractedPathString ); delete [] extractedPathString; delete path; return 1; } primrose-6+dfsg1.orig/minorGems/io/file/File.h0000644000175000017500000005024110304641041017765 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-February-25 Jason Rohrer * Fixed file name bugs in length and existence functions. * * 2001-May-11 Jason Rohrer * Added a missing include. * * 2001-November-3 Jason Rohrer * Added a function for checking if a file is a directory. * Added a function for getting the child files of a directory. * Added a function for getting a pathless file name. * * 2001-November-13 Jason Rohrer * Made name length parameter optional in constructor. * Made return length parameter optional in name getting functions. * * 2001-November-17 Jason Rohrer * Added a functions for removing a file and for copying a file. * * 2002-March-11 Jason Rohrer * Added destruction comment to getFullFileName(). * * 2002-March-13 Jason Rohrer * Changed mName to be \0-terminated to fix interaction bugs with Path. * Fixed a missing delete. * Added a function for creating a directory. * * 2002-March-31 Jason Rohrer * Fixed some bad syntax. * * 2002-April-6 Jason Rohrer * Replaced use of strdup. * * 2002-April-8 Jason Rohrer * Fixed fopen bug. * * 2002-April-11 Jason Rohrer * Fixed a memory leak. * Fixed a casting error. * * 2002-June-28 Jason Rohrer * Added a function for copying a file class. * * 2002-August-3 Jason Rohrer * Added a function for getting the parent file. * * 2002-August-5 Jason Rohrer * Used an unused error variable. * * 2002-September-11 Jason Rohrer * Added return value to remove. * * 2003-January-27 Jason Rohrer * Added a function for reading file contents. * * 2003-February-3 Jason Rohrer * Added a function for writing a string to a file. * * 2003-March-13 Jason Rohrer * Added a function for getting a child file from a directory. * * 2003-June-2 Jason Rohrer * Fixed parent directory behavior when current file is root directory. * Fixed a bug in getting child files of root directory. * * 2003-November-6 Jason Rohrer * Added function for getting last modification time. * * 2003-November-10 Jason Rohrer * Changed to use platform-dependent makeDirectory function. * * 2004-January-4 Jason Rohrer * Added recursive child file functions. * * 2005-August-29 Jason Rohrer * Fixed an uninitialized variable warning. */ #include "minorGems/common.h" #ifndef FILE_CLASS_INCLUDED #define FILE_CLASS_INCLUDED #include #include #include #include #include "Path.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/stringUtils.h" /** * File interface. Provides access to information about a * file. * * @author Jason Rohrer */ class File { public: /** * Constructs a file. * * @param inPath the path for this file. * Is destroyed when this class is destroyed. * Pass in NULL to specify * no path (the current working directory). * @param inName the name of the file to open. * Must be destroyed by caller if not const. * Copied internally. * @param inNameLength length of the name in chars, * or -1 to use the c-string length of inName * (assuming that inName is \0-terminated). * Defaults to -1. */ File( Path *inPath, char *inName, int inNameLength = -1 ); ~File(); /** * Gets whether this file is a directory. * * @return true iff this file is a directory. */ char isDirectory(); /** * Makes a directory in the location of this file. * * Can only succeed if exists() is false. * * @return true iff directory creation succeeded. */ char makeDirectory(); /** * Gets the files contained in this file if it is a directory. * * @param outNumFiles pointer to where the number of * files will be returned. * * @return an array of files, or NULL if this * file is not a directory, is an empty directory, or doesn't exist. * Must be destroyed by caller if non-NULL. */ File **getChildFiles( int *outNumFiles ); /** * Gets the files contained in this file if it is a directory and * recursively in subdirectories of this file. * * @param inDepthLimit the maximum subdirectory depth to recurse into. * If inDepthLimit is 0, then only child files in this directory * will be returned. * @param outNumFiles pointer to where the number of * files will be returned. * * @return an array of files, or NULL if this * file is not a directory, is an empty directory (or a directory * containing empty subdirectories), or doesn't exist. * Must be destroyed by caller if non-NULL. */ File **getChildFilesRecursive( int inDepthLimit, int *outNumFiles ); /** * Gets a child of this directory. * * @param inChildFileName the name of the child file. * Must be destroyed by caller if non-const. * * @return the child file (even if it does not exist), or NULL if * this file is not a directory. * Must be destroyed by caller if non-NULL. */ File *getChildFile( char *inChildFileName ); /** * Gets the parent directory of this file. * * @return the parent directory of this file. * Must be destroyed by caller. */ File *getParentDirectory(); /** * Gets the length of this file. * * @return the length of this file in bytes. Returns * 0 if the file does not exist. */ long getLength(); /** * Gets whether a file exists. * * @return true if the file exists. */ char exists(); /** * Gets the last modification time of this file. * * @return the modification time in seconds based on the * system clock. Returns 0 if the file does not exist. */ unsigned long getModificationTime(); /** * Removes this file from the disk, if it exists. * * @return true iff the remove succeeded, false if the removal * fails or the file does not exist. */ char remove(); /** * Copies this file object (does not copy the file described by * this object). * * @return a deep copy of this file object. */ File *copy(); /** * Copies the contents of this file into another file. * * @param inDestination the file to copy this file into. * If it exists, it will be overwritten. * If it does not exist, it will be created. * Must be destroyed by caller. * @param inBlockSize the block size to use when copying. * Defaults to blocks of 5000 bytes. */ void copy( File *inDestination, long inBlockSize = 5000 ); /** * Gets the full-path file name sufficient * to access this file from the current working * directory. * * @param outLength pointer to where the name length, in * characters, will be returned. Set to NULL to ignore * the output length. Defaults to NULL. * * @return the full path file name for this file, * in platform-specific form. Must be destroyed by caller. * The returned string is '\0' terminated, but this * extra character is not included in the length. * Must be destroyed by caller. */ char *getFullFileName( int *outLength = NULL ); /** * Gets the pathless name of this file. * * @param outLength pointer to where the name length, in * characters, will be returned. Set to NULL to ignore * the output length. Defaults to NULL. * * @return the name of this file. Must be destroyed by caller. */ char *getFileName( int *outLength = NULL ); /** * Reads the contents of this file. * * @return a \0-terminated string containing the file contents, * or NULL if reading the file into memory failed. * Must be destroyed by caller. */ char *readFileContents(); /** * Writes a string to this file. * * @param inString the \0-terminated string to write. * Must be destroyed by caller if non-const. * * @return true if the file was written to successfully, or * false otherwise. */ char writeToFile( char *inString ); private: Path *mPath; char *mName; int mNameLength; /** * Gets the files contained in this file if it is a directory and * recursively in subdirectories of this file. * * @param inDepthLimit the maximum subdirectory depth to recurse into. * If inDepthLimit is 0, then only child files in this directory * will be returned. * @param inResultVector vector to add the discovered files to. * Must be destroyed by caller. */ void getChildFilesRecursive( int inDepthLimit, SimpleVector *inResultVector ); }; inline File::File( Path *inPath, char *inName, int inNameLength ) : mPath( inPath ), mNameLength( inNameLength ) { if( inNameLength == -1 ) { inNameLength = strlen( inName ); mNameLength = inNameLength; } // copy name internally mName = stringDuplicate( inName ); } inline File::~File() { delete [] mName; if( mPath != NULL ) { delete mPath; } } inline long File::getLength() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == 0 ) { return fileInfo.st_size; } else { // file does not exist return 0; } } inline char File::isDirectory() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == -1 ) { return false; } else { return S_ISDIR( fileInfo.st_mode ); } } inline File **File::getChildFiles( int *outNumFiles ) { int length; char *stringName = getFullFileName( &length ); DIR *directory = opendir( stringName ); if( directory != NULL ) { SimpleVector< File* > *fileVector = new SimpleVector< File* >(); struct dirent *entry = readdir( directory ); if( entry == NULL ) { delete fileVector; closedir( directory ); delete [] stringName; *outNumFiles = 0; return NULL; } while( entry != NULL ) { // skip parentdir and thisdir files, if they occur if( strcmp( entry->d_name, "." ) && strcmp( entry->d_name, ".." ) ) { Path *newPath; if( mPath != NULL ) { newPath = mPath->append( mName ); } else { if( Path::isRoot( mName ) ) { // use name as a string path newPath = new Path( mName ); } else { char **folderPathArray = new char*[1]; folderPathArray[0] = mName; // a non-absolute path to this directory's contents int numSteps = 1; char absolute = false; newPath = new Path( folderPathArray, numSteps, absolute ); delete [] folderPathArray; } } // safe to pass d_name in directly because it is copied // internally by the constructor fileVector->push_back( new File( newPath, entry->d_name, strlen( entry->d_name ) ) ); } entry = readdir( directory ); } // now we have a vector full of this directory's files int vectorSize = fileVector->size(); *outNumFiles = vectorSize; if( vectorSize == 0 ) { delete fileVector; closedir( directory ); delete [] stringName; return NULL; } else { File **returnFiles = new File *[vectorSize]; for( int i=0; igetElement( i ) ); } delete fileVector; closedir( directory ); delete [] stringName; return returnFiles; } } else { delete [] stringName; *outNumFiles = 0; return NULL; } } inline File **File::getChildFilesRecursive( int inDepthLimit, int *outNumFiles ) { // create a vector for results SimpleVector *resultVector = new SimpleVector(); // call the recursive function getChildFilesRecursive( inDepthLimit, resultVector ); // extract results from vector File **resultArray = NULL; int numResults = resultVector->size(); if( numResults > 0 ) { resultArray = resultVector->getElementArray(); } delete resultVector; *outNumFiles = numResults; return resultArray; } inline void File::getChildFilesRecursive( int inDepthLimit, SimpleVector *inResultVector ) { // get our child files int numChildren; File **childFiles = getChildFiles( &numChildren ); if( childFiles != NULL ) { // for each child, add it to vector and // recurse into it if it is a directory for( int i=0; ipush_back( child ); if( child->isDirectory() ) { // skip recursion if we have hit our depth limit if( inDepthLimit > 0 ) { // recurse into this subdirectory child->getChildFilesRecursive( inDepthLimit - 1, inResultVector ); } } } delete [] childFiles; } } inline File *File::getChildFile( char *inChildFileName ) { // make sure we are a directory if( !isDirectory() ) { return NULL; } // get a path to this directory Path *newPath; if( mPath != NULL ) { newPath = mPath->append( mName ); } else { char **folderPathArray = new char*[1]; folderPathArray[0] = mName; // a non-absolute path to this directory's contents int numSteps = 1; char absolute = false; newPath = new Path( folderPathArray, numSteps, absolute ); delete [] folderPathArray; } return new File( newPath, inChildFileName ); } inline File *File::getParentDirectory() { if( mPath != NULL ) { char *parentName; Path *parentPath; if( strcmp( mName, ".." ) == 0 ) { // already a parent dir reference // append one more parent dir reference with parentName below parentPath = mPath->append( ".." ); parentName = stringDuplicate( ".." ); } else { // not a parent dir reference, so we can truncate parentPath = mPath->truncate(); parentName = mPath->getLastStep(); } File *parentFile = new File( parentPath, parentName ); delete [] parentName; return parentFile; } else { if( Path::isRoot( mName ) ) { // we are already at the root return new File( NULL, mName ); } else { // append parent dir symbol to path char **parentPathSteps = new char*[1]; parentPathSteps[0] = mName; Path *parentPath = new Path( parentPathSteps, 1, false ); char *parentName = ".."; File *parentFile = new File( parentPath, parentName ); delete [] parentPathSteps; return parentFile; } } } inline char File::exists() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == 0 ) { return true; } else { // file does not exist return false; } } inline unsigned long File::getModificationTime() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == 0 ) { return fileInfo.st_mtime; } else { // file does not exist return 0; } } inline char File::remove() { char returnVal = false; if( exists() ) { char *stringName = getFullFileName(); int error = ::remove( stringName ); if( error == 0 ) { returnVal = true; } delete [] stringName; } return returnVal; } inline File *File::copy() { Path *pathCopy = NULL; if( mPath != NULL ) { pathCopy = mPath->copy(); } return new File( pathCopy, mName ); } inline void File::copy( File *inDestination, long inBlockSize ) { char *thisFileName = getFullFileName(); char *destinationFileName = inDestination->getFullFileName(); FILE *thisFile = fopen( thisFileName, "rb" ); FILE *destinationFile = fopen( destinationFileName, "wb" ); long length = getLength(); long bytesCopied = 0; char *buffer = new char[ inBlockSize ]; while( bytesCopied < length ) { long bytesToCopy = inBlockSize; // end of file case if( length - bytesCopied < bytesToCopy ) { bytesToCopy = length - bytesCopied; } fread( buffer, 1, bytesToCopy, thisFile ); fwrite( buffer, 1, bytesToCopy, destinationFile ); bytesCopied += bytesToCopy; } fclose( thisFile ); fclose( destinationFile ); delete [] buffer; delete [] thisFileName; delete [] destinationFileName; } inline char *File::getFileName( int *outLength ) { char *returnName = stringDuplicate( mName ); if( outLength != NULL ) { *outLength = mNameLength; } return returnName; } inline char *File::getFullFileName( int *outLength ) { int length = mNameLength; int pathLength = 0; char *path = NULL; if( mPath != NULL ) { path = mPath->getPathString( &pathLength ); length += pathLength; } // extra character for '\0' termination char *returnString = new char[ length + 1 ]; if( path != NULL ) { memcpy( returnString, path, pathLength ); memcpy( &( returnString[pathLength] ), mName, mNameLength ); delete [] path; } else { // no path, so copy the name directly in memcpy( returnString, mName, mNameLength ); } // terminate the string returnString[ length ] = '\0'; if( outLength != NULL ) { *outLength = length; } return returnString; } #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" inline char *File::readFileContents() { if( exists() ) { int length = getLength(); char *returnString = new char[ length + 1 ]; if( returnString != NULL ) { FileInputStream *input = new FileInputStream( this ); int numRead = input->read( (unsigned char *)returnString, length ); delete input; if( numRead == length ) { returnString[ length ] = '\0'; return returnString; } else { delete [] returnString; return NULL; } } else { // failed to allocate this much memory return NULL; } } else { return NULL; } } inline char File::writeToFile( char *inString ) { long stringLength = strlen( inString ); FileOutputStream *output = new FileOutputStream( this ); long numWritten = output->writeString( inString ); delete output; if( stringLength == numWritten ) { return true; } else { return false; } } #include "Directory.h" inline char File::makeDirectory() { if( exists() ) { return false; } else { return Directory::makeDirectory( this ); } } #endif primrose-6+dfsg1.orig/minorGems/io/file/UniversalFileIO.h0000644000175000017500000000572407205611501022120 0ustar pabspabs// Jason Rohrer // UniversalFileIO.h /** * * Object that handles universal file reading and writing * Writes files as big endian, even on little endian machines * * Assumes that longs and floats are 32-bits * * Created 1-12-99 * Mods: * Jason Rohrer 1-30-2000 Fixed fwrite functions to work on little endian machines */ #ifndef UNIVERSAL_FILE_IO_INCLUDED #define UNIVERSAL_FILE_IO_INCLUDED #include class UniversalFileIO { public: UniversalFileIO(); long freadLong( FILE *f ); float freadFloat( FILE *f ); void fwriteLong( FILE *f, long x ); void fwriteFloat( FILE *f, float x ); private: char machineBigEndian; char bytesInLong; char bytesInFloat; }; inline UniversalFileIO::UniversalFileIO() : machineBigEndian( true ), bytesInLong( 4 ), bytesInFloat( 4 ) { // test whether machine is big endian long test = 1; char testChopped = (*(char*)&test); if( testChopped == 1 ) machineBigEndian = false; } inline long UniversalFileIO::freadLong( FILE *f ) { if( machineBigEndian ) { long returnVal; fread((void *)&returnVal, sizeof(long), 1, f); return returnVal; } else { unsigned char *buffer = new unsigned char[bytesInLong]; fread((void *)buffer, sizeof(char), bytesInLong, f); // now put the bytes into a long long returnVal = (long)( buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3] ); delete [] buffer; return returnVal; } } inline float UniversalFileIO::freadFloat( FILE *f ) { if( machineBigEndian ) { float returnVal; fread( (void *)&returnVal, sizeof(float), 1, f ); return returnVal; } else { unsigned char *buffer = new unsigned char[bytesInFloat]; fread( (void *)buffer, sizeof(char), bytesInFloat, f ); // now put the bytes into a long long temp = (long)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]); delete [] buffer; return *((float *) &temp); // convert long into a float } } inline void UniversalFileIO::fwriteLong( FILE *f, long x ) { if( machineBigEndian ) { fwrite( (void *)&x, sizeof(long), 1, f ); } else { unsigned char *buffer = new unsigned char[bytesInLong]; buffer[0] = (unsigned char)(x >> 24); // put bytes from long into char buffer buffer[1] = (unsigned char)(x >> 16); buffer[2] = (unsigned char)(x >> 8); buffer[3] = (unsigned char)(x); fwrite( (void *)buffer, sizeof(char), bytesInLong, f ); } } inline void UniversalFileIO::fwriteFloat( FILE *f, float x ) { if( machineBigEndian ) { fwrite( (void *)&x, sizeof(float), 1, f ); } else { unsigned char *buffer = new unsigned char[bytesInFloat]; long temp = *((long*)&x); // convert float into long so that bit-wise ops can be performed buffer[0] = (unsigned char)(temp >> 24); // put bytes from float into char buffer buffer[1] = (unsigned char)(temp >> 16); buffer[2] = (unsigned char)(temp >> 8); buffer[3] = (unsigned char)(temp); fwrite( (void *)buffer, sizeof(char), bytesInFloat, f ); } } #endifprimrose-6+dfsg1.orig/minorGems/io/file/Path.h0000644000175000017500000003536210304641041020011 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2001-May-11 Jason Rohrer * Added a version of getPathString that * returns a '\0' terminated string. * * 2001-September-21 Jason Rohrer * Added a missing include. * * 2001-September-23 Jason Rohrer * Added a copy function. * Made some comments more explicit. * Changed the constructor to allow for const path step strings. * * 2001-November-3 Jason Rohrer * Added a function for appending a string to a path. * Changed the interface to the main constructor. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-April-11 Jason Rohrer * Fixed a variable scoping bug. * * 2002-July-2 Jason Rohrer * Fixed a major memory leak in copy(). * * 2002-August-1 Jason Rohrer * Added support for path truncation. * Added support for parsing platform-dependent path strings. * * 2003-May-29 Jason Rohrer * Fixed a bug when an extra delimeters are at the end of the path. * Fixed a bug when string path consists only of root. * * 2003-June-2 Jason Rohrer * Fixed a bug in absolute path detection. * Added platform-specific functions for root and absolute path detection. * Fixed a memory bug when string path contains root only. * Fixed a path step bug when path is root. * Fixed bugs in truncate and append when non-default root string is used. * * 2005-August-29 Jason Rohrer * Fixed an uninitialized variable warning. */ #include "minorGems/common.h" #ifndef PATH_CLASS_INCLUDED #define PATH_CLASS_INCLUDED #include #include "minorGems/util/stringUtils.h" #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Platform-independent file path interface. Contains * all of path except for file name. Thus, appending * a file name to the path will produce a complete file path. * * E.g., on Linux, file path: * temp/files/ * file name: * test.txt * full path: * temp/files/test.txt * * @author Jason Rohrer */ class Path { public: /** * Constructs a path. * * @param inPathSteps an array of c-strings representing * each step in the path, with no delimeters. * For example, { "temp", "files" } to represent * the linux path temp/files. * Must be destroyed by caller since copied internally. * @param inNumSteps the number of strings in the path. * @param inAbsolute set to true to make this an absolute * path. For example, in Linux, an absolute path * is one that starts with '/', as in /usr/include/. * The effects of inAbsolute vary by platform. * @param inRootString the root string for this path if it * is absolute, or NULL to specify a default root. * Defaults to NULL. * Must be destroyed by caller if non-NULL. */ Path( char **inPathSteps, int inNumSteps, char inAbsolute, char *inRootString = NULL ); /** * Constructs a path by parsing a platform-dependent path string. * * @param inPathSteps a \0-terminated string representing the path. * Must be destroyed by caller. */ Path( char *inPathString ); ~Path(); /** * Returns a complete, platform-dependent string path. * * @param outLength pointer to where the path length, in * characters, will be returned. * * @return a new char array containing the path. Note * that the string is not terminated by '\0'. Must * be destroyed by the caller. */ char *getPathString( int *outLength ); /** * Returns a complete, platform-dependent string path, terminated * bye '\0'. * * @return a new char array containing the path. Note * that the string IS terminated by '\0'. Must * be destroyed by the caller. */ char *getPathStringTerminated(); /** * Gets the platform-specific path delimeter. * * Note that this function is implemented separately for * each supported platform. * * @return the path delimeter. */ static char getDelimeter(); /** * Gets start characters for an absolute path. * * Note that this function is implemented separately for * each supported platform. * * @param outLength pointer to where the string length, in * characters, will be returned. * * @return the absolute path start string characters. For * example, on Linux, this would be the string "/". * Must be destroyed by the caller. */ static char *getAbsoluteRoot( int *outLength ); /** * Gets whether a path string is absolute. * * Note that this function is implemented separately for * each supported platform. * * @param inPathString the string to check. * Must be destroyed by caller if non-const. * * @return true if the string is absolute, or false otherwise. */ static char isAbsolute( char *inPathString ); /** * Extracts the root string from a path string. * * * @param inPathString the string to check. * Must be destroyed by caller if non-const. * * @return the root string, or NULL if inPathString is not * absolute. Must be destroyed by caller if non-NULL. */ static char *extractRoot( char *inPathString ); /** * Gets whether a path string is a root path. * * Note that this function is implemented separately for * each supported platform. For example, on Unix, only "/" * is the root path, while on Windows, both "c:\" and "d:\" might * be root paths. * * @param inPathString the string to check. * Must be destroyed by caller if non-const. * * @return true if the string is a root string, or false otherwise. */ static char isRoot( char *inPathString ); /** * Gets start string for an absolute path. * * @return the absolute path start string in \0-terminated form. * Must be destroyed by the caller. */ static char *getAbsoluteRootString(); /** * Copies this path. * * @return a new path that is a deep copy of this path. */ Path *copy(); /** * Constructs a new path by appending an additional * step onto this path. * * @param inStepString the step to add to this path. * Must be destroyed by caller if non-const. * * @return a new path with the extra step. * Must be destroyed by caller. */ Path *append( char *inStepString ); /** * Constructs a new path by removing the last step from this path. * * @return a new path, or NULL if there is only one step in this path. * Must be destroyed by caller. */ Path *truncate(); /** * Gets the last step in this path. * * @return the last step. Must be destroyed by caller. */ char *getLastStep(); private: char **mPathSteps; int mNumSteps; int *mStepLength; char mAbsolute; // the root string of this path, if it is absolute char *mRootString; }; inline Path::Path( char **inPathSteps, int inNumSteps, char inAbsolute, char *inRootString ) : mNumSteps( inNumSteps ), mAbsolute( inAbsolute ), mRootString( NULL ) { if( inRootString != NULL ) { mRootString = stringDuplicate( inRootString ); } // copy the path steps mPathSteps = new char*[ mNumSteps ]; mStepLength = new int[ mNumSteps ]; for( int i=0; i 1 ) { // don't count tail end delimeters delimCount++; } currentDelimPointer = strstr( &( currentDelimPointer[1] ), delimString ); } // no delimeter at end of path mNumSteps = delimCount + 1; mPathSteps = new char*[ mNumSteps ]; mStepLength = new int[ mNumSteps ]; // now extract the chars between delimeters as path steps currentDelimPointer = strstr( pathRootSkipped, delimString ); int stepIndex = 0; currentDelimPointer[0] = '\0'; mPathSteps[ stepIndex ] = stringDuplicate( pathRootSkipped ); mStepLength[ stepIndex ] = strlen( mPathSteps[ stepIndex ] ); stepIndex++; while( currentDelimPointer != NULL ) { char *nextDelimPointer = strstr( &( currentDelimPointer[1] ), delimString ); if( nextDelimPointer != NULL ) { nextDelimPointer[0] = '\0'; } mPathSteps[ stepIndex ] = stringDuplicate( &( currentDelimPointer[1] ) ); mStepLength[ stepIndex ] = strlen( mPathSteps[ stepIndex ] ); stepIndex++; currentDelimPointer = nextDelimPointer; } } else { // no delimeters if( strlen( pathRootSkipped ) > 0 ) { mNumSteps = 1; mPathSteps = new char*[1]; mPathSteps[0] = stringDuplicate( pathRootSkipped ); mStepLength = new int[1]; mStepLength[0] = strlen( mPathSteps[0] ); } else { // path with root only mNumSteps = 0; mPathSteps = new char*[0]; mStepLength = new int[0]; } } delete [] delimString; delete [] pathStringCopy; } inline Path::~Path() { // delete each step for( int i=0; i= 1 ) { return stringDuplicate( mPathSteps[ mNumSteps - 1 ] ); } else { if( mAbsolute ) { if( mRootString != NULL ) { return stringDuplicate( mRootString ); } else { return getAbsoluteRootString(); } } else { // no path steps and not absolute... return stringDuplicate( "" ); } } } inline char *Path::getAbsoluteRootString() { int rootLength; char *root = getAbsoluteRoot( &rootLength ); char *rootString = new char[ rootLength + 1 ]; strncpy( rootString, root, rootLength ); // strncopy won't add termination if length limit reached rootString[ rootLength ] = '\0'; delete [] root; return rootString; } #endif primrose-6+dfsg1.orig/minorGems/io/file/linux/0000755000175000017500000000000011201637530020077 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/file/linux/PathLinux.cpp0000644000175000017500000000220607666762723022546 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2001-August-1 Jason Rohrer * Added missing length return value. * * 2003-June-2 Jason Rohrer * Added support for new path checking functions. */ #include "minorGems/io/file/Path.h" #include "minorGems/util/stringUtils.h" /* * Linux-specific path implementation. May be compatible * with other posix-complient systems. */ char Path::getDelimeter() { return '/'; } char *Path::getAbsoluteRoot( int *outLength ) { char *returnString = new char[1]; returnString[0] = '/'; *outLength = 1; return returnString; } char Path::isAbsolute( char *inPathString ) { if( inPathString[0] == '/' ) { return true; } else { return false; } } char *Path::extractRoot( char *inPathString ) { if( isAbsolute( inPathString ) ){ return stringDuplicate( "/" ); } else { return NULL; } } char Path::isRoot( char *inPathString ) { if( strcmp( inPathString, "/" ) == 0 ) { return true; } else { return false; } } primrose-6+dfsg1.orig/minorGems/io/file/Directory.h0000644000175000017500000000262207753761021021071 0ustar pabspabs/* * Modification History * * 2003-January-23 Jason Rohrer * Created. * * * 2003-November-10 Jason Rohrer * Added makeDirectory function. */ #include "minorGems/common.h" #include "minorGems/io/file/File.h" #ifndef DIRECTORY_INCLUDED #define DIRECTORY_INCLUDED /** * Class of static directory functions. * * This class exists because most directory operations are * platform-dependent, and a large body of existing code * depends on a platform-independent File.h. * * @author Jason Rohrer. */ class Directory { public: /** * Removes a directory. * * The directory must be empty for this call to succeed. * * @param inFile the file representing the directory. * Must be destroyed by caller. * * @return true if the directory is removed successfully, or * false otherwise (for example, if the directory is not empy). */ static char removeDirectory( File *inFile ); /** * Makes a directory. * * @param inFile the file representing the directory. * Must be destroyed by caller. * * @return true if the directory is removed successfully, or * false otherwise (for example, if the directory is not empy). */ static char makeDirectory( File *inFile ); }; #endif primrose-6+dfsg1.orig/minorGems/io/file/win32/0000755000175000017500000000000011201637530017702 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/file/win32/DirectoryWin32.cpp0000644000175000017500000000140507753761036023215 0ustar pabspabs/* * Modification History * * 2003-January-23 Jason Rohrer * Created. * * 2003-November-10 Jason Rohrer * Added makeDirectory function. */ #include "minorGems/io/file/Directory.h" #include char Directory::removeDirectory( File *inFile ) { char *fileName = inFile->getFullFileName(); int result = _rmdir( fileName ); delete [] fileName; if( result == 0 ) { return true; } else { return false; } } char Directory::makeDirectory( File *inFile ) { char *stringName = inFile->getFullFileName(); int result = mkdir( stringName ); delete [] stringName; if( 0 == result ) { return true; } else { return false; } } primrose-6+dfsg1.orig/minorGems/io/file/win32/dirent.cpp0000644000175000017500000000654307552400302021702 0ustar pabspabs/* * Modification History * * 2002-April-7 Jason Rohrer * Added a mkdir wrapper for CodeWarrior. * * 2002-April-11 Jason Rohrer * Changed type of mode parameter to work with Visual C++. * Added missing include. * * 2002-July-22 Jason Rohrer * Commented out mkdir replacement function to work with new MSL. * * 2002-October-13 Jason Rohrer * Re-added mkdir wrapper function, since both CW4 and VC++ need it. */ /* Implementation of POSIX directory browsing functions and types for Win32. Kevlin Henney (mailto:kevlin@acm.org), March 1997. Copyright Kevlin Henney, 1997. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives, and that no charge may be made for the software and its documentation except to cover cost of distribution. This software is supplied "as is" without express or implied warranty. But that said, if there are any problems please get in touch. */ #include #include #include #include #include #include struct DIR { long handle; /* -1 for failed rewind */ struct _finddata_t info; struct dirent result; /* d_name null iff first time */ char *name; /* NTBS */ }; DIR *opendir(const char *name) { DIR *dir = 0; if(name && name[0]) { size_t base_length = strlen(name); const char *all = /* the root directory is a special case... */ strchr("/\\", name[base_length - 1]) ? "*" : "/*"; if((dir = (DIR *) malloc(sizeof *dir)) != 0 && (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0) { strcat(strcpy(dir->name, name), all); if((dir->handle = _findfirst(dir->name, &dir->info)) != -1) { dir->result.d_name = 0; } else /* rollback */ { free(dir->name); free(dir); dir = 0; } } else /* rollback */ { free(dir); dir = 0; errno = ENOMEM; } } else { errno = EINVAL; } return dir; } int closedir(DIR *dir) { int result = -1; if(dir) { if(dir->handle != -1) { result = _findclose(dir->handle); } free(dir->name); free(dir); } if(result == -1) /* map all errors to EBADF */ { errno = EBADF; } return result; } struct dirent *readdir(DIR *dir) { struct dirent *result = 0; if(dir && dir->handle != -1) { if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) { result = &dir->result; result->d_name = dir->info.name; } } else { errno = EBADF; } return result; } void rewinddir(DIR *dir) { if(dir && dir->handle != -1) { _findclose(dir->handle); dir->handle = _findfirst(dir->name, &dir->info); dir->result.d_name = 0; } else { errno = EBADF; } } int mkdir( const char *pathname, unsigned int mode ) { return mkdir( pathname ); } primrose-6+dfsg1.orig/minorGems/io/file/win32/PathWin32.cpp0000644000175000017500000000321507666767217022160 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Fixed delimeter constants. * * 2001-August-1 Jason Rohrer * Added missing length return value. * * 2003-June-2 Jason Rohrer * Added support for new path checking functions. */ #include "minorGems/io/file/Path.h" #include "minorGems/util/stringUtils.h" /* * Windows-specific path implementation. */ char Path::getDelimeter() { return '\\'; } char *Path::getAbsoluteRoot( int *outLength) { // C:\ is the only root we can generically return char *returnString = new char[3]; returnString[0] = 'C'; returnString[1] = ':'; returnString[2] = '\\'; *outLength = 3; return returnString; } char Path::isAbsolute( char *inPathString ) { // ignore first character, which will be drive letter if( inPathString[1] == ':' && inPathString[2] == '\\' ) { return true; } else { return false; } } char *Path::extractRoot( char *inPathString ) { if( isAbsolute( inPathString ) ){ // copy path, then trim to only three characters char *pathCopy = stringDuplicate( inPathString ); pathCopy[ 3 ] = '\0'; char *trimmedCopy = stringDuplicate( pathCopy ); delete [] pathCopy; return trimmedCopy; } else { return NULL; } } char Path::isRoot( char *inPathString ) { // must be of form "c:\" if( strlen( inPathString ) == 3 && inPathString[1] == ':' && inPathString[2] == '\\' ) { return true; } else { return false; } } primrose-6+dfsg1.orig/minorGems/io/file/win32/dirent.h0000644000175000017500000000327607554101513021353 0ustar pabspabs/* * Modification History * * 2002-April-7 Jason Rohrer * Added a mkdir wrapper for CodeWarrior. * * 2002-April-11 Jason Rohrer * Changed type of mode parameter to work with Visual C++. * Added missing macros. * * 2002-July-22 Jason Rohrer * Commented out mkdir replacement function to work with new MSL. * * 2002-October-13 Jason Rohrer * Re-added mkdir wrapper function, since both CW4 and VC++ need it. */ #include "minorGems/common.h" /* Declaration of POSIX directory browsing functions and types for Win32. Kevlin Henney (mailto:kevlin@acm.org), March 1997. Copyright Kevlin Henney, 1997. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives, and that no charge may be made for the software and its documentation except to cover cost of distribution. */ #ifndef DIRENT_INCLUDED #define DIRENT_INCLUDED typedef struct DIR DIR; struct dirent { char *d_name; }; DIR *opendir(const char *); int closedir(DIR *); struct dirent *readdir(DIR *); void rewinddir(DIR *); #include /** * The Metrowerks Standard Library seems * to have only a 1-parameter mkdir command in sys/stat.h. */ int mkdir( const char *pathname, unsigned int mode ); // make sure our needed macros are defined // S_IFMT and S_IFDIR seem to be defined everywhere #ifndef __S_ISTYPE #define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask)) #endif #ifndef S_ISDIR #define S_ISDIR(mode) __S_ISTYPE((mode), S_IFDIR) #endif #endif primrose-6+dfsg1.orig/minorGems/io/file/test/0000755000175000017500000000000011201637530017717 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/file/test/testPath.cpp0000644000175000017500000000112207776046015022231 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. */ #include "Path.h" #include int main() { char *pathString = "/test/this/thing"; printf( "using path string = %s\n", pathString ); printf( "Constructing path.\n" ); Path *path = new Path( pathString ); printf( "Extracting path string.\n" ); char *extractedPathString = path->getPathStringTerminated(); printf( "extracted path string = %s\n", extractedPathString ); delete [] extractedPathString; delete path; return 1; } primrose-6+dfsg1.orig/minorGems/io/file/test/testChildFiles.cpp0000644000175000017500000000223107776046015023345 0ustar pabspabs/* * Modification History * * 2004-January-4 Jason Rohrer * Created. */ /** * A test program for the various child file functions in File.h * * @author Jason Rohrer. */ #include "minorGems/io/file/File.h" int main( int inNumArgs, char **inArgs ) { char *fileName = "linux"; if( inNumArgs > 1 ) { fileName = inArgs[1]; } File *testFile = new File( NULL, fileName ); int numChildren; File **childFiles = testFile->getChildFiles( &numChildren ); printf( "child files:\n" ); for( int i=0; igetFullFileName(); printf( " %s\n", fullName ); delete [] fullName; delete childFiles[i]; } delete [] childFiles; childFiles = testFile->getChildFilesRecursive( 10, &numChildren ); printf( "recursive child files:\n" ); for( int i=0; igetFullFileName(); printf( " %s\n", fullName ); delete [] fullName; delete childFiles[i]; } delete [] childFiles; delete testFile; return 0; } primrose-6+dfsg1.orig/minorGems/io/serialPort/0000755000175000017500000000000011201637530020145 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/serialPort/testSerialPort.cpp0000644000175000017500000000101007624272636023645 0ustar pabspabs #include "SerialPort.h" #include int main() { printf( "Constructing serial port.\n" ); SerialPort *port = new SerialPort( 4800, SerialPort::PARITY_NONE, 8, 1 ); char *line = port->receiveLine(); // specific to GPS unit port->sendLine( "ASTRAL" ); while( line != NULL ) { printf( "received: %s\n", line ); delete [] line; line = port->receiveLine(); } printf( "Deleting serial port.\n" ); delete port; return 0; } primrose-6+dfsg1.orig/minorGems/io/serialPort/linux/0000755000175000017500000000000011201637530021304 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/serialPort/linux/SerialPortLinux.cpp0000644000175000017500000001477507643326107025144 0ustar pabspabs/* * Modification History * * 2003-February-17 Jason Rohrer * Created. * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ #include "minorGems/io/serialPort/SerialPort.h" #include "minorGems/util/stringUtils.h" // Much of the code in this implementation was copied // from the Serial Programming FAQ, by Gary Frefking // http://en.tldp.org/HOWTO/Serial-Programming-HOWTO/ #include #include #include #include #include #include // baudrate settings are defined in , which is // included by class LinuxSerialPortObject { public: int mFileHandle; struct termios mOldTermIO; }; SerialPort::SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ) { int fileHandle = open( "/dev/ttyS0", O_RDWR | O_NOCTTY ); if( fileHandle < 0 ) { mNativeObjectPointer = NULL; } else { LinuxSerialPortObject *serialPortObject = new LinuxSerialPortObject(); serialPortObject->mFileHandle = fileHandle; mNativeObjectPointer = (void *)serialPortObject; struct termios newTermIO; //save current serial port settings tcgetattr( fileHandle, &( serialPortObject->mOldTermIO ) ); // clear struct for new port settings bzero( &newTermIO, sizeof( newTermIO ) ); unsigned int baudRate; switch( inBaud ) { case 1200: baudRate = B1200; break; case 2400: baudRate = B2400; break; case 4800: baudRate = B4800; break; case 9600: baudRate = B9600; break; case 19200: baudRate = B19200; break; case 38400: baudRate = B38400; break; case 57600: baudRate = B57600; break; default: break; } unsigned int parity = 0; switch( inParity ) { case SerialPort::PARITY_NONE: // disable parity parity = 0; break; case SerialPort::PARITY_EVEN: // enable parity, defaults to even parity = PARENB; break; case SerialPort::PARITY_ODD: // enable parity, and set to odd parity = PARENB | PARODD; break; default: break; } unsigned int dataBits = 0; switch( inDataBits ) { case 5: dataBits = CS5; break; case 6: dataBits = CS6; break; case 7: dataBits = CS7; break; case 8: dataBits = CS8; break; default: break; } unsigned int stopBits = 0; switch( inStopBits ) { case 1: stopBits = 0; break; case 2: stopBits = CSTOPB; break; default: break; } newTermIO.c_cflag = baudRate | parity | dataBits | stopBits | CLOCAL | CREAD; /* IGNPAR : ignore bytes with parity errors ICRNL : map CR to NL (otherwise a CR input on the other computer will not terminate input) IGNCR : ignore CR, so only one line is read when other machine sends CRLF otherwise make device raw (no other input processing) */ newTermIO.c_iflag = IGNPAR | ICRNL | IGNCR; /* Raw output. */ newTermIO.c_oflag = 0; /* ICANON : enable canonical input disable all echo functionality, and don't send signals to calling program */ newTermIO.c_lflag = ICANON; /* now clean the modem line and activate the settings for the port */ tcflush( fileHandle, TCIFLUSH ); tcsetattr( fileHandle, TCSANOW, &newTermIO ); } } SerialPort::~SerialPort() { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; tcsetattr( fileHandle, TCSANOW, &( serialPortObject->mOldTermIO ) ); delete serialPortObject; } } int SerialPort::sendLine( char *inLine ) { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; int stringLength = strlen( inLine ); int numWritten = write( fileHandle, inLine, stringLength ); char *endLineString = "\n"; int numWrittenEndLine = write( fileHandle, endLineString, 1 ); if( numWritten == stringLength && numWrittenEndLine == 1 ) { return 1; } else { return -1; } } else { return -1; } } char *SerialPort::receiveLine() { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; char *buffer = new char[500]; int numRead = read( fileHandle, buffer, 500 ); char *returnString; if( numRead != -1 ) { buffer[ numRead ] = '\0'; returnString = stringDuplicate( buffer ); } else { returnString = NULL; } delete [] buffer; return returnString; } else { return NULL; } } void SerialPort::dumpReceiveBuffer() { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; // from man page: // flushes data received but not read tcflush( fileHandle, TCIFLUSH ); } } primrose-6+dfsg1.orig/minorGems/io/serialPort/SerialPortFromFile.cpp0000644000175000017500000000266207641141423024373 0ustar pabspabs/* * Modification History * * 2003-March-28 Jason Rohrer * Created. */ #include "minorGems/io/serialPort/SerialPort.h" #include "minorGems/util/stringUtils.h" #include SerialPort::SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ) { FILE *file = fopen( "gpscap.txt", "r" ); mNativeObjectPointer = file; } SerialPort::~SerialPort() { if( mNativeObjectPointer != NULL ) { FILE *file = (FILE *)mNativeObjectPointer; fclose( file ); } } int SerialPort::sendLine( char *inLine ) { return 1; } char *SerialPort::receiveLine() { if( mNativeObjectPointer != NULL ) { FILE *file = (FILE *)mNativeObjectPointer; char *buffer = new char[500]; // read up to first newline int index = 0; char lastCharRead = (char)getc( file ); while( lastCharRead != '\n' && index < 499 ) { buffer[index] = lastCharRead; lastCharRead = (char)getc( file ); index++; } char *returnString; if( index > 0 ) { buffer[ index ] = '\0'; returnString = stringDuplicate( buffer ); } else { returnString = NULL; } delete [] buffer; return returnString; } else { return NULL; } } primrose-6+dfsg1.orig/minorGems/io/serialPort/win32/0000755000175000017500000000000011201637530021107 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/serialPort/win32/COMPort.h0000644000175000017500000000672307643326110022557 0ustar pabspabs/* * Modification History * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ //============================================================================= // General component library for WIN32 // Copyright (C) 2000, UAB BBDSoft ( http://www.bbdsoft.com/ ) // // This material is provided "as is", with absolutely no warranty expressed // or implied. Any use is at your own risk. // // Permission to use or copy this software for any purpose is hereby granted // without fee, provided the above notices are retained on all copies. // Permission to modify the code and to distribute modified code is granted, // provided the above notices are retained, and a notice that the code was // modified is included with the above copyright notice. // // The author of this program may be contacted at developers@bbdsoft.com //============================================================================= #ifndef _COMPORT_ #define _COMPORT_ //----------------------------------------------------------------------------- class COMPort { public: enum Parity { None = 0 , Odd , Even , Mark , Space }; enum DataBits { db4 = 4 , db5 , db6 , db7 , db8 }; enum StopBits { sb1 = 0, sb15, sb2 }; enum BitRate { br110 = 110, br300 = 300, br600 = 600, br1200 = 1200, br2400 = 2400, br4800 = 4800, br9600 = 9600, br19200 = 19200, br38400 = 38400, br56000 = 56000, br57600 = 57600, br115200 = 115200, br256000 = 256000 }; // for function getModemSignals struct MSPack { unsigned char DTR : 1; unsigned char RTS : 1; unsigned char : 2; unsigned char CTS : 1; unsigned char DSR : 1; unsigned char RI : 1; unsigned char DCD : 1; }; COMPort ( const char * const portName ); ~COMPort (); // I/O operations char read (); COMPort & write (const char inChar); unsigned long read ( void * , const unsigned long count ); unsigned long write ( const void * , const unsigned long count ); // dumps unread characters in the receive buffer void dumpReceiveBuffer(); COMPort& setBitRate ( unsigned long Param ); unsigned long bitRate () const; COMPort& setParity ( Parity Param ); Parity parity () const; COMPort& setDataBits ( DataBits Param ); DataBits dataBits () const; COMPort& setStopBits ( StopBits Param ); StopBits stopBits () const; COMPort & setHandshaking ( bool inHandshaking = true ); COMPort& setLineCharacteristics ( char * Param ); unsigned long getMaximumBitRate () const; COMPort & setxONxOFF ( bool Param = true); bool isxONxOFF () const; MSPack getModemSignals () const; COMPort& setBlockingMode ( unsigned long inReadInterval = 0 , unsigned long inReadMultiplyer = 0 , unsigned long inReadConstant = 0 ); protected: private: // disable copy constructor and assignment operator COMPort (const COMPort &); COMPort& operator= (const COMPort &); void getState () const; COMPort& setState (); unsigned thePortHandle; char * theDCB; }; // End of COMPort class declaration #endif primrose-6+dfsg1.orig/minorGems/io/serialPort/win32/SerialPortWin32.cpp0000644000175000017500000001036507643326111024534 0ustar pabspabs/* * Modification History * * 2003-March-24 Jason Rohrer * Created. * * 2003-March-26 Jason Rohrer * Fixed a line parsing bug (lines end with newline, not CR). * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ #include "minorGems/io/serialPort/SerialPort.h" #include "minorGems/util/stringUtils.h" // For now, we are using BBDSoft's COM port code #include "COMPort.h" SerialPort::SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ) { COMPort *port = new COMPort( "COM1" ); port->setHandshaking( false ); unsigned long baudRate = COMPort::br2400; switch( inBaud ) { case 1200: baudRate = COMPort::br1200; break; case 2400: baudRate = COMPort::br2400; break; case 4800: baudRate = COMPort::br4800; break; case 9600: baudRate = COMPort::br9600; break; case 19200: baudRate = COMPort::br19200; break; case 38400: baudRate = COMPort::br38400; break; case 57600: baudRate = COMPort::br57600; break; default: break; } port->setBitRate( baudRate ); switch( inParity ) { case SerialPort::PARITY_NONE: port->setParity( COMPort::None ); break; case SerialPort::PARITY_EVEN: port->setParity( COMPort::Even ); break; case SerialPort::PARITY_ODD: port->setParity( COMPort::Odd ); break; default: port->setParity( COMPort::None ); break; } switch( inDataBits ) { case 5: port->setDataBits( COMPort::db5 ); break; case 6: port->setDataBits( COMPort::db6 ); break; case 7: port->setDataBits( COMPort::db7 ); break; case 8: port->setDataBits( COMPort::db8 ); break; default: port->setDataBits( COMPort::db8 ); break; } switch( inStopBits ) { case 1: port->setStopBits( COMPort::sb1 ); break; case 2: port->setStopBits( COMPort::sb2 ); break; default: port->setStopBits( COMPort::sb1 ); break; } mNativeObjectPointer = (void *)port; } SerialPort::~SerialPort() { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; delete port; } } int SerialPort::sendLine( char *inLine ) { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; int stringLength = strlen( inLine ); int numWritten = port->write( (void *)inLine, stringLength ); char *endLineString = "\n"; int numWrittenEndLine = port->write( (void *)endLineString, 1 ); if( numWritten == stringLength && numWrittenEndLine == 1 ) { return 1; } else { return -1; } } else { return -1; } } char *SerialPort::receiveLine() { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; char *buffer = new char[500]; // read up to first newline int index = 0; char lastCharRead = port->read(); while( lastCharRead != '\n' && index < 499 ) { buffer[index] = lastCharRead; lastCharRead = port->read(); index++; } char *returnString; if( index > 0 ) { buffer[ index ] = '\0'; returnString = stringDuplicate( buffer ); } else { returnString = NULL; } delete [] buffer; return returnString; } else { return NULL; } } void SerialPort::dumpReceiveBuffer() { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; port->dumpReceiveBuffer(); } } primrose-6+dfsg1.orig/minorGems/io/serialPort/win32/COMPort.cpp0000644000175000017500000002471107643367544023127 0ustar pabspabs/* * Modification History * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ //============================================================================= // General component library for WIN32 // Copyright (C) 2000, UAB BBDSoft ( http://www.bbdsoft.com/ ) // // This material is provided "as is", with absolutely no warranty expressed // or implied. Any use is at your own risk. // // Permission to use or copy this software for any purpose is hereby granted // without fee, provided the above notices are retained on all copies. // Permission to modify the code and to distribute modified code is granted, // provided the above notices are retained, and a notice that the code was // modified is included with the above copyright notice. // // The author of this program may be contacted at developers@bbdsoft.com //============================================================================= #ifndef _COMPORT_ #include "ComPort.h" #endif #ifndef _WINDOWS_ #define WIN32_LEAN_AND_MEAN #include #endif #ifndef _STDEXCEPT_ #include #endif using namespace std; //---------------------------------------------------------------------------- COMPort::COMPort ( const char * const portName ) : theDCB (NULL) { thePortHandle = (unsigned ) CreateFile ( portName , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_NO_BUFFERING , NULL ); if (thePortHandle == HFILE_ERROR) { throw runtime_error ("COMPort: failed to open."); } // endif theDCB = new char [sizeof(DCB)]; getState(); setBlockingMode(); setHandshaking(); } // end constructor //---------------------------------------------------------------------------- COMPort::~COMPort() { delete [] theDCB; // close serial port device if (CloseHandle ((HANDLE)thePortHandle) == FALSE ) { throw runtime_error ("COMPort: failed to close."); } // endif } // end destructor //---------------------------------------------------------------------------- void COMPort::getState () const { if (!GetCommState ( (HANDLE) thePortHandle , (LPDCB) theDCB ) ) { throw runtime_error ("COMPort: could not retrieve serial port state."); } // endif } // end COMPort::getState () const //---------------------------------------------------------------------------- COMPort& COMPort::setState () { if (!SetCommState ( (HANDLE) thePortHandle , (LPDCB) theDCB ) ) { throw runtime_error ("COMPort: could not modify serial port state."); } // endif return *this; } // end COMPort::setState () //----------------------------------------------------------------------------- COMPort& COMPort::setBitRate ( unsigned long Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.BaudRate = Param; return setState(); } // end COMPort::setBitRate (..) //----------------------------------------------------------------------------- unsigned long COMPort::bitRate() const { DCB & aDCB = *((LPDCB)theDCB); return aDCB.BaudRate; } // end COMPort::bitRate () const //----------------------------------------------------------------------------- COMPort& COMPort::setLineCharacteristics( char * inConfig ) { COMMTIMEOUTS aTimeout; if ( !BuildCommDCBAndTimeouts ( inConfig , (LPDCB)theDCB , &aTimeout ) ) { throw runtime_error ("COMPort: could not set line characteristics."); } // endif if ( ! SetCommTimeouts ( (HANDLE(thePortHandle)) , &aTimeout ) ) { throw runtime_error ("COMPort: could not set line characteristics."); } // endif return setState(); } //---------------------------------------------------------------------------- char COMPort::read () { char buffer; DWORD charsRead = 0; do { if (! ReadFile ( (HANDLE(thePortHandle)) , &buffer , sizeof(char) , &charsRead , NULL ) ) { throw runtime_error ("COMPort: read failed."); } // endif } while ( !charsRead ); return buffer; } // end COMPort::read() //---------------------------------------------------------------------------- void COMPort::dumpReceiveBuffer () { PurgeComm( (HANDLE(thePortHandle)) , PURGE_RXCLEAR ); } // end COMPort::dumpReceiveBuffer() //---------------------------------------------------------------------------- unsigned long COMPort::read ( void *inBuffer , const unsigned long inCharsReq ) { DWORD charsRead = 0; if ( !ReadFile ( (HANDLE(thePortHandle)) , inBuffer , inCharsReq , &charsRead , NULL ) ) { throw runtime_error ("COMPort: read failed."); } // endif return charsRead; } // end COMPort::read (..) //---------------------------------------------------------------------------- COMPort & COMPort::write ( const char inChar ) { char buffer = inChar; DWORD charsWritten = 0; if ( !WriteFile ( (HANDLE(thePortHandle)) , &buffer , sizeof(char) , &charsWritten , NULL ) ) { throw runtime_error ("COMPort: write failed."); } // endif return *this; } // end COMPort::write (..) //---------------------------------------------------------------------------- unsigned long COMPort::write ( const void *inBuffer , const unsigned long inBufSize ) { DWORD charsWritten = 0; if ( !WriteFile ( (HANDLE(thePortHandle)) , inBuffer , inBufSize , &charsWritten , NULL ) ) { throw runtime_error ("COMPort: write failed."); } // endif return charsWritten; } // end COMPort::write() //----------------------------------------------------------------------------- COMPort& COMPort::setxONxOFF ( bool Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.fOutX = Param ? 1 : 0; aDCB.fInX = Param ? 1 : 0; return setState(); } // end COMPort::setxONxOFF (..) //----------------------------------------------------------------------------- bool COMPort::isxONxOFF () const { DCB & aDCB = *((LPDCB)theDCB); return (aDCB.fOutX && aDCB.fInX); } // end COMPort::isxONxOFF () const //---------------------------------------------------------------------------- COMPort& COMPort::setBlockingMode ( unsigned long inReadInterval , unsigned long inReadMultiplyer , unsigned long inReadConstant ) { COMMTIMEOUTS commTimeout; if ( !GetCommTimeouts ( (HANDLE(thePortHandle)) , &commTimeout ) ) { throw runtime_error ("COMPort: failed to retrieve timeouts."); } // endif commTimeout.ReadIntervalTimeout = inReadInterval; if ( inReadInterval==MAXDWORD ) { commTimeout.ReadTotalTimeoutMultiplier = 0; commTimeout.ReadTotalTimeoutConstant = 0; } else { commTimeout.ReadTotalTimeoutMultiplier = inReadMultiplyer; commTimeout.ReadTotalTimeoutConstant = inReadConstant; } // endifelse if ( !SetCommTimeouts ( (HANDLE(thePortHandle)) , &commTimeout ) ) { throw runtime_error ("COMPort: failed to modify timeouts."); } // endif return *this; } // end COMPort::setBlockingMode (..) //----------------------------------------------------------------------------- COMPort & COMPort::setHandshaking ( bool inHandshaking ) { DCB & aDCB = *((LPDCB)theDCB); if (inHandshaking) { aDCB.fOutxCtsFlow = TRUE; aDCB.fOutxDsrFlow = FALSE; aDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; } else { aDCB.fOutxCtsFlow = FALSE; aDCB.fOutxDsrFlow = FALSE; aDCB.fRtsControl = RTS_CONTROL_ENABLE; } // endifelse return setState(); } // end COMPort::setHandshaking (..) //----------------------------------------------------------------------------- unsigned long COMPort::getMaximumBitRate() const { COMMPROP aProp; if ( !GetCommProperties ( (HANDLE)thePortHandle , &aProp ) ) { throw runtime_error ("COMPort: failed to retrieve port properties."); } // endif return aProp.dwMaxBaud; } // end COMPort::getMaximumBitRate () const //----------------------------------------------------------------------------- COMPort::MSPack COMPort::getModemSignals() const { MSPack aPack; // 1 bit - DTR, 2 - bit RTS (output signals) // 4 bit - CTS, 5 bit - DSR, 6 bit - RI, 7 bit - DCD (input signals) if ( !GetCommModemStatus ( (HANDLE)thePortHandle , (LPDWORD)&aPack ) ) { throw runtime_error ("COMPort: failed to retrieve modem signals."); } // endif return aPack; } // end COMPort::getModemSignals () const //----------------------------------------------------------------------------- COMPort& COMPort::setParity ( Parity Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.Parity = Param; return setState(); } // end COMPort::setParity (..) //----------------------------------------------------------------------------- COMPort& COMPort::setDataBits ( DataBits Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.ByteSize = Param; return setState(); } // end COMPort::setDataBits (..) //----------------------------------------------------------------------------- COMPort& COMPort::setStopBits ( StopBits Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.StopBits = Param; return setState(); } // end COMPort::setStopBits (..) //----------------------------------------------------------------------------- COMPort::Parity COMPort::parity () const { DCB & aDCB = *((LPDCB)theDCB); return (COMPort::Parity)aDCB.Parity; } // end COMPort::parity () const //----------------------------------------------------------------------------- COMPort::DataBits COMPort::dataBits () const { DCB & aDCB = *((LPDCB)theDCB); return (COMPort::DataBits)aDCB.ByteSize; } // end COMPort::dataBits () const //----------------------------------------------------------------------------- COMPort::StopBits COMPort::stopBits () const { DCB & aDCB = *((LPDCB)theDCB); return (COMPort::StopBits)aDCB.StopBits; } // end COMPort::stopBits () cosnt primrose-6+dfsg1.orig/minorGems/io/serialPort/testSerialPortCompile0000755000175000017500000000011507624270527024402 0ustar pabspabsg++ -o testSerialPort -I../../.. linux/SerialPortLinux.cpp testSerialPort.cppprimrose-6+dfsg1.orig/minorGems/io/serialPort/SerialPort.h0000644000175000017500000000430607643326042022415 0ustar pabspabs/* * Modification History * * 2003-February-17 Jason Rohrer * Created. * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ #ifndef SERIAL_PORT_INCLUDED #define SERIAL_PORT_INCLUDED /** * Serial port. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class SerialPort { public: static const int PARITY_NONE = 0; static const int PARITY_EVEN = 1; static const int PARITY_ODD = 2; /** * Constructs a serial port. * * @param inBaud the baud rate. * @param inParity the parity, one of SerialPort:: PARITY_NONE, * PARITY_EVEN, or PARITY_ODD. * @param inDataBits the number of data bits, 5, 6, 7, or 8. * @param inStopBits the number of stop bits, 1 or 2. */ SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ); ~SerialPort(); /** * Sends a line of text through this serial port. * * @param inLine the \0-terminated line of text to send. * Should not contain newline characters. * Must be destroyed by caller if non-const. * * @return 1 if the line was sent successfully, * or -1 for a port error. */ int sendLine( char *inLine ); /** * Receives a line of text from this serial port. * * @return the read line as a \0-terminated string with end of * line characters included, or NULL for a port error. * Must be destroyed by caller if non-NULL. */ char *receiveLine(); /** * Discards all characters in the receive buffer, including * unread characters. * * Can be used to recover from buffer overflow problems. */ void dumpReceiveBuffer(); private: /** * Used for platform-specific implementations. */ void *mNativeObjectPointer; }; #endif primrose-6+dfsg1.orig/minorGems/io/InputStream.h0000644000175000017500000000735010047466201020454 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-9 Jason Rohrer * Changed the "number of bytes read" parameter and return value * to longs. * * 2001-February-3 Jason Rohrer * Added a readDouble function to fix platform-specific double problems. * Also added a readLong function for completeness. Implemented * these functions, making use of the new TypeIO interface. * * 2001-February-12 Jason Rohrer * Changed to subclass Stream. * * 2002-March-9 Jason Rohrer * Added a readByte() function. * * 2002-March-31 Jason Rohrer * Made destructor virtual so it works with subclasses. * * 2004-May-9 Jason Rohrer * Added support for shorts. */ #include "minorGems/common.h" #ifndef INPUT_STREAM_CLASS_INCLUDED #define INPUT_STREAM_CLASS_INCLUDED #include "Stream.h" #include "TypeIO.h" /** * Interface for a byte input stream. * * @author Jason Rohrer */ class InputStream : public Stream { public: InputStream(); virtual ~InputStream(); /** * Reads bytes from this stream. * * @param inBuffer the buffer where read bytes will be put. * Must be pre-allocated memory space. * @param inNumBytes the number of bytes to read from the stream. * * @return the number of bytes read successfully, * or -1 for a stream error. */ virtual long read( unsigned char *inBuffer, long inNumBytes ) = 0; /** * Reads a byte from this stream. * * @param outByte pointer to where the byte should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readByte( unsigned char *outByte ); /** * Reads a double from the stream in a platform-independent way. * * @param outDouble pointer to where the double should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readDouble( double *outDouble ); /** * Reads a long from the stream in a platform-independent way. * * @param outLong pointer to where the long should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readLong( long *outLong ); /** * Reads a short from the stream in a platform-independent way. * * @param outShort pointer to where the short should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readShort( short *outShort ); private: unsigned char *mDoubleBuffer; unsigned char *mLongBuffer; unsigned char *mShortBuffer; unsigned char *mByteBuffer; }; inline InputStream::InputStream() : mDoubleBuffer( new unsigned char[8] ), mLongBuffer( new unsigned char[4] ), mShortBuffer( new unsigned char[2] ), mByteBuffer( new unsigned char[1] ) { } inline InputStream::~InputStream() { delete [] mDoubleBuffer; delete [] mShortBuffer; delete [] mLongBuffer; delete [] mByteBuffer; } inline long InputStream::readByte( unsigned char *outByte ) { int numBytes = read( mByteBuffer, 1 ); *outByte = mByteBuffer[0]; return numBytes; } inline long InputStream::readDouble( double *outDouble ) { int numBytes = read( mDoubleBuffer, 8 ); *outDouble = TypeIO::bytesToDouble( mDoubleBuffer ); return numBytes; } inline long InputStream::readLong( long *outLong ) { int numBytes = read( mLongBuffer, 4 ); *outLong = TypeIO::bytesToLong( mLongBuffer ); return numBytes; } inline long InputStream::readShort( short *outShort ) { int numBytes = read( mShortBuffer, 4 ); *outShort = TypeIO::bytesToShort( mShortBuffer ); return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/io/TypeIO.h0000644000175000017500000000650610047466202017355 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * Fixed parameter names to match convention. * * 2003-January-11 Jason Rohrer * Added missing casts. * * 2004-May-9 Jason Rohrer * Added support for shorts. */ #include "minorGems/common.h" #ifndef TYPE_IO_INCLUDED #define TYPE_IO_INCLUDED /** * Interfaces for platform-independent type input and output. * * The specification for the input/output format for types is as follows: * * Types should be output in the order and format that a big-endian Linux * outputs them by default. * * Note that minorGems/numtest.cpp can be used to test how doubles are * stored on a specific platform. * * @author Jason Rohrer */ class TypeIO { public: /** * Converts an 32-bit integer to a byte array in a * platform-independent fashion. * * @param inInt the integer to convert to a byte array. * @param outBytes preallocated array where bytes will be returned. */ static void longToBytes( long inInt, unsigned char *outBytes ); /** * Converts a 4-byte array to a 32-bit integer * platform-independent fashion. * * @param inBytes array of bytes to convert. * * @return the integer represented by the bytes. */ static long bytesToLong( unsigned char *inBytes ); /** * Converts an 16-bit integer to a byte array in a * platform-independent fashion. * * @param inInt the integer to convert to a byte array. * @param outBytes preallocated array where bytes will be returned. */ static void shortToBytes( short inInt, unsigned char *outBytes ); /** * Converts a 2-byte array to a 16-bit integer * platform-independent fashion. * * @param inBytes array of bytes to convert. * * @return the integer represented by the bytes. */ static short bytesToShort( unsigned char *inBytes ); /** * Converts an 64-bit float to a byte array in a * platform-independent fashion. * * @param inDouble the double to convert to a byte array. * @param outBytes preallocated array where bytes will be returned. */ static void doubleToBytes( double inDouble, unsigned char *outBytes ); /** * Converts a 8-byte array to a 64-bit float * platform-independent fashion. * * @param inBytes array of bytes to convert. * * @return the double represented by the bytes. */ static double bytesToDouble( unsigned char *inBytes ); }; // for now, these long IO functions can be implemented in the same way // on every platform. inline void TypeIO::longToBytes( long inInt, unsigned char *outBytes ) { // use a big-endian conversion outBytes[0] = (unsigned char)( inInt >> 24 & 0xFF ); outBytes[1] = (unsigned char)( inInt >> 16 & 0xFF ); outBytes[2] = (unsigned char)( inInt >> 8 & 0xFF ); outBytes[3] = (unsigned char)( inInt & 0xFF ); } inline long TypeIO::bytesToLong( unsigned char *inBytes ) { return (long)( inBytes[0] << 24 | inBytes[1] << 16 | inBytes[2] << 8 | inBytes[3] ); } inline void TypeIO::shortToBytes( short inInt, unsigned char *outBytes ) { // use a big-endian conversion outBytes[0] = (unsigned char)( inInt >> 8 & 0xFF ); outBytes[1] = (unsigned char)( inInt & 0xFF ); } inline short TypeIO::bytesToShort( unsigned char *inBytes ) { return (short)( inBytes[0] << 8 | inBytes[1] ); } #endif primrose-6+dfsg1.orig/minorGems/io/pipedStreamTest.cpp0000644000175000017500000000305607244373534021663 0ustar pabspabs/* * Modification History * * 2001-February-19 Jason Rohrer * Created. */ #include #include "PipedStream.h" #include "minorGems/util/random/StdRandomSource.h" // test function for piped streams int main() { PipedStream *stream = new PipedStream; InputStream *inStream = stream; OutputStream *outStream = stream; StdRandomSource *randSource = new StdRandomSource(); unsigned char *bufferA = new unsigned char[10]; unsigned char *bufferB = new unsigned char[15]; int i; printf( "bufferA = \n" ); for( i=0; i<10; i++ ) { bufferA[i] = (unsigned char)( randSource->getRandomBoundedInt(0, 255) ); printf( "%d\n", bufferA[i] ); } printf( "bufferB = \n" ); for( i=0; i<15; i++ ) { bufferB[i] = (unsigned char)( randSource->getRandomBoundedInt(0, 255) ); printf( "%d\n", bufferB[i] ); } unsigned char *bufferC = new unsigned char[ 10 + 15]; outStream->write( bufferA, 10 ); outStream->write( bufferB, 15 ); inStream->read( bufferC, 10 + 10 ); char *error = inStream->getLastError(); if( error != NULL ) { printf( "Stream error %s\n", error ); delete [] error; } printf( "bufferc = \n" ); for( i=0; i<10 + 15; i++ ) { printf( "%d\n", bufferC[i] ); } inStream->read( bufferC, 10 ); error = inStream->getLastError(); if( error != NULL ) { printf( "Stream error %s\n", error ); delete [] error; } printf( "bufferc = \n" ); for( i=0; i<10 + 15; i++ ) { printf( "%d\n", bufferC[i] ); } delete [] bufferA; delete [] bufferB; delete [] bufferC; delete randSource; delete stream; } primrose-6+dfsg1.orig/minorGems/io/linux/0000755000175000017500000000000011201637530017160 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/linux/TypeIOLinux.cpp0000644000175000017500000000524507473770515022104 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * Fixed a bug in the big-endian code. * Fixed parameter names to match convention. * * 2001-February-26 Jason Rohrer * Fixed a bug in the little-endian implementation. * * 2001-August-28 Jason Rohrer * Changed to be FreeBSD compatible. * * 2002-March-13 Jason Rohrer * Started to change to work with solaris. * Finished changing to work with solaris. * * 2002-April-11 Jason Rohrer * Added a default BSD case to work with OSX. * * 2002-May-25 Jason Rohrer * Changed to use minorGems endian.h */ #include "minorGems/io/TypeIO.h" #include "minorGems/system/endian.h" /* * Linux-specific type input and output. * Note that all types are output in the order that * a big-endian linux machine outputs them with no conversion. */ #if __BYTE_ORDER == __LITTLE_ENDIAN void TypeIO::doubleToBytes( double inDouble, unsigned char *outBytes ) { unsigned char *doubleBuffer = (unsigned char*)( &inDouble ); // output second word first outBytes[0] = doubleBuffer[7]; outBytes[1] = doubleBuffer[6]; outBytes[2] = doubleBuffer[5]; outBytes[3] = doubleBuffer[4]; outBytes[4] = doubleBuffer[3]; outBytes[5] = doubleBuffer[2]; outBytes[6] = doubleBuffer[1]; outBytes[7] = doubleBuffer[0]; } double TypeIO::bytesToDouble( unsigned char *inBytes ) { double returnValue; unsigned char *doubleBuffer = (unsigned char*)( &returnValue ); // put first word at the end of this double doubleBuffer[7] = inBytes[0]; doubleBuffer[6] = inBytes[1]; doubleBuffer[5] = inBytes[2]; doubleBuffer[4] = inBytes[3]; doubleBuffer[3] = inBytes[4]; doubleBuffer[2] = inBytes[5]; doubleBuffer[1] = inBytes[6]; doubleBuffer[0] = inBytes[7]; return returnValue; } #endif #if __BYTE_ORDER == __BIG_ENDIAN void TypeIO::doubleToBytes( double inDouble, unsigned char *outBytes ) { unsigned char *doubleBuffer = (unsigned char*)( &inDouble ); // output in stored order outBytes[0] = doubleBuffer[0]; outBytes[1] = doubleBuffer[1]; outBytes[2] = doubleBuffer[2]; outBytes[3] = doubleBuffer[3]; outBytes[4] = doubleBuffer[4]; outBytes[5] = doubleBuffer[5]; outBytes[6] = doubleBuffer[6]; outBytes[7] = doubleBuffer[7]; } double TypeIO::bytesToDouble( unsigned char *inBytes ) { double returnValue; unsigned char *doubleBuffer = (unsigned char*)( &returnValue ); // store in input order doubleBuffer[0] = inBytes[0]; doubleBuffer[1] = inBytes[1]; doubleBuffer[2] = inBytes[2]; doubleBuffer[3] = inBytes[3]; doubleBuffer[4] = inBytes[4]; doubleBuffer[5] = inBytes[5]; doubleBuffer[6] = inBytes[6]; doubleBuffer[7] = inBytes[7]; return returnValue; } #endif primrose-6+dfsg1.orig/minorGems/io/OutputStream.h0000644000175000017500000000702310047466201020652 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-9 Jason Rohrer * Changed the "number of bytes written" parameter and return value * to longs. * * 2001-February-3 Jason Rohrer * Added a writeDouble function to fix platform-specific double problems. * Also added a writeLong function for completeness. Implemented * these functions, making use of the new TypeIO interface. * * 2001-February-12 Jason Rohrer * Changed to subclass Stream. * * 2002-February-25 Jason Rohrer * Added a function for writing a string. * * 2002-March-31 Jason Rohrer * Made destructor virtual so it works with subclasses. * * 2004-May-9 Jason Rohrer * Added support for shorts. */ #include "minorGems/common.h" #ifndef OUTPUT_STREAM_CLASS_INCLUDED #define OUTPUT_STREAM_CLASS_INCLUDED #include "Stream.h" #include "TypeIO.h" #include /** * Interface for a byte output stream. * * @author Jason Rohrer */ class OutputStream : public Stream { public: OutputStream(); virtual ~OutputStream(); /** * Writes bytes to this stream. * * @param inBuffer the buffer of bytes to send. * @param inNumBytes the number of bytes to send. * * @return the number of bytes written successfully, * or -1 for a stream error. */ virtual long write( unsigned char *inBuffer, long inNumBytes ) = 0; /** * Writes a string to this stream. * * @param inString a \0-terminated string. * Must be destroyed by caller. * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeString( char *inString ); /** * Writes a double to the stream in a platform-independent way. * * @param inDouble the double to write * * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeDouble( double inDouble ); /** * Writes a long to the stream in a platform-independent way. * * @param inLong the long to write * * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeLong( long inLong ); /** * Writes a short to the stream in a platform-independent way. * * @param inShort the long to write * * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeShort( short inShort ); private: unsigned char *mDoubleBuffer; unsigned char *mLongBuffer; unsigned char *mShortBuffer; }; inline OutputStream::OutputStream() : mDoubleBuffer( new unsigned char[8] ), mLongBuffer( new unsigned char[4] ), mShortBuffer( new unsigned char[2] ) { } inline OutputStream::~OutputStream() { delete [] mDoubleBuffer; delete [] mLongBuffer; delete [] mShortBuffer; } inline long OutputStream::writeString( char *inString ) { int numBytes = write( (unsigned char *)inString, strlen( inString ) ); return numBytes; } inline long OutputStream::writeDouble( double inDouble ) { TypeIO::doubleToBytes( inDouble, mDoubleBuffer ); int numBytes = write( mDoubleBuffer, 8 ); return numBytes; } inline long OutputStream::writeLong( long inLong ) { TypeIO::longToBytes( inLong, mLongBuffer ); int numBytes = write( mLongBuffer, 4 ); return numBytes; } inline long OutputStream::writeShort( short inShort ) { TypeIO::shortToBytes( inShort, mShortBuffer ); int numBytes = write( mShortBuffer, 2 ); return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/io/PipedStream.h0000644000175000017500000000765107554101513020423 0ustar pabspabs/* * Modification History * * 2001-February-19 Jason Rohrer * Created. * * 2001-February-20 Jason Rohrer * Added a missing return value. */ #include "minorGems/common.h" #ifndef PIPED_STREAM_CLASS_INCLUDED #define PIPED_STREAM_CLASS_INCLUDED #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" #include "minorGems/util/SimpleVector.h" #include /** * An input/output stream that can server as a pipe between * two components that read from and write to streams. * * Buffered internally to prevent blocking, so is compatible * with non-threaded components. Note, however, that * ever buffer written to the stream is copied internally, * so max memory usage is doubled. * * IS NOT THREAD-SAFE! * * @author Jason Rohrer */ class PipedStream : public InputStream, public OutputStream { public: /** * Constructs a PipedStream. */ PipedStream(); /** * Destroys any pending unread buffers. */ ~PipedStream(); // implements the InputStream interface long read( unsigned char *inBuffer, long inNumBytes ); // implements the OutputStream interface long write( unsigned char *inBuffer, long inNumBytes ); protected: SimpleVector *mBuffers; SimpleVector *mBufferSizes; long mCurrentBufferIndex; }; inline PipedStream::PipedStream() : mBuffers( new SimpleVector() ), mBufferSizes( new SimpleVector() ), mCurrentBufferIndex( 0 ) { } inline PipedStream::~PipedStream() { int numRemaining = mBuffers->size(); for( int i=0; igetElement( i ) ); delete [] buffer; } delete mBuffers; delete mBufferSizes; } inline long PipedStream::read( unsigned char *inBuffer, long inNumBytes ) { if( mBuffers->size() == 0 ) { // none read, since no buffers available InputStream:: setNewLastErrorConst( "No data available on piped stream read." ); return 0; } else { unsigned char *currentBuffer = *( mBuffers->getElement( 0 ) ); long currentBufferSize = *( mBufferSizes->getElement( 0 ) ); long outputIndex = 0; while( outputIndex < inNumBytes ) { long bytesRemaining = inNumBytes - outputIndex; long bytesRemainingInCurrent = currentBufferSize - mCurrentBufferIndex; // if current buffer isn't big enough to fill output if( bytesRemaining >= bytesRemainingInCurrent ) { // copy all of current buffer into inBuffer memcpy( &( inBuffer[outputIndex] ), &( currentBuffer[mCurrentBufferIndex] ), bytesRemainingInCurrent ); outputIndex += bytesRemainingInCurrent; // delete the current buffer mBuffers->deleteElement( 0 ); mBufferSizes->deleteElement( 0 ); delete [] currentBuffer; mCurrentBufferIndex = 0; if( outputIndex != inNumBytes && mBuffers->size() == 0 ) { // partial read, since no more buffers available InputStream::setNewLastErrorConst( "Partial data available on piped stream read." ); return outputIndex; } if( mBuffers->size() != 0 ) { // get the new current buffer currentBuffer = *( mBuffers->getElement( 0 ) ); currentBufferSize = *( mBufferSizes->getElement( 0 ) ); } } else { // current buffer is bigger memcpy( &( inBuffer[outputIndex] ), &( currentBuffer[mCurrentBufferIndex] ), bytesRemaining ); mCurrentBufferIndex += bytesRemaining; outputIndex += bytesRemaining; } } // end while // if we made it out of the while loop, we read all bytes return inNumBytes; } // end else } inline long PipedStream::write( unsigned char *inBuffer, long inNumBytes ) { // add a copy of the buffer to the vector of buffers unsigned char *copy = new unsigned char[ inNumBytes ]; memcpy( copy, inBuffer, inNumBytes ); mBuffers->push_back( copy ); mBufferSizes->push_back( inNumBytes ); return inNumBytes; } #endif primrose-6+dfsg1.orig/minorGems/io/Stream.h0000644000175000017500000000513707554101513017436 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-March-31 Jason Rohrer * Made destructor virtual so it works with subclasses. * Fixed several bugs in deletion of mLastError. */ #include "minorGems/common.h" #ifndef STREAM_CLASS_INCLUDED #define STREAM_CLASS_INCLUDED #include #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Base class for all streams. * * @author Jason Rohrer */ class Stream { public: /** * Constructs a stream. */ Stream(); virtual ~Stream(); /** * Gets the last error associated with this stream. * Calling this function clears the error until * another error occurs. * * @return the last stream error in human-readable form. * Must be destroyed by caller. Returns NULL if * there is no error. Note that this string is '\0' terminated. */ char *getLastError(); protected: /** * Called by subclasses to specify a new last error. Useful * when error doesn't contain information specifiable by * a constant string. * * @param inString human-readable string representing the error. * Note that this string must be '\0' terminated. * Will be destroyed by this class. */ void setNewLastError( char *inString ); /** * Called by subclasses to specify a new last error. Useful * when the error can be described by a constant string * * @param inString human-readable constant string representing * the error. * Note that this string must be '\0' terminated. */ void setNewLastErrorConst( const char *inString ); private: // set to NULL when there is no error char *mLastError; }; inline Stream::Stream() : mLastError( NULL ) { } inline Stream::~Stream() { if( mLastError != NULL ) { delete [] mLastError; } } inline char *Stream::getLastError() { char *returnString = mLastError; mLastError = NULL; return returnString; } inline void Stream::setNewLastError( char *inString ) { if( mLastError != NULL ) { delete [] mLastError; } mLastError = inString; } inline void Stream::setNewLastErrorConst( const char *inString ) { int length = 0; char lastChar = 'a'; while( lastChar != '\0' ) { lastChar = inString[length]; length++; } // add one more to length to accommodate '\0' terminination length++; if( mLastError != NULL ) { delete [] mLastError; } mLastError = new char[ length ]; memcpy( mLastError, inString, length ); } #endif primrose-6+dfsg1.orig/minorGems/io/win32/0000755000175000017500000000000011201637530016763 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/io/win32/TypeIOWin32.cpp0000644000175000017500000000247107237354514021503 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * Fixed parameter names to match convention. * * 2001-February-4 Jason Rohrer * Fixed a byte-order bug. */ #include "minorGems/io/TypeIO.h" /* * Win32-specific type input and output. * Note that all types are output in the order that * a big-endian linux machine outputs them with no conversion. */ // windows machines are all little-endian void TypeIO::doubleToBytes( double inDouble, unsigned char *outBytes ) { unsigned char *doubleBuffer = (unsigned char*)( &inDouble ); // output second word first outBytes[0] = doubleBuffer[7]; outBytes[1] = doubleBuffer[6]; outBytes[2] = doubleBuffer[5]; outBytes[3] = doubleBuffer[4]; outBytes[4] = doubleBuffer[3]; outBytes[5] = doubleBuffer[2]; outBytes[6] = doubleBuffer[1]; outBytes[7] = doubleBuffer[0]; } double TypeIO::bytesToDouble( unsigned char *inBytes ) { double returnValue; unsigned char *doubleBuffer = (unsigned char*)( &returnValue ); // put first word at the end of this double doubleBuffer[7] = inBytes[0]; doubleBuffer[6] = inBytes[1]; doubleBuffer[5] = inBytes[2]; doubleBuffer[4] = inBytes[3]; doubleBuffer[3] = inBytes[4]; doubleBuffer[2] = inBytes[5]; doubleBuffer[1] = inBytes[6]; doubleBuffer[0] = inBytes[7]; return returnValue; } primrose-6+dfsg1.orig/minorGems/formats/0000755000175000017500000000000011201637525017071 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/formats/xml/0000755000175000017500000000000011201637525017671 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/formats/xml/XMLUtils.cpp0000644000175000017500000000470207540235637022072 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #include "XMLUtils.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include char *XMLUtils::escapeDisallowedCharacters( char *inString ) { SimpleVector *returnStringVector = new SimpleVector(); int stringLength = strlen( inString ); int i; for( i=0; ipush_back( '&' ); returnStringVector->push_back( 'a' ); returnStringVector->push_back( 'm' ); returnStringVector->push_back( 'p' ); returnStringVector->push_back( ';' ); break; case '<': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'l' ); returnStringVector->push_back( 't' ); returnStringVector->push_back( ';' ); break; case '>': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'g' ); returnStringVector->push_back( 't' ); returnStringVector->push_back( ';' ); break; case '\"': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'q' ); returnStringVector->push_back( 'u' ); returnStringVector->push_back( 'o' ); returnStringVector->push_back( 't' ); returnStringVector->push_back( ';' ); break; case '\'': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'a' ); returnStringVector->push_back( 'p' ); returnStringVector->push_back( 'o' ); returnStringVector->push_back( 's' ); returnStringVector->push_back( ';' ); break; default: returnStringVector->push_back( inString[i] ); break; } } int numChars = returnStringVector->size(); char *returnString = new char[ numChars + 1 ]; for( i=0; igetElement( i ) ); } returnString[ numChars ] = '\0'; delete returnStringVector; return returnString; } primrose-6+dfsg1.orig/minorGems/formats/xml/XMLUtils.h0000644000175000017500000000134107540235637021533 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #ifndef XML_UTILS_INCLUDED #define XML_UTILS_INCLUDED /** * Utilities for processing XML. * * @author Jason Rohrer */ class XMLUtils { public: /** * Escapes characters disallowed in XML character data. * * @param the string to escape as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return string with characters escaped as a newly allocated * \0-terminated string. * Must be destroyed by caller. */ static char *escapeDisallowedCharacters( char *inString ); }; #endif primrose-6+dfsg1.orig/minorGems/formats/html/0000755000175000017500000000000011201637525020035 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/formats/html/HTMLUtils.cpp0000644000175000017500000000215707540240755022341 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #include "HTMLUtils.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include char *HTMLUtils::removeAllTags( char *inString ) { SimpleVector *returnStringVector = new SimpleVector(); int stringLength = strlen( inString ); int i = 0; while( i < stringLength ) { if( inString[i] == '<' ) { // the start of a tag // skip all until (and including) close of tag while( i < stringLength && inString[i] != '>' ) { // do nothing i++; } } else { returnStringVector->push_back( inString[i] ); } i++; } int numChars = returnStringVector->size(); char *returnString = new char[ numChars + 1 ]; for( i=0; igetElement( i ) ); } returnString[ numChars ] = '\0'; delete returnStringVector; return returnString; } primrose-6+dfsg1.orig/minorGems/formats/html/HTMLUtils.h0000644000175000017500000000131007540240755021774 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #ifndef HTML_UTILS_INCLUDED #define HTML_UTILS_INCLUDED /** * Utilities for processing HTML. * * @author Jason Rohrer */ class HTMLUtils { public: /** * Removes all HTML tags from an HTML string. * * @param the HTML data as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return data with all HTML tags removed as a newly allocated * \0-terminated string. * Must be destroyed by caller. */ static char *removeAllTags( char *inString ); }; #endif primrose-6+dfsg1.orig/minorGems/formats/encodingUtilsTestCompile0000755000175000017500000000021007733613350023775 0ustar pabspabsg++ -g -I../.. -o encodingUtilsTest encodingUtilsTest.cpp encodingUtils.cpp ../util/stringUtils.cpp ../util/StringBufferOutputStream.cppprimrose-6+dfsg1.orig/minorGems/formats/encodingUtils.h0000644000175000017500000000423207733613350022057 0ustar pabspabs/* * Modification History * * 2003-August-22 Jason Rohrer * Created. * * 2003-September-22 Jason Rohrer * Added base64 encoding. */ #ifndef ENCODING_UTILS_INCLUDED #define ENCODING_UTILS_INCLUDED /** * A collection of functions for representing data in various encoding formats. * * @author Jason Rohrer */ /** * Encodes data as a ASCII hexidecimal string. * * @param inData the data to encode. * Must be destroyed by caller. * @param inDataLength the length of inData in bytes. * * @return a \0-terminated ASCII hexidecimal string containing * characters in the range [0-9] and [A-F]. * Will be twice as long as inData. * Must be destroyed by caller. */ char *hexEncode( unsigned char *inData, int inDataLength ); /** * Decodes raw data from an ASCII hexidecimal string. * * @param inHexString a \0-terminated hexidecimal string. * Must be destroyed by caller. * * @return an array of raw data, or NULL if decoding fails. * Will be half as long as inHexString. * Must be destroyed by caller if non-NULL. */ unsigned char *hexDecode( char *inHexString ); /** * Encodes data as a ASCII base64 string. * * @param inData the data to encode. * Must be destroyed by caller. * @param inDataLength the length of inData in bytes. * @param inBreakLines set to true to break lines every 76 characters, * or false to produce an unbroken base64 string. * * @return a \0-terminated ASCII base64 string containing * characters in the range [0-9], [A-Z], [a-z], and [+,/,=]. * Must be destroyed by caller. */ char *base64Encode( unsigned char *inData, int inDataLength, char inBreakLines = true ); /** * Decodes raw data from an ASCII base64 string. * * @param inBase64String a \0-terminated base64 string. Can optionally contain * linebreaks. * Must be destroyed by caller. * @param outDataLength pointer to where the length of the decoded data * should be returned. * * @return an array of raw data, or NULL if decoding fails. * Must be destroyed by caller if non-NULL. */ unsigned char *base64Decode( char *inBase64String, int *outDataLength ); #endif primrose-6+dfsg1.orig/minorGems/formats/encodingUtils.cpp0000644000175000017500000003143510027336105022405 0ustar pabspabs/* * Modification History * * 2003-August-22 Jason Rohrer * Created. * * 2003-September-22 Jason Rohrer * Added base64 encoding. * * 2004-March-21 Jason Rohrer * Fixed a variable scoping and redefinition bug pointed out by Benjamin Meyer. */ #include "encodingUtils.h" #include "minorGems/util/SimpleVector.h" #include #include char fourBitIntToHex( int inInt ) { char outChar[2]; if( inInt < 10 ) { sprintf( outChar, "%d", inInt ); } else { switch( inInt ) { case 10: outChar[0] = 'A'; break; case 11: outChar[0] = 'B'; break; case 12: outChar[0] = 'C'; break; case 13: outChar[0] = 'D'; break; case 14: outChar[0] = 'E'; break; case 15: outChar[0] = 'F'; break; default: outChar[0] = '0'; break; } } return outChar[0]; } // returns -1 if inHex is not a valid hex character int hexToFourBitInt( char inHex ) { int returnInt; switch( inHex ) { case '0': returnInt = 0; break; case '1': returnInt = 1; break; case '2': returnInt = 2; break; case '3': returnInt = 3; break; case '4': returnInt = 4; break; case '5': returnInt = 5; break; case '6': returnInt = 6; break; case '7': returnInt = 7; break; case '8': returnInt = 8; break; case '9': returnInt = 9; break; case 'A': case 'a': returnInt = 10; break; case 'B': case 'b': returnInt = 11; break; case 'C': case 'c': returnInt = 12; break; case 'D': case 'd': returnInt = 13; break; case 'E': case 'e': returnInt = 14; break; case 'F': case 'f': returnInt = 15; break; default: returnInt = -1; break; } return returnInt; } char *hexEncode( unsigned char *inData, int inDataLength ) { char *resultHexString = new char[ inDataLength * 2 + 1 ]; int hexStringIndex = 0; for( int i=0; i> 4 ); int lowBits = 0xF & ( currentByte ); resultHexString[ hexStringIndex ] = fourBitIntToHex( highBits ); hexStringIndex++; resultHexString[ hexStringIndex ] = fourBitIntToHex( lowBits ); hexStringIndex++; } resultHexString[ hexStringIndex ] = '\0'; return resultHexString; } unsigned char *hexDecode( char *inHexString ) { int hexLength = strlen( inHexString ); if( hexLength % 2 != 0 ) { // hex strings must be even in length return NULL; } int dataLength = hexLength / 2; unsigned char *rawData = new unsigned char[ dataLength ]; for( int i=0; i *encodingVector = new SimpleVector(); int numInLine = 0; // take groups of 3 data bytes and map them to 4 base64 digits for( int i=0; i> 18 ); unsigned int digitB = 0x3F & ( block >> 12 ); unsigned int digitC = 0x3F & ( block >> 6 ); unsigned int digitD = 0x3F & ( block ); encodingVector->push_back( binaryToAscii[ digitA ] ); encodingVector->push_back( binaryToAscii[ digitB ] ); encodingVector->push_back( binaryToAscii[ digitC ] ); encodingVector->push_back( binaryToAscii[ digitD ] ); numInLine += 4; if( inBreakLines && numInLine == 76 ) { // break the line encodingVector->push_back( '\r' ); encodingVector->push_back( '\n' ); numInLine = 0; } } else { // at end int numLeft = inDataLength - i; switch( numLeft ) { case 0: // no padding break; case 1: { // two digits, two pads unsigned int block = inData[i] << 16 | 0; unsigned int digitA = 0x3F & ( block >> 18 ); unsigned int digitB = 0x3F & ( block >> 12 ); encodingVector->push_back( binaryToAscii[ digitA ] ); encodingVector->push_back( binaryToAscii[ digitB ] ); encodingVector->push_back( '=' ); encodingVector->push_back( '=' ); break; } case 2: { // three digits, one pad unsigned int block = inData[i] << 16 | inData[i+1] << 8 | 0; // base64 digits, with digitA at left unsigned int digitA = 0x3F & ( block >> 18 ); unsigned int digitB = 0x3F & ( block >> 12 ); unsigned int digitC = 0x3F & ( block >> 6 ); encodingVector->push_back( binaryToAscii[ digitA ] ); encodingVector->push_back( binaryToAscii[ digitB ] ); encodingVector->push_back( binaryToAscii[ digitC ] ); encodingVector->push_back( '=' ); break; } default: break; } // done with all data i = inDataLength; } } char *returnString = encodingVector->getElementString(); delete encodingVector; return returnString; } unsigned char *base64Decode( char *inBase64String, int *outDataLength ) { SimpleVector *decodedVector = new SimpleVector(); int encodingLength = strlen( inBase64String ); SimpleVector *binaryEncodingVector = new SimpleVector(); int i; for( i=0; ipush_back( currentBinary ); } } int binaryEncodingLength = binaryEncodingVector->size(); unsigned char *binaryEncoding = binaryEncodingVector->getElementArray(); delete binaryEncodingVector; int blockCount = binaryEncodingLength / 4; if( binaryEncodingLength % 4 != 0 ) { // extra, 0-padded block blockCount += 1; } // take groups of 4 encoded digits and map them to 3 data bytes for( i=0; i> 16 ); unsigned int digitB = 0xFF & ( block >> 8 ); unsigned int digitC = 0xFF & ( block ); decodedVector->push_back( digitA ); decodedVector->push_back( digitB ); decodedVector->push_back( digitC ); } else { // at end int numLeft = binaryEncodingLength - i; switch( numLeft ) { case 0: // no padding break; case 1: { // impossible break; } case 2: { // two base64 digits, one data byte unsigned int block = binaryEncoding[i] << 18 | binaryEncoding[i+1] << 12 | 0; // data byte digits, with digitA at left unsigned int digitA = 0xFF & ( block >> 16 ); decodedVector->push_back( digitA ); break; } case 3: { // three base64 digits, two data bytes unsigned int block = binaryEncoding[i] << 18 | binaryEncoding[i+1] << 12 | binaryEncoding[i+2] << 6 | 0; // data byte digits, with digitA at left unsigned int digitA = 0xFF & ( block >> 16 ); unsigned int digitB = 0xFF & ( block >> 8 ); decodedVector->push_back( digitA ); decodedVector->push_back( digitB ); break; } default: break; } // done with all data i = binaryEncodingLength; } } delete [] binaryEncoding; *outDataLength = decodedVector->size(); unsigned char* returnData = decodedVector->getElementArray(); delete decodedVector; return returnData; } primrose-6+dfsg1.orig/minorGems/formats/encodingUtilsTest.cpp0000644000175000017500000000232107733613350023247 0ustar pabspabs/* * Modification History * * 2003-September-22 Jason Rohrer * Created. */ #include "encodingUtils.h" #include #include int main() { const char *dataString = "*#$&$(@KFI#*$(SDBM@#*!(@%" "*#$&$(@KFI#*$(SDBM@#*!(@%" "*#$&$(@KFI#*$(SDBM@#*!(@F" "*#$&$(@KFI#*$(SDBM@#*!(@F" "*#$&$(@KFI#*$(SDBM@#*!(@F" "*#$&$(@KFI#*$(SDBM@#*!(@%a"; printf( "base64 encoding the string: %s\n", dataString ); char *encoding = base64Encode( (unsigned char *)dataString, strlen( dataString ), true ); printf( "Encoded as:\n%s\n", encoding ); int decodedLength; unsigned char *decoding = base64Decode( encoding, &decodedLength ); char *buffer = new char[ decodedLength + 1 ]; memcpy( (void *)buffer, (void *)decoding, decodedLength ); buffer[ decodedLength ] = '\0'; printf( "Decoded as: %s\n", buffer ); if( strcmp( buffer, dataString ) == 0 ) { printf( "Test passed\n" ); } else { printf( "Test failed\n" ); } delete [] buffer; delete [] decoding; delete [] encoding; return 0; } primrose-6+dfsg1.orig/minorGems/util/0000755000175000017500000000000011201637600016365 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/util/development/0000755000175000017500000000000011203741225020710 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/util/development/leakTracer/0000755000175000017500000000000011201637600022764 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/util/development/leakTracer/LeakCheckAnalyze0000755000175000017500000000033110612151771026052 0ustar pabspabs#!/bin/sh CHECKER=`dirname $0`/LeakCheck" $@" ANALYZER=`dirname $0`/leak-analyze" $1 leak.out" echo "Checking with: $CHECKER" echo "" $CHECKER echo "" echo "Analyzing with: $ANALYZER" echo "" $ANALYZER 2>&1 | more primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/leak-analyze0000755000175000017500000000636410002231613025270 0ustar pabspabs#!/usr/bin/perl # # Modification History # # 2004-January-17 Jason Rohrer # Fixed regexps to match both A-F and a-f for hex address strings. # # Erwin S. Andreasen # Henner Zeller # # Homepage: http://www.andreasen.org/LeakTracer/ # This program is Public Domain use IO::Handle; die "You must supply at least one argument.\n" unless $#ARGV >= 0; $ExeFile = shift @ARGV; $LeaksFile = $#ARGV >= 0 ? shift @ARGV : "leak.out"; open (LEAKS, $LeaksFile) or die "Could not open leaks data file $LeaksFile: $!"; if ($#ARGV >= 0) { $BreakOn = shift @ARGV; # Rest in @ARGV are program arguments } $n = $u = 0; while () { chop; next if (m/^\s*#/); # 1 2 3 4 5 6 7 #if (/^\s*L\s+(0x)?([0-9a-fA-F]+)\s+(0x)?([0-9a-fA-F]+)\s+(0x)?([0-9a-fA-F]+)\s+(\d+)/) { # Allocations, which have not been freed or deallocations which have not # been allocated. # 1 2 3 if (/^\s*L\s+(0x)?([0-9a-fA-F]+)\s+(\d+)/) { $addr="$2"; # ",$4,$6"; $u++ if not exists $Type{$addr}; $Count{$addr}++; $Size{$addr} += $3; # $7; $Type{$addr} = "Leak"; $n++; } elsif (/^\s*D\s+(0x)?([0-9a-fA-F]+)/) { $addr="$2"; # ",$4,$6"; $u++ if not exists $Type{$addr}; $Count{$addr}++; $Type{$addr} = "delete on not allocated memory"; $n++; } # allocations/deallocations with other errornous conditions # 1 2 3 4 5 elsif (/^\s*([SO])\s+(0x)?([0-9a-fA-F]+)\s+(0x)?([0-9a-fA-F]+)/) { $addrs = "$3,$5,$1"; $AllocDealloc{$addrs} = ("$1" =~ m/S/) ? "Different allocation schemes" : "This Memory was overwritten"; } } print STDERR "Gathered $n ($u unique) points of data.\n"; close (LEAKS); # Instead of using -batch, we just run things as usual. with -batch, # we quit on the first error, which we don't want. open (PIPE, "|gdb -q $ExeFile") or die "Cannot start gdb"; #open (PIPE, "|cat"); # Change set listsize 2 to something else to show more lines print PIPE "set prompt\nset complaints 1000\nset height 0\n"; # Optionally, run the program if (defined($BreakOn)) { print PIPE "break $BreakOn\n"; print PIPE "run ", join(" ", @ARGV), " \n"; } print PIPE "set listsize 2\n"; foreach (sort keys %AllocDealloc) { print PIPE "echo \\n#-- Alloc: $AllocDealloc{$_}\\nalloc here :\n"; @addrs = split(/,/,$_); print PIPE "l *0x" . (shift @addrs) . "\necho ..free here :\n"; print PIPE "set listsize 1\n"; print PIPE "l *0x" . (shift @addrs) . "\n"; } foreach (sort keys %Type) { print PIPE "echo \\n#-- $Type{$_}: counted $Count{$_}x"; if ($Size{$_} > 0) { print PIPE " / total Size: $Size{$_}"; } print PIPE "\\n\n"; @addrs = split(/,/,$_); print PIPE "set listsize 2\n"; print PIPE "l *0x" . (shift @addrs) . "\n"; #print PIPE "echo ..called from :\n"; #print PIPE "set listsize 1\n"; # gdb bails out, if it cannot find an address. #print PIPE "l *0x" . (shift @addrs) . "\necho ..called from :\n"; #print PIPE "l *0x" . (shift @addrs) . "\n"; } if (defined($BreakOn)) { print PIPE "kill\n"; } print PIPE "quit\n"; PIPE->flush(); wait(); close (PIPE); primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/VERSION0000644000175000017500000000000410001775461024033 0ustar pabspabs2.3 primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/LeakCheck0000755000175000017500000000064010001775461024531 0ustar pabspabs#!/bin/sh if [ $# -lt 1 ] ; then echo "Usage: $0 " exit 1 fi # this looks in the same directory, this # LeakCheck script resides; modify to your # needs: SHLIB=`dirname $0`/LeakTracer.so if [ ! -x $SHLIB ] ; then echo "$SHLIB not found" exit 1 fi if [ -z "$LEAKTRACE_FILE" ] ; then rm -f leak.out else rm -f "$LEAKTRACE_FILE" fi export LD_PRELOAD=$SHLIB exec $@ primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/test.cc0000644000175000017500000000054110001775461024257 0ustar pabspabs/* * Modification History * * 2002-March-31 Jason Rohrer * Added test of strdup support. */ #include // Small leaky test program void foo() { int *x = new int; } int main() { char *str = strdup( "Test String" ); int *z = new int[10]; foo(); foo(); delete z; delete z; // delete value twice } primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/README.html0000644000175000017500000002270510001775461024622 0ustar pabspabs

Table of contents

Introduction

LeakTracer is a small tool I wrote when checking a C++ program for memory
leaks. I couldn't get dmalloc to display what I wanted, and I just saw the
__builtin_return_address gcc-extension mentioned.

To use LeakTracer, run your program using the provided LeakCheck script. It
uses the LD_PRELOAD feature to "overlay" some functions on top of your
functions (no recompile needed). If your platform does not support LD_PRELOAD,
you can add the LeakTracer.o object file to the objects in your Makefile and
run your application. 

LeakTracer uses gdb to print out the exact line where the memory was allocated
and not freed - this of course means you have to free all dynamically
allocated data. LeakTracer also overrides the global operator new and operator
delete - this will give problems if you override them as well.

LeakTracer traces only new/new[] and delete calls - it does not look at
malloc/free/realloc.

Here is some example output:

Gathered 8 (8 unique) points of data.
(gdb)
Allocations: 1 / Size: 36
0x80608e6 is in NullArcableInstance::NullArcableInstance(void) (Machine.cc:40).
39      public:
40          NullArcableInstance() : ArcableInstance(new NullArcable) {}

Allocations: 1 / Size: 8
0x8055b02 is in init_types(void) (Type.cc:119).
118     void init_types() {
119         Type::Integer = new IntegerType;

Allocations: 1 / Size: 132 (new[])
0x805f4ab is in Hashtable::Hashtable(unsigned int) (ea/h/Hashtable.h:15).
14          Hashtable (uint _size = 32) : size(_size), count(0) {
15              table = new List [size];

[...]

Requirements

You need Perl5 and gdb installed to run the leak-analyzer. You need gcc -- I
currently use 2.95 but have used it with previous older versions without
problems.
You also need to run this on an architecture which supports
__builtin_return_address arguments that are greater than 0 - there may be
some problems on MIPS there. 

So far this code has been tested under Linux 2.2, x86 system, Solaris and
HP-UX.

Installation

Just type make. There is no install target; you should put LeakTracer
some place you can remember.

Since version 2.0, it is possible to preload the LeakTracer object on
architectures that support LD_PRELOAD (this is at least Linux and probably
others -- please report success/failure). This means it is much easier to use
the program: you do not need to relink your program with LeakTracer.o.

In case your platform does not support LD_PRELOAD, you can use LeakTracer in
the old pre 2.0 way: add LeakTracer.o to your object files -- at the very end
of them (also after -llibrary lines).

In any case your application must also be compiled with debugging enabled
(i.e. -g).

Running with LeakTracer

If you are using the shared object, run the LeakCheck script. This script
should stay in the directory where you install LeakCheck -- it will search for
LeakTracer.so file there and load it. E.g.:

~/src/LeakTracer/LeakCheck yourApplication

(if you put LeakTracer in ~/src/LeakTracer/)

Run your application as normal, performing tasks that you want to be traced
for memory leaks. While the application runs, LeakTracer will write data about
memory allocation to the file "leak.out" in the current directory. You can
override the location of that file by setting the LEAKTRACE_FILE environment
variable.

If you cannot use LD_PRELOAD, just run your application as normal after
relinking it. It will also produce a "leak.out" file when it finishes.

Detectable errors

LeakTracer is capable to detect the following problems with your program

  1) memory which is allocated but not freed
  2) (limited support for) overwritten memory at the end of the allocated
     block  ( reason = 1 )
  3) memory which is tried to be deleted but which is not allocated
     (either because of a garbage pointer or twice deletion)
     (reason = 2)
  4) memory which is allocated with new[] but deleted with simple delete
     and vice versa (reason = 4)

For the last three problems, LeakTracer can abort() your program if you
tell it so; the resulting core-dump allows to debug the problem. By default,
only the overwrite memory condition results in an abort of the program
because it is inherently critical. The two other conditions are not critical.
You can influence what LeakTracer does with the environment variable
   LT_ABORTREASON
which you can set to some numeric value which is the result of the
sum of the reasons you find in the parentesis in the enumeration above.
To abort on any reason, for example, you would set LT_ABORTREASON to 7.

Analyzing output

You should then run leak-analyze, since looking at the raw leak.out file will
not help you much. To run leak-analyze, you need Perl as well as gdb
installed (any version of gdb will do). For example:

leak-analyze myprog leak.out

You don't have to specify the leak.out filename if you just use the default
one. leak-analyze will run gdb on the file, sending it a number of commands
that will show the source lines with the memory leaks.

leak-analyze should show you something like this:

Gathered 2 (2 unique) points of data.

#-- Alloc: Different allocation schemes
alloc here :0x80485b7 is in main (test.cc:6).
5
6               int *wrong = new int[10];
..free here :0x80485d9 is in main (test.cc:11).
11              delete wrong;

#-- Leak: Allocations: 1 / Size: 168 
0x8048593 is in main (test.cc:3).
2       int main() {
3               int *array = new int [42] ;

#-- Leak: Allocations: 1 / Size: 4 
0x80485a5 is in main (test.cc:4).
3               int *array = new int [42] ;
4               int *foo = new int;
This means that total of two allocations happened, in two different places.

First a delete error is shown: you allocated some memory using new[] but you
freed it using delete. leak-analyze will show where you allocated the memory and where you freed it.

Afterwards each allocation is shown in turn. There was 1 allocation from this
line of code (test.cc:3), and it was 168 bytes in size. Note that of the two
lines of code shown, it's the bottom one that created the allocation.

That's all there is to it - now you should find those memory leaks, fix them
and rerun Leak tracer.

Shared libraries and objects

If you want to analyze the leaks in shared libraries in your file, it may be
necessary to make leak-analyze run your program and thus load the shared
libraries before searching for addresses.

To do that, run leak-analyze with the program name, leak name AND another
argument which is where to set the breakpoint, e.g.:

leak-analyze myprog leak.out main

This will make leak-analyze tell gdb to set a breakpoint on "main" and then
run the program. After the analysis is complete, the program will be killed.

If you want to load some shared libraries, you can set a breakpoint on a
different location, e.g. main.cc:42 if you know that once line 42 is reached,
all shared objects have been loaded.

If your program needs some command line arguments, supply them after "main".

Licensing

LeakTracer is public domain (i.e. do with it whatever you feel like).

Credits

Initial version of LeakTracer was written by Erwin Andreasen. Henner Zeller
(foobar@to.com) contributed a rewrite of the code which
introduced dynamic loading of LeakTracer and more.

Revision history

February 21, 1999       v1.0 - only tested internally
February 23, 1999       v1.1 - added operator new[] / delete[]
February 23, 1999           v1.2 - Oops, forgot to free() the memory..
February 26, 1999       v1.3 - allow delete 0
March 27, 1999          v1.4 - Allow %p format without leading 0x for non-GNU 
                                       libc. Option to leak-analyze to run the program.
July 21, 1999               v1.5 - Fix for the above suggested by Alan Gonzalez
August 21, 2000         v1.6 - use a destructor instead of 
                                       __attribute__(destructor)
November 19, 2000               v2.0 - Rewrite by Henner Zeller introduces LD_PRELOAD
                                       and much more
February 27, 2001               v2.1 - Further update by Henner: optional thread safety,
                                       choose what should make LeakTracer abort(), better
                                       tracing of delete on non-new'ed pointers
March 2, 2001                   v2.2 - Another updated by Henner: hash table to increase
                                       performance with many allocations
June 13, 2001                   v2.3 - Made LT more resistant to being called before init
                                       and after destruction

Authors:    Erwin Andreasen 
        Henner Zeller 
Homepage:   http://www.andreasen.org/LeakTracer/

primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/Makefile0000644000175000017500000000262510001777407024440 0ustar pabspabs# # Modification History # # 2004-January-16 Jason Rohrer # Switched to use minorGems platform-independed mutexes. # CC = g++ # Source files SRC := LeakTracer.cc ROOT_PATH = ../../../.. # Switch comment to select a platform # PLATFORM_MUTEX = $(ROOT_PATH)/minorGems/system/win32/MutexLockWin32.cpp PLATFORM_MUTEX = $(ROOT_PATH)/minorGems/system/linux/MutexLockLinux.cpp -pthread # Comment both of these out to disable thread safetly C_THREAD=-DTHREAD_SAVE -D_REENTRANT -D_THREAD_SAFE O_THREAD = $(PLATFORM_MUTEX) # Common flags C_FLAGS = -g -pipe -Wall -W -I$(ROOT_PATH) $(C_THREAD) O_FLAGS = $(C_FLAGS) $(O_THREAD) # Object files OBJ_DIR = . OBJ := $(patsubst %.cc,$(OBJ_DIR)/%.o,$(SRC)) SHOBJ := $(patsubst %.o,$(OBJ_DIR)/%.so,$(OBJ)) .PHONY: all clean tidy distrib test all: $(OBJ) $(SHOBJ) clean: tidy rm -f $(OBJ) leak.out tidy: rm -f *~ *orig *bak *rej tags: $(SRC) $(INCL) ctags $(SRC) $(INCL) distrib: clean all README.html (cd .. && tar cvfz /root/drylock/LeakTracer/LeakTracer.tar.gz --exclude LeakTracer/CVS --exclude LeakTracer/old --exclude LeakTracer/test LeakTracer/) $(OBJ_DIR)/%.o: %.cc $(CC) -fPIC -c $(C_FLAGS) $< -o $@ $(OBJ_DIR)/%.so : $(OBJ_DIR)/%.o $(CC) $(O_FLAGS) -shared -o $@ $< README.html: README /root/ed/mcl/util/htmlize.pl README test: $(CC) $(C_FLAGS) test.cc -o test ./test ./LeakCheck ./test ./leak-analyze ./test # ./compare-test test.template test.result primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/README0000644000175000017500000002130110001775461023646 0ustar pabspabsIntroduction ------------ LeakTracer is a small tool I wrote when checking a C++ program for memory leaks. I couldn't get dmalloc to display what I wanted, and I just saw the __builtin_return_address gcc-extension mentioned. To use LeakTracer, run your program using the provided LeakCheck script. It uses the LD_PRELOAD feature to "overlay" some functions on top of your functions (no recompile needed). If your platform does not support LD_PRELOAD, you can add the LeakTracer.o object file to the objects in your Makefile and run your application. LeakTracer uses gdb to print out the exact line where the memory was allocated and not freed - this of course means you have to free all dynamically allocated data. LeakTracer also overrides the global operator new and operator delete - this will give problems if you override them as well. LeakTracer traces only new/new[] and delete calls - it does not look at malloc/free/realloc. Here is some example output: Gathered 8 (8 unique) points of data. (gdb) Allocations: 1 / Size: 36 0x80608e6 is in NullArcableInstance::NullArcableInstance(void) (Machine.cc:40). 39 public: 40 NullArcableInstance() : ArcableInstance(new NullArcable) {} Allocations: 1 / Size: 8 0x8055b02 is in init_types(void) (Type.cc:119). 118 void init_types() { 119 Type::Integer = new IntegerType; Allocations: 1 / Size: 132 (new[]) 0x805f4ab is in Hashtable::Hashtable(unsigned int) (ea/h/Hashtable.h:15). 14 Hashtable (uint _size = 32) : size(_size), count(0) { 15 table = new List [size]; [...] Requirements ------------ You need Perl5 and gdb installed to run the leak-analyzer. You need gcc -- I currently use 2.95 but have used it with previous older versions without problems. You also need to run this on an architecture which supports __builtin_return_address arguments that are greater than 0 - there may be some problems on MIPS there. So far this code has been tested under Linux 2.2, x86 system, Solaris and HP-UX. Installation ------------ Just type make. There is no install target; you should put LeakTracer some place you can remember. Since version 2.0, it is possible to preload the LeakTracer object on architectures that support LD_PRELOAD (this is at least Linux and probably others -- please report success/failure). This means it is much easier to use the program: you do not need to relink your program with LeakTracer.o. In case your platform does not support LD_PRELOAD, you can use LeakTracer in the old pre 2.0 way: add LeakTracer.o to your object files -- at the very end of them (also after -llibrary lines). In any case your application must also be compiled with debugging enabled (i.e. -g). Running with LeakTracer ----------------------- If you are using the shared object, run the LeakCheck script. This script should stay in the directory where you install LeakCheck -- it will search for LeakTracer.so file there and load it. E.g.: ~/src/LeakTracer/LeakCheck yourApplication (if you put LeakTracer in ~/src/LeakTracer/) Run your application as normal, performing tasks that you want to be traced for memory leaks. While the application runs, LeakTracer will write data about memory allocation to the file "leak.out" in the current directory. You can override the location of that file by setting the LEAKTRACE_FILE environment variable. If you cannot use LD_PRELOAD, just run your application as normal after relinking it. It will also produce a "leak.out" file when it finishes. Detectable errors ----------------- LeakTracer is capable to detect the following problems with your program 1) memory which is allocated but not freed 2) (limited support for) overwritten memory at the end of the allocated block ( reason = 1 ) 3) memory which is tried to be deleted but which is not allocated (either because of a garbage pointer or twice deletion) (reason = 2) 4) memory which is allocated with new[] but deleted with simple delete and vice versa (reason = 4) For the last three problems, LeakTracer can abort() your program if you tell it so; the resulting core-dump allows to debug the problem. By default, only the overwrite memory condition results in an abort of the program because it is inherently critical. The two other conditions are not critical. You can influence what LeakTracer does with the environment variable LT_ABORTREASON which you can set to some numeric value which is the result of the sum of the reasons you find in the parentesis in the enumeration above. To abort on any reason, for example, you would set LT_ABORTREASON to 7. Analyzing output ---------------- You should then run leak-analyze, since looking at the raw leak.out file will not help you much. To run leak-analyze, you need Perl as well as gdb installed (any version of gdb will do). For example: leak-analyze myprog leak.out You don't have to specify the leak.out filename if you just use the default one. leak-analyze will run gdb on the file, sending it a number of commands that will show the source lines with the memory leaks. leak-analyze should show you something like this: Gathered 2 (2 unique) points of data. #-- Alloc: Different allocation schemes alloc here :0x80485b7 is in main (test.cc:6). 5 6 int *wrong = new int[10]; ..free here :0x80485d9 is in main (test.cc:11). 11 delete wrong; #-- Leak: Allocations: 1 / Size: 168 0x8048593 is in main (test.cc:3). 2 int main() { 3 int *array = new int [42] ; #-- Leak: Allocations: 1 / Size: 4 0x80485a5 is in main (test.cc:4). 3 int *array = new int [42] ; 4 int *foo = new int; This means that total of two allocations happened, in two different places. First a delete error is shown: you allocated some memory using new[] but you freed it using delete. leak-analyze will show where you allocated the memory and where you freed it. Afterwards each allocation is shown in turn. There was 1 allocation from this line of code (test.cc:3), and it was 168 bytes in size. Note that of the two lines of code shown, it's the bottom one that created the allocation. That's all there is to it - now you should find those memory leaks, fix them and rerun Leak tracer. Shared libraries and objects ---------------------------- If you want to analyze the leaks in shared libraries in your file, it may be necessary to make leak-analyze run your program and thus load the shared libraries before searching for addresses. To do that, run leak-analyze with the program name, leak name AND another argument which is where to set the breakpoint, e.g.: leak-analyze myprog leak.out main This will make leak-analyze tell gdb to set a breakpoint on "main" and then run the program. After the analysis is complete, the program will be killed. If you want to load some shared libraries, you can set a breakpoint on a different location, e.g. main.cc:42 if you know that once line 42 is reached, all shared objects have been loaded. If your program needs some command line arguments, supply them after "main". Licensing --------- LeakTracer is public domain (i.e. do with it whatever you feel like). Credits ------- Initial version of LeakTracer was written by Erwin Andreasen. Henner Zeller (foobar@to.com) contributed a rewrite of the code which introduced dynamic loading of LeakTracer and more. Revision history ---------------- February 21, 1999 v1.0 - only tested internally February 23, 1999 v1.1 - added operator new[] / delete[] February 23, 1999 v1.2 - Oops, forgot to free() the memory.. February 26, 1999 v1.3 - allow delete 0 March 27, 1999 v1.4 - Allow %p format without leading 0x for non-GNU libc. Option to leak-analyze to run the program. July 21, 1999 v1.5 - Fix for the above suggested by Alan Gonzalez August 21, 2000 v1.6 - use a destructor instead of __attribute__(destructor) November 19, 2000 v2.0 - Rewrite by Henner Zeller introduces LD_PRELOAD and much more February 27, 2001 v2.1 - Further update by Henner: optional thread safety, choose what should make LeakTracer abort(), better tracing of delete on non-new'ed pointers March 2, 2001 v2.2 - Another updated by Henner: hash table to increase performance with many allocations June 13, 2001 v2.3 - Made LT more resistant to being called before init and after destruction Authors: Erwin Andreasen Henner Zeller Homepage: http://www.andreasen.org/LeakTracer/ primrose-6+dfsg1.orig/minorGems/util/development/leakTracer/LeakTracer.cc0000644000175000017500000003331410002005355025306 0ustar pabspabs/* * Modification History * * 2002-March-31 Jason Rohrer * Added support for strdup. * Fixed bug in strdup. * * 2003-October-3 Jason Rohrer * Added printout of leak contents in report. * * 2004-January-16 Jason Rohrer * Switched to use minorGems platform-independed mutexes. * Changed to use simpler fopen call to open report. */ /* * Homepage: * * Authors: * Erwin S. Andreasen * Henner Zeller * * This program is Public Domain */ #ifdef THREAD_SAVE #define _THREAD_SAVE //#include #include "minorGems/system/MutexLock.h" #endif #include #include #include #include #include #include #include #include #include #include /* * underlying allocation, de-allocation used within * this tool */ #define LT_MALLOC malloc #define LT_FREE free #define LT_REALLOC realloc /* * prime number for the address lookup hash table. * if you have _really_ many memory allocations, use a * higher value, like 343051 for instance. */ #define SOME_PRIME 35323 #define ADDR_HASH(addr) ((unsigned long) addr % SOME_PRIME) /** * Filedescriptor to write to. This should not be a low number, * because these often have special meanings (stdin, out, err) * and may be closed by the program (daemons) * So choose an arbitrary higher FileDescriptor .. e.g. 42 */ #define FILEDESC 42 /** * allocate a bit more memory in order to check if there is a memory * overwrite. Either 0 or more than sizeof(unsigned int). Note, you can * only detect memory over_write_, not _reading_ beyond the boundaries. Better * use electric fence for these kind of bugs * */ typedef unsigned long magic_t; #define MAGIC ((magic_t) 0xAABBCCDDLu) /** * this may be more than sizeof(magic_t); if you want more, then * sepecify it like #define SAVESIZE (sizeof(magic_t) + 12) */ #define SAVESIZE (sizeof(magic_t) + 0) /** * on 'new', initialize the memory with this value. * if not defined - uninitialized. This is very helpful because * it detects if you initialize your classes correctly .. if not, * this helps you faster to get the segmentation fault you're * implicitly asking for :-). * * Set this to some value which is likely to produce a * segmentation fault on your platform. */ #define SAVEVALUE 0xAA /** * on 'delete', clean memory with this value. * if not defined - no memory clean. * * Set this to some value which is likely to produce a * segmentation fault on your platform. */ #define MEMCLEAN 0xEE /** * Initial Number of memory allocations in our list. * Doubles for each re-allocation. */ #define INITIALSIZE 32768 static class LeakTracer { struct Leak { const void *addr; size_t size; const void *allocAddr; bool type; int nextBucket; }; int newCount; // how many memory blocks do we have int leaksCount; // amount of entries in the leaks array int firstFreeSpot; // Where is the first free spot in the leaks array? int currentAllocated; // currentAllocatedMemory int maxAllocated; // maximum Allocated unsigned long totalAllocations; // total number of allocations. stats. unsigned int abortOn; // resons to abort program (see abortReason_t) /** * Have we been initialized yet? We depend on this being * false before constructor has been called! */ bool initialized; bool destroyed; // Has our destructor been called? FILE *report; // filedescriptor to write to /** * pre-allocated array of leak info structs. */ Leak *leaks; /** * fast hash to lookup the spot where an allocation is * stored in case of an delete. map */ int *leakHash; // fast lookup #ifdef THREAD_SAVE MutexLock mutex; #endif enum abortReason_t { OVERWRITE_MEMORY = 0x01, DELETE_NONEXISTENT = 0x02, NEW_DELETE_MISMATCH = 0x04 }; public: LeakTracer() { initialize(); } void initialize() { // Unfortunately we might be called before our constructor has actualy fired if (initialized) return; // fprintf(stderr, "LeakTracer::initialize()\n"); initialized = true; newCount = 0; leaksCount = 0; firstFreeSpot = 1; // index '0' is special currentAllocated = 0; maxAllocated = 0; totalAllocations = 0; abortOn = OVERWRITE_MEMORY; // only _severe_ reason report = 0; leaks = 0; leakHash = 0; char uniqFilename[256]; const char *filename = getenv("LEAKTRACE_FILE") ? : "leak.out"; struct stat dummy; if (stat(filename, &dummy) == 0) { sprintf(uniqFilename, "%s.%d", filename, getpid()); fprintf(stderr, "LeakTracer: file exists; using %s instead\n", uniqFilename); } else { sprintf(uniqFilename, "%s", filename); } // not sure why this "open" code is here // (it doesn't open the file properly in MinGW on win32) /* int reportfd = open(uniqFilename, O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE); if (reportfd < 0) { fprintf(stderr, "LeakTracer: cannot open %s: %m\n", filename); report = stderr; } else { int dupfd = dup2(reportfd, FILEDESC); close(reportfd); report = fdopen(dupfd, "w"); if (report == NULL) { report = stderr; } } */ // simpler version using only fopen report = fopen( uniqFilename, "w" ); if( report == NULL ) { fprintf( stderr, "LeakTracer: cannot open %s\n", uniqFilename ); report = stderr; } time_t t = time(NULL); fprintf (report, "# starting %s", ctime(&t)); leakHash = (int*) LT_MALLOC(SOME_PRIME * sizeof(int)); memset ((void*) leakHash, 0x00, SOME_PRIME * sizeof(int)); #ifdef MAGIC fprintf (report, "# memory overrun protection of %d Bytes " "with magic 0x%4lX\n", SAVESIZE, MAGIC); #endif #ifdef SAVEVALUE fprintf (report, "# initializing new memory with 0x%2X\n", SAVEVALUE); #endif #ifdef MEMCLEAN fprintf (report, "# sweeping deleted memory with 0x%2X\n", MEMCLEAN); #endif if (getenv("LT_ABORTREASON")) { abortOn = atoi(getenv("LT_ABORTREASON")); } #define PRINTREASON(x) if (abortOn & x) fprintf(report, "%s ", #x); fprintf (report, "# aborts on "); PRINTREASON( OVERWRITE_MEMORY ); PRINTREASON( DELETE_NONEXISTENT ); PRINTREASON( NEW_DELETE_MISMATCH ); fprintf (report, "\n"); #undef PRINTREASON #ifdef THREAD_SAVE fprintf (report, "# thread save\n"); /* * create default, non-recursive ('fast') mutex * to lock our datastructure where we keep track of * the user's new/deletes */ /*if (pthread_mutex_init(&mutex, NULL) < 0) { fprintf(report, "# couldn't init mutex ..\n"); fclose(report); _exit(1); }*/ #else fprintf(report, "# not thread save; if you use threads, recompile with -DTHREAD_SAVE\n"); #endif fflush(report); } /* * the workhorses: */ void *registerAlloc(size_t size, bool type); void registerFree (void *p, bool type); /** * write a hexdump of the given area. */ void hexdump(const unsigned char* area, int size); /** * Terminate current running progam. */ void progAbort(abortReason_t reason) { if (abortOn & reason) { fprintf(report, "# abort; DUMP of current state\n"); writeLeakReport(); fclose(report); abort(); } else fflush(report); } /** * write a Report over leaks, e.g. still pending deletes */ void writeLeakReport(); ~LeakTracer() { // fprintf(stderr, "LeakTracer::destroy()\n"); time_t t = time(NULL); fprintf (report, "# finished %s", ctime(&t)); writeLeakReport(); fclose(report); free(leaks); #ifdef THREAD_SAVE //pthread_mutex_destroy(&mutex); #endif destroyed = true; } } leakTracer; void* LeakTracer::registerAlloc (size_t size, bool type) { initialize(); // fprintf(stderr, "LeakTracer::registerAlloc()\n"); if (destroyed) { fprintf(stderr, "Oops, registerAlloc called after destruction of LeakTracer (size=%d)\n", size); return LT_MALLOC(size); } void *p = LT_MALLOC(size + SAVESIZE); // Need to call the new-handler if (!p) { fprintf(report, "LeakTracer malloc %m\n"); _exit (1); } #ifdef SAVEVALUE /* initialize with some defined pattern */ memset(p, SAVEVALUE, size + SAVESIZE); #endif #ifdef MAGIC /* * the magic value is a special pattern which does not need * to be uniform. */ if (SAVESIZE >= sizeof(magic_t)) { magic_t *mag; mag = (magic_t*)((char*)p + size); *mag = MAGIC; } #endif #ifdef THREAD_SAVE //pthread_mutex_lock(&mutex); mutex.lock(); #endif ++newCount; ++totalAllocations; currentAllocated += size; if (currentAllocated > maxAllocated) maxAllocated = currentAllocated; for (;;) { for (int i = firstFreeSpot; i < leaksCount; i++) if (leaks[i].addr == NULL) { leaks[i].addr = p; leaks[i].size = size; leaks[i].type = type; leaks[i].allocAddr=__builtin_return_address(1); firstFreeSpot = i+1; // allow to lookup our index fast. int *hashPos = &leakHash[ ADDR_HASH(p) ]; leaks[i].nextBucket = *hashPos; *hashPos = i; #ifdef THREAD_SAVE //pthread_mutex_unlock(&mutex); mutex.unlock(); #endif return p; } // Allocate a bigger array // Note that leaksCount starts out at 0. int new_leaksCount = (leaksCount == 0) ? INITIALSIZE : leaksCount * 2; leaks = (Leak*)LT_REALLOC(leaks, sizeof(Leak) * new_leaksCount); if (!leaks) { fprintf(report, "# LeakTracer realloc failed: %m\n"); _exit(1); } else { fprintf(report, "# internal buffer now %d\n", new_leaksCount); fflush(report); } memset(leaks+leaksCount, 0x00, sizeof(Leak) * (new_leaksCount-leaksCount)); leaksCount = new_leaksCount; } } void LeakTracer::hexdump(const unsigned char* area, int size) { fprintf(report, "# "); for (int j=0; j < size ; ++j) { fprintf (report, "%02x ", *(area+j)); if (j % 16 == 15) { fprintf(report, " "); for (int k=-15; k < 0 ; k++) { char c = (char) *(area + j + k); fprintf (report, "%c", isprint(c) ? c : '.'); } fprintf(report, "\n# "); } } fprintf(report, "\n"); } void LeakTracer::registerFree (void *p, bool type) { initialize(); if (p == NULL) return; if (destroyed) { fprintf(stderr, "Oops, allocation destruction of LeakTracer (p=%p)\n", p); return; } #ifdef THREAD_SAVE //pthread_mutex_lock(&mutex); mutex.lock(); #endif int *lastPointer = &leakHash[ ADDR_HASH(p) ]; int i = *lastPointer; while (i != 0 && leaks[i].addr != p) { lastPointer = &leaks[i].nextBucket; i = *lastPointer; } if (leaks[i].addr == p) { *lastPointer = leaks[i].nextBucket; // detach. newCount--; leaks[i].addr = NULL; currentAllocated -= leaks[i].size; if (i < firstFreeSpot) firstFreeSpot = i; if (leaks[i].type != type) { fprintf(report, "S %10p %10p # new%s but delete%s " "; size %d\n", leaks[i].allocAddr, __builtin_return_address(1), ((!type) ? "[]" : " normal"), ((type) ? "[]" : " normal"), leaks[i].size); progAbort( NEW_DELETE_MISMATCH ); } #ifdef MAGIC if ((SAVESIZE >= sizeof(magic_t)) && *((magic_t*)((char*)p + leaks[i].size)) != MAGIC) { fprintf(report, "O %10p %10p " "# memory overwritten beyond allocated" " %d bytes\n", leaks[i].allocAddr, __builtin_return_address(1), leaks[i].size); fprintf(report, "# %d byte beyond area:\n", SAVESIZE); hexdump((unsigned char*)p+leaks[i].size, SAVESIZE); progAbort( OVERWRITE_MEMORY ); } #endif #ifdef THREAD_SAVE # ifdef MEMCLEAN int allocationSize = leaks[i].size; # endif //pthread_mutex_unlock(&mutex); mutex.unlock(); #else #define allocationSize leaks[i].size #endif #ifdef MEMCLEAN // set it to some garbage value. memset((unsigned char*)p, MEMCLEAN, allocationSize + SAVESIZE); #endif LT_FREE(p); return; } #ifdef THREAD_SAVE //pthread_mutex_unlock(&mutex); mutex.unlock(); #endif fprintf(report, "D %10p # delete non alloc or twice pointer %10p\n", __builtin_return_address(1), p); progAbort( DELETE_NONEXISTENT ); } void LeakTracer::writeLeakReport() { initialize(); if (newCount > 0) { fprintf(report, "# LeakReport\n"); fprintf(report, "# %10s | %9s # Pointer Addr\n", "from new @", "size"); } for (int i = 0; i < leaksCount; i++) if (leaks[i].addr != NULL) { // This ought to be 64-bit safe? char *memContents = (char *)LT_MALLOC( leaks[i].size + 1 ); memcpy( (void *)memContents, (void *)( leaks[i].addr ), leaks[i].size ); memContents[ leaks[i].size ] = '\0'; fprintf(report, "L %10p %9ld # %p %s\n", leaks[i].allocAddr, (long) leaks[i].size, leaks[i].addr, memContents ); LT_FREE( memContents ); } fprintf(report, "# total allocation requests: %6ld ; max. mem used" " %d kBytes\n", totalAllocations, maxAllocated / 1024); fprintf(report, "# leak %6d Bytes\t:-%c\n", currentAllocated, (currentAllocated == 0) ? ')' : '('); if (currentAllocated > 50 * 1024) { fprintf(report, "# .. that is %d kByte!! A lot ..\n", currentAllocated / 1024); } } /** -- The actual new/delete operators -- **/ void* operator new(size_t size) { return leakTracer.registerAlloc(size,false); } void* operator new[] (size_t size) { return leakTracer.registerAlloc(size,true); } void operator delete (void *p) { leakTracer.registerFree(p,false); } void operator delete[] (void *p) { leakTracer.registerFree(p,true); } // added by Jason Rohrer char *strdup( const char *inString ) { char *outString = (char*)leakTracer.registerAlloc( strlen( inString ) + 1, true ); strcpy( outString, inString ); return outString; } /* Emacs: * Local variables: * c-basic-offset: 8 * End: * vi:set tabstop=8 shiftwidth=8 nowrap: */ primrose-6+dfsg1.orig/minorGems/util/development/memory/0000755000175000017500000000000011201637600022217 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/util/development/memory/debugMemory.cpp0000644000175000017500000000421307554553735025230 0ustar pabspabs/* * Modification History * * 2002-October-17 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Added static initialization counting class for MemoryTrack. * * 2002-October-19 Jason Rohrer * Added more detail to error message. * Improved printing behavior. * Moved include of debugMemory.h to work better with IDE compilers. * Fixed to deal with differences between malloc and new[] on some platforms. * * 2002-October-20 Jason Rohrer * Removed delete macro trick that was causing crashes in tinyxml. * Removed function that was no longer being used. */ #include "minorGems/util/development/memory/debugMemory.h" #ifdef DEBUG_MEMORY #include "minorGems/util/development/memory/MemoryTrack.h" #include "stdlib.h" #include "stdio.h" void *debugMemoryNew( unsigned int inSize, const char *inFileName, int inLine ) { void *allocatedPointer = (void *)malloc( inSize ); MemoryTrack::addAllocation( allocatedPointer, inSize, SINGLE_ALLOCATION, inFileName, inLine ); return allocatedPointer; } void *debugMemoryNewArray( unsigned int inSize, const char *inFileName, int inLine ) { unsigned int mallocSize = inSize; if( inSize == 0 ) { // always allocate at least one byte to circumvent differences // between malloc and new[] on some platforms // (new int[0] returns a pointer to an array of length 0, while // malloc( 0 ) can return NULL on some platforms) mallocSize = 1; } void *allocatedPointer = (void *)malloc( mallocSize ); MemoryTrack::addAllocation( allocatedPointer, inSize, ARRAY_ALLOCATION, inFileName, inLine ); return allocatedPointer; } void debugMemoryDelete( void *inPointer ) { MemoryTrack::addDeallocation( inPointer, SINGLE_ALLOCATION ); free( inPointer ); } void debugMemoryDeleteArray( void *inPointer ) { MemoryTrack::addDeallocation( inPointer, ARRAY_ALLOCATION ); free( inPointer ); } #endif primrose-6+dfsg1.orig/minorGems/util/development/memory/MemoryTrack.cpp0000644000175000017500000001620507554553734025211 0ustar pabspabs/* * Modification History * * 2002-October-17 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Changed to use custom list instead of SimpleVector because SimpleVector * uses debugMemory. * Added static initialization counting class. * Changed to use struct and malloc for AllocationList to avoid * circular new and delete calls. * * 2002-October-19 Jason Rohrer * Fixed a bug in adding to the alloc list. * Improved printing behavior. * Added support for clearing memory on allocation and deallocation. * Fixed to ignore deallocation of our own static lock. * Fixed bug in allocation count. * Added message for NULL pointer deallocation. * Put locks in place around print statements, which are not atomic on win32. * Changed to use hex notation when printing pointers. * * 2002-October-19 Jason Rohrer * Added ifdef for DEBUG_MEMORY. * * 2002-October-20 Jason Rohrer * Removed file and line arguments from deallocation calls. */ #ifdef DEBUG_MEMORY #include "minorGems/util/development/memory/MemoryTrack.h" #include #include #include int MemoryTrackStaticInitCounter::mCount = 0; MutexLock *MemoryTrack::mLock; AllocationList *MemoryTrack::mListHead; char MemoryTrack::mTracking = false; int MemoryTrack::mTotalAllocationSize = 0; int MemoryTrack::mTotalDeallocationSize = 0; int MemoryTrack::mNumberOfAllocations = 0; void MemoryTrack::addAllocation( void *inPointer, unsigned int inAllocationSize, int inAllocationType, const char *inFileName, int inLineNumber ) { mLock->lock(); if( !mTracking ) { printf( "Tracking off on allocation (0x%x) [%d bytes] %s:%d.\n", (unsigned int)inPointer, inAllocationSize, inFileName, inLineNumber ); mLock->unlock(); return; } // insert after head of list AllocationList *element = (AllocationList *)malloc( sizeof( AllocationList ) ); element->mPrevious = (void *)mListHead; element->mNext = mListHead->mNext; mListHead->mNext = (void *)element; AllocationList *nextElement = (AllocationList *)( element->mNext ); if( nextElement != NULL ) { nextElement->mPrevious = (void *)element; } element->mPointer = inPointer; element->mAllocationSize = inAllocationSize; element->mAllocationType = inAllocationType; element->mFileName = inFileName; element->mLineNumber = inLineNumber; mTotalAllocationSize += inAllocationSize; mNumberOfAllocations ++; // wipe this block of memory clearMemory( inPointer, inAllocationSize ); mLock->unlock(); } int MemoryTrack::addDeallocation( void *inPointer, int inDeallocationType ) { mLock->lock(); if( inPointer == NULL ) { printf( "NULL pointer (0x%x) deallocated\n", (unsigned int)inPointer ); } if( inPointer == (void *)mLock ) { // we're seeing the deallocation of our own static lock as // the system exits // ignore it mLock->unlock(); return 0; } if( !mTracking ) { printf( "Tracking off on deallocation (0x%x)\n", (unsigned int)inPointer ); mLock->unlock(); return 0; } AllocationList *element = (AllocationList *)( mListHead->mNext ); while( element != NULL ) { void *pointer = element->mPointer; if( pointer == inPointer ) { unsigned int allocationSize = element->mAllocationSize; int allocationType = element->mAllocationType; const char *allocFileName = element->mFileName; int allocLineNumber = element->mLineNumber; // remove from list, whether or not types match AllocationList *previousElement = (AllocationList *)( element->mPrevious ); AllocationList *nextElement = (AllocationList *)( element->mNext ); // patch list previousElement->mNext = (void *)( nextElement ); if( nextElement != NULL ) { nextElement->mPrevious = (void *)( previousElement ); } free( element ); mTotalDeallocationSize += allocationSize; if( allocationType == inDeallocationType ) { // found and types match mLock->unlock(); // wipe this block of memory clearMemory( inPointer, allocationSize ); return 0; } else { // allocation types don't match printf( "Attempt to deallocate (0x%x) [%d bytes] with wrong" " delete form\n" " %s:%d (location of original allocation)\n", (unsigned int)inPointer, allocationSize, allocFileName, allocLineNumber ); mLock->unlock(); return 2; } } element = (AllocationList *)( element->mNext ); } // not found (delete of unallocated memory) printf( "Attempt to deallocate (0x%x) unallocated memory\n", (unsigned int)inPointer ); mLock->unlock(); return 1; } void MemoryTrack::printLeaks() { mLock->lock(); printf( "\n\n---- debugMemory report ----\n" ); printf( "Number of Allocations: %d\n", mNumberOfAllocations ); printf( "Total allocations: %d bytes\n", mTotalAllocationSize ); printf( "Total deallocations: %d bytes\n", mTotalDeallocationSize ); int leakEstimate = mTotalAllocationSize - mTotalDeallocationSize; AllocationList *element = (AllocationList *)( mListHead->mNext ); if( element == NULL ) { printf( "No leaks detected.\n" ); } else { printf( "Leaks detected:\n" ); } int leakSum = 0; while( element != NULL ) { printf( "Not deallocated (0x%x) [%d bytes]\n" " %s:%d (location of original allocation)\n", (unsigned int)( element->mPointer ), element->mAllocationSize, element->mFileName, element->mLineNumber ); leakSum += element->mAllocationSize; element = (AllocationList *)( element->mNext ); } if( leakSum != leakEstimate ) { printf( "Warning: Leak sum does not equal leak estimate.\n" ); } printf( "Leaked memory: %d bytes\n", leakSum ); printf( "---- END debugMemory report ----\n\n" ); mLock->unlock(); } void MemoryTrack::clearMemory( void *inPointer, unsigned int inSize ) { unsigned char *charArray = (unsigned char *)inPointer; for( unsigned int i=0; i #include #define SINGLE_ALLOCATION 0 #define ARRAY_ALLOCATION 1 /** * Linked list of memory allocations. * * @author Jason Rohrer */ typedef struct { void *mPrevious; void *mNext; void *mPointer; unsigned int mAllocationSize; int mAllocationType; const char *mFileName; int mLineNumber; } AllocationList; /** * Class that tracks memory allocations and deallocations. * * @author Jason Rohrer */ class MemoryTrack { public: /** * Adds an allocation to this tracker and clears the allocated * memory block. * * @param inPointer a pointer to the allocated memory. * @param inAllocationType the type of allocation, * either SINGLE_ALLOCATION or ARRAY_ALLOCATION. * @param inAllocationSize the size of the allocation in bytes. * @param inFileName the name of the source file in which the * allocation took place. * @param inLineNumber the line number in the source file * on which the allocation took place. */ static void addAllocation( void *inPointer, unsigned int inAllocationSize, int inAllocationType, const char *inFileName, int inLineNumber ); /** * Adds a deallocation to this tracker and clears the block * to be deallocated. * Must be called *before* the memory is deallocated * * @param inPointer a pointer to the memory being deallocated. * @param inDeallocationType the type of deallocation, * either SINGLE_ALLOCATION or ARRAY_ALLOCATION. * @return 0 if the deallocation deallocates * an allocated block of memory, or 1 if it * deallocates a block of memory that is not currently allocated, * and 2 if it is the wrong deallocation type for the specified * block. */ static int addDeallocation( void *inPointer, int inDeallocationType ); /** * Prints a list of all memory leaks (allocations that have never * been deallocated). */ static void printLeaks(); // these are public so initializer can get to them static MutexLock *mLock; // dummy place holder for list head static AllocationList *mListHead; // true if we're tracking static char mTracking; static int mTotalAllocationSize; static int mTotalDeallocationSize; static int mNumberOfAllocations; protected: /** * Clears memory so that reading from it will not produce * anything useful. Good for checking for reads to memory that * has been deallocated. * * @param inPointer pointer to the memory to clear. * @Param inSize the number of bytes to clear starting at inPointer. */ static void clearMemory( void *inPointer, unsigned int inSize ); }; /** * Class that initializes MemoryTrack's static members. * * *All* files that use MemoryTrack will instantiate a static * instance of this class (see static instance below). * * This class counts how many static instantiations have happened so * far, making sure to init/destroy MemoryTrack's static members only once. * * Adapted from: * http://www.hlrs.de/organization/par/services/tools/docu/kcc/ * tutorials/static_initialization.html */ class MemoryTrackStaticInitCounter { public: MemoryTrackStaticInitCounter() { if( mCount == 0 ) { // allocate static members MemoryTrack::mLock = new MutexLock(); MemoryTrack::mListHead = (AllocationList *) malloc( sizeof( AllocationList ) ); MemoryTrack::mListHead->mPrevious = NULL; MemoryTrack::mListHead->mNext = NULL; MemoryTrack::mTotalAllocationSize = 0; MemoryTrack::mTotalDeallocationSize = 0; MemoryTrack::mNumberOfAllocations = 0; MemoryTrack::mTracking = true; } mCount++; } ~MemoryTrackStaticInitCounter() { mCount--; if( mCount == 0 ) { // print leaks... we should only get here after // all static members of classes that use MemoryTrack // have been destroyed. MemoryTrack::printLeaks(); MemoryTrack::mTracking = false; // deallocate static members free( MemoryTrack::mListHead ); delete MemoryTrack::mLock; } } private: // only allocate/deallocate when mCount == 0 static int mCount; }; // This will be included in *every* file that includes MemoryTrack.h static MemoryTrackStaticInitCounter memoryTrackInitializer; #endif primrose-6+dfsg1.orig/minorGems/util/development/memory/testDebugMemory.cpp0000644000175000017500000000267707554421343026071 0ustar pabspabs/* * Modification History * * 2002-October-17 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Added static initialization counting class for MemoryTrack. * * 2002-October-19 Jason Rohrer * Removed call to debugMemoryPrintLeaksAndStopTracking. * Made test cases more interesting. * Added test cases for deleting NULL pointers. */ #include "minorGems/util/development/memory/debugMemory.h" #include class TestClass { public: TestClass() { mX = new int[5]; } ~TestClass() { delete [] mX; } int *mX; }; int main() { int *x = new int[5]; printf( "array contents before initializing elements:\n" "%d, %d, %d, %d, %d\n\n", x[0], x[1], x[2], x[3], x[4] ); x[0] = 1; x[1] = 2; x[2] = 3; x[3] = 4; x[4] = 5; printf( "array contents before deleting:\n" "%d, %d, %d, %d, %d\n\n", x[0], x[1], x[2], x[3], x[4] ); delete [] x; printf( "array contents after deleting:\n" "%d, %d, %d, %d, %d\n\n", x[0], x[1], x[2], x[3], x[4] ); int *y = new int[4]; y[0] = 1; TestClass *t = new TestClass(); delete t; int *z = new int[7]; delete z; //delete t; int *badPointer = NULL; delete badPointer; int *badPointer2 = NULL; delete [] badPointer2; return 0; } primrose-6+dfsg1.orig/minorGems/util/SettingsManager.h0000644000175000017500000002012111145055254021633 0ustar pabspabs/* * Modification History * * 2002-September-16 Jason Rohrer * Created. * Fixed a memory leak. * * 2002-September-25 Jason Rohrer * Added a setSetting function that takes a string value. * * 2002-September-26 Jason Rohrer * Added functions for integer values. * * 2003-August-24 Jason Rohrer * Fixed to remove 499-character limit for a setting value. * * 2009-February-11 Jason Rohrer * Made getSettingsFile public to support arbitry binary data in settings. * * 2009-February-12 Jason Rohrer * Added support for secure hashing. */ #include "minorGems/common.h" #ifndef SETTINGS_MANAGER_INCLUDED #define SETTINGS_MANAGER_INCLUDED #include "minorGems/util/SimpleVector.h" #include "minorGems/system/MutexLock.h" #include // utility class for dealing with static member dealocation class SettingsManagerStaticMembers; /** * Class that manages program settings. * * @author Jason Rohrer */ class SettingsManager { public: /** * Sets the directory name where settings are stored. * * @param inName the name of the directory (relative to the * program's working directory). * Must be destroyed by caller if non-const. */ static void setDirectoryName( char *inName ); /** * Gets the directory name where settings are stored. * * @return the name of the directory (relative to the * program's working directory). * Must be destroyed by caller. */ static char *getDirectoryName(); /** * Sets the salt to be used when hashing settings. * * @param inSalt the salt as an ASCII string. * Must be destroyed by caller if non-const. */ static void setHashSalt( char *inSalt ); /** * Gets the salt to be used when hashing settings. * * @return the hash salt. * Must be destroyed by caller. */ static char *getHashSalt(); /** * Turns hashing on or off. If off, manager will reject * settings in folder that do not have proper hashes. * * @param inOn true to turn hashing on. */ static void setHashingOn( char inOn ); /** * Gets a setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * * @return a vector of strings representing the setting value. * The vector and the strings it contains must be destroyed * by the caller. */ static SimpleVector *getSetting( char *inSettingName ); /** * Gets a string setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * * @return the setting value string, or NULL if no setting * value can be read. * Must be destroyed by caller if non-NULL. */ static char *getStringSetting( char *inSettingName ); /** * Gets a float setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * @param outValueFound pointer to where flag should be returned * indicating whether or not the value was found. * Set to true if the value was found, false otherwise. * * @return the setting value. */ static float getFloatSetting( char *inSettingName, char *outValueFound ); /** * Gets an integer setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * @param outValueFound pointer to where flag should be returned * indicating whether or not the value was found. * Set to true if the value was found, false otherwise. * * @return the setting value. */ static int getIntSetting( char *inSettingName, char *outValueFound ); /** * Sets a setting. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingVector a vector of strings representing the * setting value. * The vector and the strings it contains must be destroyed * by the caller. */ static void setSetting( char *inSettingName, SimpleVector *inSettingVector ); /** * Sets a setting to a single float value. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingValue the value to set. */ static void setSetting( char *inSettingName, float inSettingValue ); /** * Sets a setting to a single int value. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingValue the value to set. */ static void setSetting( char *inSettingName, int inSettingValue ); /** * Sets a setting to a single string value. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingValue the value to set. * Must be destroyed by caller. */ static void setSetting( char *inSettingName, char *inSettingValue ); /** * Gets the file for a setting name. * * @param inSettingName the name of the setting. * Must be destroyed by caller if non-const. * @param inReadWriteFlags the flags to pass into the * fopen call. For example, "r" or "w". * * @return the file descriptor, or NULL if the open failed. * Must be fclose()'d by caller if non-NULL. */ static FILE *getSettingsFile( char *inSettingName, const char *inReadWriteFlags ); protected: static SettingsManagerStaticMembers mStaticMembers; static char mHashingOn; /** * Gets the file name for a setting with the default ini extension. * The .ini extension is added automatically by this call. * * @param inSettingName the name of the setting. * Must be destroyed by caller if non-const. * * @return the name of the settings file. * Must be destroyed by caller. */ static char *getSettingsFileName( char *inSettingName ); /** * Gets the file name for a setting with a custom extension. * The extension should be passed in without a period in it. * * @param inSettingName the name of the setting. * Must be destroyed by caller if non-const. * @param inExtension the extension to add to the name. * Example: "ini" * Must be destroyed by caller if non-const. * * @return the name of the settings file. * Must be destroyed by caller. */ static char *getSettingsFileName( char *inSettingName, char *inExtension ); }; /** * Container for static members to allow for their proper destruction * on program termination. * * @author Jason Rohrer */ class SettingsManagerStaticMembers { public: SettingsManagerStaticMembers(); ~SettingsManagerStaticMembers(); char *mDirectoryName; char *mHashSalt; }; #endif primrose-6+dfsg1.orig/minorGems/util/CircularBuffer.h0000644000175000017500000000614107554101514021444 0ustar pabspabs/* * Modification History * * 2001-Janary-11 Jason Rohrer * Created. * * 2001-Janary-12 Jason Rohrer * Added canRead and canWrite functions. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. */ #include "minorGems/common.h" #ifndef CIRCULAR_BUFFER_INCLUDED #define CIRCULAR_BUFFER_INCLUDED #include "minorGems/system/Semaphore.h" /** * Thread-safe circular buffer. * * @author Jason Rohrer */ class CircularBuffer { public: /** * Constructs a CircularBuffer. * * @param inSize the number of objects in this buffer. */ CircularBuffer( unsigned long inSize ); ~CircularBuffer(); /** * Writes an object into the next free position in the buffer. * Blocks if no free positions are available. * * @param inObject the object pointer to write. */ void writeObject( void *inObject ); /** * Reads the next available object from the buffer. * Blocks if now objects are available. * * @return the object pointer read. */ void *readNextObject(); /** * Returns true if an object can be read from this buffer * without blocking. */ char canRead(); /** * Returns true if an object can be written to this buffer * without blocking. */ char canWrite(); private: unsigned long mBufferSize; void **mObjects; unsigned long mReadIndex, mWriteIndex; // initialized to 0 Semaphore *mReadSemaphore; // initialized to mBufferSize; Semaphore *mWriteSemaphore; MutexLock *mLock; }; inline CircularBuffer::CircularBuffer( unsigned long inSize ) : mBufferSize( inSize ), mObjects( new void*[inSize] ), mReadIndex( 0 ), mWriteIndex( 0 ), mReadSemaphore( new Semaphore( 0 ) ), mWriteSemaphore( new Semaphore( inSize ) ), mLock( new MutexLock() ) { } inline CircularBuffer::~CircularBuffer() { delete [] mObjects; delete mReadSemaphore; delete mWriteSemaphore; delete mLock; } // note that in this implementation, no mutex is needed, since // reader and writer are never accessing the same data members // simultaneously inline void CircularBuffer::writeObject( void *inObject ) { // wait to for a space to write into mWriteSemaphore->wait(); // write, and increment our write location mObjects[ mWriteIndex ] = inObject; mWriteIndex++; mWriteIndex = mWriteIndex % mBufferSize; // signal the reader that an new object is ready mReadSemaphore->signal(); } inline void *CircularBuffer::readNextObject() { void *returnObject; // wait for an object to read mReadSemaphore->wait(); // read the object, and increment our read location returnObject = mObjects[ mReadIndex ]; mReadIndex++; mReadIndex = mReadIndex % mBufferSize; // signal the writer mWriteSemaphore->signal(); // now return the object that we retrieved from the buffer return returnObject; } inline char CircularBuffer::canRead() { // can read if the read semaphore won't block return ! mReadSemaphore->willBlock(); } inline char CircularBuffer::canWrite() { // can write if the write semaphore won't block return ! mWriteSemaphore->willBlock(); } #endif primrose-6+dfsg1.orig/minorGems/util/SettingsManager.cpp0000644000175000017500000002100211145055532022164 0ustar pabspabs/* * Modification History * * 2002-September-16 Jason Rohrer * Created. * Fixed a memory leak. * * 2002-September-25 Jason Rohrer * Added a setSetting function that takes a string value. * * 2002-September-26 Jason Rohrer * Added functions for integer values. * * 2003-January-11 Jason Rohrer * Added default values for float and int settings. * * 2003-August-24 Jason Rohrer * Fixed to remove 499-character limit for a setting value. * * 2009-February-12 Jason Rohrer * Added support for secure hashing. */ #include "SettingsManager.h" #include "minorGems/util/stringUtils.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/Path.h" #include "minorGems/crypto/hashes/sha1.h" // will be destroyed automatically at program termination SettingsManagerStaticMembers SettingsManager::mStaticMembers; char SettingsManager::mHashingOn = false; void SettingsManager::setDirectoryName( char *inName ) { delete [] mStaticMembers.mDirectoryName; mStaticMembers.mDirectoryName = stringDuplicate( inName ); } char *SettingsManager::getDirectoryName() { return stringDuplicate( mStaticMembers.mDirectoryName ); } void SettingsManager::setHashSalt( char *inSalt ) { delete [] mStaticMembers.mHashSalt; mStaticMembers.mHashSalt = stringDuplicate( inSalt ); } char *SettingsManager::getHashSalt() { return stringDuplicate( mStaticMembers.mHashSalt ); } void SettingsManager::setHashingOn( char inOn ) { mHashingOn = inOn; } SimpleVector *SettingsManager::getSetting( char *inSettingName ) { char *fileName = getSettingsFileName( inSettingName ); File *settingsFile = new File( NULL, fileName ); delete [] fileName; char *fileContents = settingsFile->readFileContents(); delete settingsFile; if( fileContents == NULL ) { // return empty vector return new SimpleVector(); } if( mHashingOn ) { char *hashFileName = getSettingsFileName( inSettingName, "hash" ); File *hashFile = new File( NULL, hashFileName ); delete [] hashFileName; char *savedHash = hashFile->readFileContents(); delete hashFile; if( savedHash == NULL ) { printf( "Hash missing for setting %s\n", inSettingName ); delete [] fileContents; return new SimpleVector(); } // compute hash char *stringToHash = autoSprintf( "%s%s", fileContents, mStaticMembers.mHashSalt ); char *hash = computeSHA1Digest( stringToHash ); delete [] stringToHash; int difference = strcmp( hash, savedHash ); delete [] hash; delete [] savedHash; if( difference != 0 ) { printf( "Hash mismatch for setting %s\n", inSettingName ); delete [] fileContents; return new SimpleVector(); } } // else tokenize the file contents SimpleVector *returnVector = tokenizeString( fileContents ); delete [] fileContents; return returnVector; } char *SettingsManager::getStringSetting( char *inSettingName ) { char *value = NULL; SimpleVector *settingsVector = getSetting( inSettingName ); int numStrings = settingsVector->size(); if( numStrings >= 1 ) { char *firstString = *( settingsVector->getElement( 0 ) ); value = stringDuplicate( firstString ); } for( int i=0; igetElement( i ) ); delete [] nextString; } delete settingsVector; return value; } float SettingsManager::getFloatSetting( char *inSettingName, char *outValueFound ) { char valueFound = false; float value = 0; char *stringValue = getStringSetting( inSettingName ); if( stringValue != NULL ) { int numRead = sscanf( stringValue, "%f", &value ); if( numRead == 1 ) { valueFound = true; } delete [] stringValue; } *outValueFound = valueFound; return value; } int SettingsManager::getIntSetting( char *inSettingName, char *outValueFound ) { char valueFound = false; int value = 0; char *stringValue = getStringSetting( inSettingName ); if( stringValue != NULL ) { int numRead = sscanf( stringValue, "%d", &value ); if( numRead == 1 ) { valueFound = true; } delete [] stringValue; } *outValueFound = valueFound; return value; } void SettingsManager::setSetting( char *inSettingName, SimpleVector *inSettingVector ) { char **settingParts = inSettingVector->getElementArray(); char *settingString = join( settingParts, inSettingVector->size(), "\n" ); delete [] settingParts; if( mHashingOn ) { // compute hash char *stringToHash = autoSprintf( "%s%s", settingString, mStaticMembers.mHashSalt ); char *hash = computeSHA1Digest( stringToHash ); delete [] stringToHash; char *hashFileName = getSettingsFileName( inSettingName, "hash" ); FILE *file = fopen( hashFileName, "w" ); delete [] hashFileName; if( file != NULL ) { fprintf( file, "%s", hash ); fclose( file ); } delete [] hash; } FILE *file = getSettingsFile( inSettingName, "w" ); if( file != NULL ) { fprintf( file, "%s", settingString ); fclose( file ); } delete [] settingString; // else do nothing } void SettingsManager::setSetting( char *inSettingName, float inSettingValue ) { char *valueString = new char[ 15 ]; sprintf( valueString, "%f", inSettingValue ); setSetting( inSettingName, valueString ); delete [] valueString; } void SettingsManager::setSetting( char *inSettingName, int inSettingValue ) { char *valueString = new char[ 15 ]; sprintf( valueString, "%d", inSettingValue ); setSetting( inSettingName, valueString ); delete [] valueString; } void SettingsManager::setSetting( char *inSettingName, char *inSettingValue ) { SimpleVector *settingsVector = new SimpleVector( 1 ); settingsVector->push_back( inSettingValue ); setSetting( inSettingName, settingsVector ); delete settingsVector; } FILE *SettingsManager::getSettingsFile( char *inSettingName, const char *inReadWriteFlags ) { char *fullFileName = getSettingsFileName( inSettingName ); FILE *file = fopen( fullFileName, inReadWriteFlags ); delete [] fullFileName; return file; } char *SettingsManager::getSettingsFileName( char *inSettingName ) { return getSettingsFileName( inSettingName, "ini" ); } char *SettingsManager::getSettingsFileName( char *inSettingName, char *inExtension ) { char **pathSteps = new char*[1]; pathSteps[0] = mStaticMembers.mDirectoryName; char *fileName = new char[ strlen( inSettingName ) + strlen( inExtension ) + 2 ]; sprintf( fileName, "%s.%s", inSettingName, inExtension ); File *settingsFile = new File( new Path( pathSteps, 1, false ), fileName ); delete [] fileName; // pathSteps copied internally by Path constructor delete [] pathSteps; char *fullFileName = settingsFile->getFullFileName(); delete settingsFile; return fullFileName; } SettingsManagerStaticMembers::SettingsManagerStaticMembers() : mDirectoryName( stringDuplicate( "settings" ) ), mHashSalt( stringDuplicate( "default_salt" ) ) { } SettingsManagerStaticMembers::~SettingsManagerStaticMembers() { delete [] mDirectoryName; delete [] mHashSalt; } primrose-6+dfsg1.orig/minorGems/util/random/0000755000175000017500000000000011201637600017645 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/util/random/Noise.h0000644000175000017500000000473207554101514021107 0ustar pabspabs// Jason Rohrer // Noise.h /** * * Noise generation interface * * * Created 11-3-99 * Mods: * Jason Rohrer 12-20-2000 Added a fractal noise function * that fills a double array. * */ #include "minorGems/common.h" #ifndef NOISE_INCLUDED #define NOISE_INCLUDED #include #include #include "RandomSource.h" // fills 2d image with RGBA noise void genRandNoise2d(unsigned long *buff, int buffHigh, int buffWide); // returns a random floating point between 0 and 1 inline float floatRand() { float invRandMax = 1 / ((float)RAND_MAX); return (float)(rand()) * invRandMax; } // fills 2d image with ARGB fractal noise void genFractalNoise2d(unsigned long *buff, int buffHigh, int buffWide); /** * Fills a 2d array with 1/f fractal noise. * * @param inBuffer a pre-allocated buffer to fill. * @param inWidth the width and height of the 2d array * contained in the buffer. * Must be a power of 2. * @param inMaxFrequency the maximum frequency of noise modulation to * include, in [2,inWidth]. Lower values produce more "blurry" or * blocky noise. * @param inFPower power to raise F to whene generating noise. * Amplitude of modulation = 1 / (F^inFPower). * @param inInterpolate set to true to perform interpolation of * each frequency modulation. Setting to false produces a "blockier" * noise, while setting to true makes the noise more cloud-like. * @param inRandSource the source to use for random numbers. */ void genFractalNoise2d( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ); /** * Fills a 1d array with 1/f fractal noise. * * @param inBuffer a pre-allocated buffer to fill. * @param inWidth the width of the 2d array * contained in the buffer. * Must be a power of 2. * @param inMaxFrequency the maximum frequency of noise modulation to * include, in [2,inWidth]. Lower values produce more "blurry" or * blocky noise. * @param inFPower power to raise F to whene generating noise. * Amplitude of modulation = 1 / (F^inFPower). * @param inInterpolate set to true to perform interpolation of * each frequency modulation. Setting to false produces a "blockier" * noise, while setting to true makes the noise more cloud-like. * @param inRandSource the source to use for random numbers. */ void genFractalNoise( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ); #endif primrose-6+dfsg1.orig/minorGems/util/random/testRandom.cpp0000644000175000017500000001141311142365151022474 0ustar pabspabs#include "RandomSource.h" #include // perform tests on a random source // tests found here: // NIST FIPS 140-1 U.S. Federal Standard // http://csrc.nist.gov/publications/fips/fips140-1/fips1401.pdf void testRandom( RandomSource *inSource ) { int bitsPerStep = 1; // 20000 bits // must be a multiple of bitsPerStep int numBits = 20000; int numSteps = numBits / bitsPerStep; unsigned int *drawnNumbers = new unsigned int[ numSteps ]; unsigned int *drawnBits = new unsigned int[ numBits ]; unsigned int bitSum = 0; // 1 or 0 when we're in a run unsigned int currentRunType = 2; unsigned int currentRunLength = 0; unsigned int longestRunLength = 0; #define maxRunLengthToTrack 100 unsigned int runLengthCounts[2][ maxRunLengthToTrack ]; int r; for( r=0; rgetRandomBoundedInt( 0, 1 ); //drawnNumbers[i] = inSource->getRandomBoolean(); for( int b=0; b> b & 0x01 ); bitSum += bit; drawnBits[bitIndex] = bit; bitIndex++; if( bit == currentRunType ) { currentRunLength++; if( currentRunLength > longestRunLength ) { longestRunLength = currentRunLength; } } else { // end of run if( currentRunLength > 0 && currentRunLength < maxRunLengthToTrack ) { // count it runLengthCounts[currentRunType][ currentRunLength ] ++; } currentRunType = bit; currentRunLength = 1; } } } float mean = (float)bitSum / numBits; printf( "Mean = %f\n", mean ); float varSum = 0; for( i=0; i 2326 && Z[t] < 2674 ) { } else { failed = true; //printf( "autocorrelation test failed for Z[%d] = %d\n", t, Z[t] ); } } if( !failed ) { printf( "Autocorrelation test passed.\n" ); } delete [] drawnNumbers; delete [] drawnBits; } #include "CustomRandomSource.h" #include "StdRandomSource.h" int main() { CustomRandomSource randSource( 11234258 ); //StdRandomSource randSource( 11 ); testRandom( &randSource ); return 0; } primrose-6+dfsg1.orig/minorGems/util/random/CustomRandomSource.h0000644000175000017500000001146611175630012023622 0ustar pabspabs/* * Modification History * * 2009-January-14 Jason Rohrer * Created. * * 2009-February-5 Jason Rohrer * Added support for restoring from saved state. * */ #ifndef CUSTOM_RANDOM_SOURCE_INCLUDED #define CUSTOM_RANDOM_SOURCE_INCLUDED #include #include #include "RandomSource.h" /** * Implementation of RandomSource that does not depend on platform or library. * * Maintains its own internal state. */ class CustomRandomSource : public RandomSource { public: // seeds itself with current time CustomRandomSource(); // specify the seed CustomRandomSource( unsigned int inSeed ); // save for rewind later void saveState(); void rewindState(); // can be used to save state to disk unsigned int getSavedState(); void restoreFromSavedState( unsigned int inSavedState ); void reseed( unsigned int inSeed ); // implements these functions float getRandomFloat(); // in interval [0,1.0] double getRandomDouble(); // in interval [0,1.0] unsigned int getRandomInt(); // in interval [0,MAX] unsigned int getIntMax(); // returns MAX int getRandomBoundedInt( int inRangeStart, int inRangeEnd ); double getRandomBoundedDouble( double inRangeStart, double inRangeEnd ); char getRandomBoolean(); private: double mInvMAXPlusOne; // 1 / ( MAX + 1 ) unsigned int mState; unsigned int mSavedState; // returns next number and updates state unsigned int genRand32(); }; inline CustomRandomSource::CustomRandomSource() { MAX = 4294967295U; mState = (unsigned)( time(NULL) ); invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (float)MAX ) + 1.0 ); saveState(); } inline CustomRandomSource::CustomRandomSource( unsigned int inSeed ) { MAX = 4294967295U; mState = inSeed; invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (double)MAX ) + 1.0 ); saveState(); } inline void CustomRandomSource::saveState() { mSavedState = mState; } inline void CustomRandomSource::rewindState() { mState = mSavedState; } inline unsigned int CustomRandomSource::getSavedState() { return mSavedState; } inline void CustomRandomSource::restoreFromSavedState( unsigned int inSavedState) { mState = inSavedState; } inline void CustomRandomSource::reseed( unsigned int inSeed ) { mState = inSeed; } // from Cultivation/Passage's landscape.cpp // faster as a set of macros #define CustNum1( inSeed ) \ ( ( inSeed * 0xFEA09B9DU ) + 1 ) #define CustNum2( inSeed ) \ ( ( ( inSeed ^ CustNum1( inSeed ) ) * 0x9C129511U ) + 1 ) #define CustNum3( inSeed ) \ ( ( inSeed * 0x2512CFB8U ) + 1 ) #define CustNum4( inSeed ) \ ( ( ( inSeed ^ CustNum3( inSeed ) ) * 0xB89C8895U ) + 1 ) #define CustNum5( inSeed ) \ ( ( inSeed * 0x6BF962C1U ) + 1 ) #define CustNum6( inSeed ) \ ( ( ( inSeed ^ CustNum5( inSeed ) ) * 0x4BF962C1U ) + 1 ) inline unsigned int CustomRandomSource::genRand32() { mState = CustNum2( mState ) ^ (CustNum4( mState ) >> 11) ^ (CustNum6( mState ) >> 22); return mState; } inline float CustomRandomSource::getRandomFloat() { return (float)(genRand32()) * invMAX; } inline double CustomRandomSource::getRandomDouble() { return (double)(genRand32()) * invDMAX; } inline unsigned int CustomRandomSource::getRandomInt() { return genRand32(); } inline unsigned int CustomRandomSource::getIntMax() { return MAX; } inline int CustomRandomSource::getRandomBoundedInt( int inRangeStart, int inRangeEnd ) { // float in range [0,1) double randFloat = (double)( genRand32() ) * mInvMAXPlusOne; int onePastRange = inRangeEnd + 1; int magnitude = (int)( randFloat * ( onePastRange - inRangeStart ) ); return magnitude + inRangeStart; } inline double CustomRandomSource::getRandomBoundedDouble( double inRangeStart, double inRangeEnd ) { // double in range [0,1] double randDouble = getRandomDouble(); double magnitude = randDouble * ( inRangeEnd - inRangeStart ); return magnitude + inRangeStart; } inline char CustomRandomSource::getRandomBoolean() { // float in range [0,1] double randFloat = getRandomFloat(); if( randFloat < 0.5 ) { return true; } else { return false; } } #endif primrose-6+dfsg1.orig/minorGems/util/random/RandomSource.h0000644000175000017500000000401411133471650022423 0ustar pabspabs// Jason Rohrer // RandomSource.h /** * * abstract interface for random number generation * * Can be implemented by: * --stdlib rand() function calls * --seed file full of random numbers * * Created 12-7-99 * Mods: * Jason Rohrer 9-28-2000 Added a getRandomBoundedInt() * interface to faciliate retrieving * an integer in a given range [a,b] * where each integer in the range * has the same probability of being * returned. * Jason Rohrer 12-16-2000 Added a getRandomDouble() interface. * Jason Rohrer 11-21-2005 Added a virtual destructor. * Jason Rohrer 07-09-2006 Added a getRandomBoundedDouble interface. * Jason Rohrer 07-27-2006 Added a getRandomBoolean interface. */ #include "minorGems/common.h" #ifndef RANDOM_SOURCE_INCLUDED #define RANDOM_SOURCE_INCLUDED class RandomSource { public: // pure virtual functions implemented by inheriting classes virtual float getRandomFloat() = 0; // in interval [0,1.0] virtual double getRandomDouble() = 0; // in interval [0,1.0] virtual unsigned int getRandomInt() = 0; // in interval [0,MAX] virtual unsigned int getIntMax() = 0; // returns MAX /** * Returns a random integer in [rangeStart,rangeEnd] * where each integer in the range has an equal * probability of occuring. */ virtual int getRandomBoundedInt( int inRangeStart, int inRangeEnd ) = 0; /** * Returns a random double in [rangeStart,rangeEnd]. */ virtual double getRandomBoundedDouble( double inRangeStart, double inRangeEnd ) = 0; /** * Gets a random true/false value. */ virtual char getRandomBoolean() = 0; virtual ~RandomSource(); protected: unsigned int MAX; // maximum integer random number float invMAX; // floating point inverse of MAX double invDMAX; // double invers of MAX }; inline RandomSource::~RandomSource() { // does nothing // exists to ensure that subclass destructors are called } #endif primrose-6+dfsg1.orig/minorGems/util/random/StdRandomSource.h0000644000175000017500000000641311133471650023103 0ustar pabspabs// Jason Rohrer // StdRandomSource.h /** * * Implementation of random number generation that uses stdlib calls * * * Created 12-7-99 * Mods: * Jason Rohrer 9-28-2000 Added a getRandomBoundedInt() * implementation * Jason Rohrer 12-7-2000 Overloaded constructor to support * specifying a seed. * Jason Rohrer 12-16-2000 Added a getRandomDouble() function. * Jason Rohrer 12-17-2000 Fixed bug in initialization of invDMAX * in default constructor. * Jason Rohrer 9-13-2001 Fixed a bug in getRandomBoundedInt() * as floats were being used, and they * don't provide enough resolution. * Jason Rohrer 10-11-2002 Fixed some type casting warnings. * Jason Rohrer 07-09-2006 Added getRandomBoundedDouble. * Jason Rohrer 07-27-2006 Added getRandomBoolean. */ #include "minorGems/common.h" #ifndef STD_RANDOM_SOURCE_INCLUDED #define STD_RANDOM_SOURCE_INCLUDED #include #include #include "RandomSource.h" class StdRandomSource : public RandomSource { public: StdRandomSource(); // needed to seed stdlib generator // specify the seed for the stdlib generator StdRandomSource( unsigned int inSeed ); // implements these functions float getRandomFloat(); // in interval [0,1.0] double getRandomDouble(); // in interval [0,1.0] unsigned int getRandomInt(); // in interval [0,MAX] unsigned int getIntMax(); // returns MAX int getRandomBoundedInt( int inRangeStart, int inRangeEnd ); double getRandomBoundedDouble( double inRangeStart, double inRangeEnd ); char getRandomBoolean(); private: double mInvMAXPlusOne; // 1 / ( MAX + 1 ) }; inline StdRandomSource::StdRandomSource() { MAX = RAND_MAX; srand( (unsigned)time(NULL) ); invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (float)MAX ) + 1.0 ); } inline StdRandomSource::StdRandomSource( unsigned int inSeed ) { MAX = RAND_MAX; srand( inSeed ); invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (double)MAX ) + 1.0 ); } inline float StdRandomSource::getRandomFloat() { return (float)(rand()) * invMAX; } inline double StdRandomSource::getRandomDouble() { return (double)(rand()) * invDMAX; } inline unsigned int StdRandomSource::getRandomInt() { return rand(); } inline unsigned int StdRandomSource::getIntMax() { return MAX; } inline int StdRandomSource::getRandomBoundedInt( int inRangeStart, int inRangeEnd ) { // float in range [0,1) double randFloat = (double)( rand() ) * mInvMAXPlusOne; int onePastRange = inRangeEnd + 1; int magnitude = (int)( randFloat * ( onePastRange - inRangeStart ) ); return magnitude + inRangeStart; } inline double StdRandomSource::getRandomBoundedDouble( double inRangeStart, double inRangeEnd ) { // double in range [0,1] double randDouble = getRandomDouble(); double magnitude = randDouble * ( inRangeEnd - inRangeStart ); return magnitude + inRangeStart; } inline char StdRandomSource::getRandomBoolean() { // float in range [0,1] double randFloat = getRandomFloat(); if( randFloat < 0.5 ) { return true; } else { return false; } } #endif primrose-6+dfsg1.orig/minorGems/util/random/Noise.cpp0000644000175000017500000001625407220517221021440 0ustar pabspabs// Jason Rohrer // Noise.cpp /** * * Noise generation implementation * * * Created 11-3-99 * Mods: * Jason Rohrer 12-20-2000 Changed genFractalNoise2d function to make * it less blocky. * */ #include "Noise.h" // fills 2d image with ARGB noise void genRandNoise2d(unsigned long *buff, int buffHigh, int buffWide) { int *yOffset = new int[buffHigh]; // precalc y offsets for( int y=0; y> 24 & 0xFF) + alpha; int buffRed = (buffARGB >> 16 & 0xFF) + red; int buffGreen = (buffARGB >> 8 & 0xFF) + green; int buffBlue = (buffARGB & 0xFF) + blue; if( buffAlpha < 0) buffAlpha = 0; if( buffRed < 0) buffRed = 0; if( buffGreen < 0) buffGreen = 0; if( buffBlue < 0) buffBlue = 0; if( buffAlpha > 255) buffAlpha = 255; if( buffRed > 255) buffRed = 255; if( buffGreen > 255) buffGreen = 255; if( buffBlue > 255) buffBlue = 255; buff[ yOffset[buffY] + buffX] = buffBlue | buffGreen << 8 | buffRed << 16 | buffAlpha << 24; buffX++; blockX++; if( buffX >= buffWide ) blockX = blockWide; // if this block hangs outside buffer } buffY++; blockY++; if( buffY >= buffHigh ) blockY = blockHigh; // if this block hangs outside buffer } buffX = startX + blockWide; } buffY = startY + blockHigh; } } delete [] yOffset; } void genFractalNoise2d( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ) { RandomSource *r = inRandSource; int w = inWidth; int i, x, y, f; int numPoints = w * w; // first, fill surface with a uniform 0.5 value for( i=0; igetRandomDouble() - 1 ) * weight; } // now walk though 2d array and perform // bilinear interpolation between blocks for( y=0; y 1.0 ) { inBuffer[y * w + x] = 1.0; } else if( inBuffer[y * w + x] < 0.0 ) { inBuffer[y * w + x] = 0.0; } } } delete [] blockValues; } } void genFractalNoise( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ) { RandomSource *r = inRandSource; int w = inWidth; int i, x, f; // first, fill array with uniform 0.5 values for( i=0; igetRandomDouble() - 1 ) * weight; } // now walk though array and perform linear interpolation between blocks for( x=0; x 1.0 ) { inBuffer[x] = 1.0; } else if( inBuffer[x] < 0.0 ) { inBuffer[x] = 0.0; } } delete [] blockValues; } } primrose-6+dfsg1.orig/minorGems/util/stringUtils.h0000644000175000017500000002125510440046700021071 0ustar pabspabs/* * Modification History * * 2002-April-6 Jason Rohrer * Created. * * 2002-April-8 Jason Rohrer * Fixed multiple inclusion bug * * 2002-May-7 Jason Rohrer * Added functions for case-insensitive substring finding and case * conversion. * * 2002-May-9 Jason Rohrer * Fixed a bug when string not found. * * 2002-May-26 Jason Rohrer * Added a function for string comparison ignoring cases. * * 2003-March-28 Jason Rohrer * Added split function. * * 2003-May-1 Jason Rohrer * Added replacement functions. * * 2003-May-4 Jason Rohrer * Added list replacement function. * * 2003-May-10 Jason Rohrer * Moved implementations into a .cpp file. This will break several * projects. * Added a tokenization function. * * 2003-June-14 Jason Rohrer * Added a join function. * * 2003-June-22 Jason Rohrer * Added an autoSprintf function. * * 2003-August-12 Jason Rohrer * Added a concatonate function. * * 2003-September-7 Jason Rohrer * Improved split comment. * * 2006-June-2 Jason Rohrer * Added a stringStartsWith function. */ #include "minorGems/common.h" #include "minorGems/util/SimpleVector.h" #ifndef STRING_UTILS_INCLUDED #define STRING_UTILS_INCLUDED // ANSI does not support strdup, strcasestr, or strcasecmp #include #include #include /** * Duplicates a string into a newly allocated string. * * @param inString the \0-terminated string to duplicate. * Must be destroyed by caller if non-const. * * @return a \0-terminated duplicate of inString. * Must be destroyed by caller. */ inline char *stringDuplicate( const char *inString ) { char *returnBuffer = new char[ strlen( inString ) + 1 ]; strcpy( returnBuffer, inString ); return returnBuffer; } /** * Converts a string to lower case. * * @param inString the \0-terminated string to convert. * Must be destroyed by caller if non-const. * * @return a newly allocated \0-terminated string * that is a lowercase version of inString. * Must be destroyed by caller. */ char *stringToLowerCase( const char *inString ); /** * Searches for the first occurrence of one string in another. * * @param inHaystack the \0-terminated string to search in. * Must be destroyed by caller if non-const. * @param inNeedle the \0-terminated string to search for. * Must be destroyed by caller if non-const. * * @return a string pointer into inHaystack where the * first occurrence of inNeedle starts, or NULL if inNeedle is not found. */ char *stringLocateIgnoreCase( const char *inHaystack, const char *inNeedle ); /** * Compares two strings, ignoring case. * * @param inStringA the first \0-terminated string. * Must be destroyed by caller if non-const. * @param inStringB the second \0-terminated string. * Must be destroyed by caller if non-const. * * @return an integer less than, equal to, or greater than zero if * inStringA is found, respectively, to be less than, to match, or be * greater than inStringB. */ int stringCompareIgnoreCase( const char *inStringA, const char *inStringB ); /** * Checks if a string starts with a given prefix string. * * @param inString a \0-terminated string. * Must be destroyed by caller if non-const. * @param inPrefix the prefix to look for as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return true if inString begins with inPrefix, or false otherwise. */ char stringStartsWith( const char *inString, const char *inPrefix ); /** * Splits a string into parts around a separator string. * * Note that splitting strings that start and/or end with the separator * results in "empty" strings being returned at the start and/or end * of the parts array. * * For example, splitting "a#short#test" around the "#" separator will * result in the array { "a", "short", "test" }, but splitting * "#another#short#test#" will result in the array * { "", "another", "short", "test", "" }. * * This differs somewhat from the perl version of split, but it gives the * caller more information about the string being split. * * @param inString the string to split. * Must be destroyed by caller if non-const. * @param inSeparator the separator string. * Must be destroyed by caller if non-const. * @param outNumParts pointer to where the the number of parts (the length of * the returned array) should be returned. * * @return an array of split parts. * Must be destroyed by caller. */ char **split( char *inString, char *inSeparator, int *outNumParts ); /** * Joins a collection of strings using a separator string. * * @param inStrings the strings to join. * Array and strings must be destroyed by caller. * @param inNumParts the number of strings to join. * @param inSeparator the separator string. * Must be destroyed by caller if non-const. * * @return the joined string. * Must be destroyed by caller. */ char *join( char **inStrings, int inNumParts, char *inGlue ); /** * Concatonates two strings. * * @param inStringA the first string in the concatonation. * Must be destroyed by caller if non-const. * @param inStringB the second string in the concatonation. * Must be destroyed by caller if non-const. * * @return the concatonation. * Must be destroyed by caller. */ char *concatonate( char *inStringA, char *inStringB ); /** * Replaces the first occurrence of a target string with * a substitute string. * * All parameters and return value must be destroyed by caller. * * @param inHaystack the string to search for inTarget in. * @param inTarget the string to search for. * @param inSubstitute the string to replace the first occurrence * of the target with. * @param outFound a pre-allocated character which will be filled * with true if the target is found, and filled with false * otherwise. * * @return a newly allocated string with the substitution performed. */ char *replaceOnce( char *inHaystack, char *inTarget, char *inSubstitute, char *outFound ); /** * Replaces the all occurrences of a target string with * a substitute string. * * Note that this function is not self-insertion-safe: * If inSubstitute contains inTarget, this function will * enter an infinite loop. * * All parameters and return value must be destroyed by caller. * * @param inHaystack the string to search for inTarget in. * @param inTarget the string to search for. * @param inSubstitute the string to replace the all occurrences * of the target with. * @param outFound a pre-allocated character which will be filled * with true if the target is found at least once, * and filled with false otherwise. * * @return a newly allocated string with the substitutions performed. */ char *replaceAll( char *inHaystack, char *inTarget, char *inSubstitute, char *outFound ); /** * Replaces the all occurrences of each target string on a list with * a corresponding substitute string. * * Note that this function is not self-insertion-safe: * If inSubstituteVector contains elements from inTargetVector, * this function will enter an infinite loop. * * All parameters and return value must be destroyed by caller. * * @param inHaystack the string to search for targets in. * @param inTargetVector the list of strings to search for. * Vector and contained strings must be destroyed by caller. * @param inSubstituteVector the corresponding list of strings to * replace the all occurrences of the targets with. * Vector and contained strings must be destroyed by caller. * * @return a newly allocated string with the substitutions performed. */ char *replaceTargetListWithSubstituteList( char *inHaystack, SimpleVector *inTargetVector, SimpleVector *inSubstituteVector ); /** * Split a string into tokens using whitespace as separators. * * @param inString the string to tokenize. * Must be destroyed by caller. * * @return a vector of extracted strings. * Vector and strings must be destroyed by caller. */ SimpleVector *tokenizeString( char *inString ); /** * Prints formatted data elements into a newly allocated string buffer. * * Similar to sprintf, except that buffer sizing is automatic (and therefore * safer than manual sizing). * * @param inFormatString the format string to print from. * @param variable argument list data values to fill in the format string * with (uses same conventions as printf). * * @return a newly allocated buffer containing the \0-terminated printed * string. * Must be destroyed by caller. */ char *autoSprintf( const char* inFormatString, ... ); #endif primrose-6+dfsg1.orig/minorGems/util/log/0000755000175000017500000000000011201637600017146 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/util/log/PrintLog.h0000644000175000017500000000326407554101514021070 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-April-8 Jason Rohrer * Changed to be thread-safe. */ #include "minorGems/common.h" #ifndef PRINT_LOG_INCLUDED #define PRINT_LOG_INCLUDED #include "Log.h" #include "minorGems/system/MutexLock.h" /** * A console-based implementation of the Log interface. * * @author Jason Rohrer */ class PrintLog : public Log { public: /** * Constructs a print log. */ PrintLog(); virtual ~PrintLog(); // implement the Log interface virtual void setLoggingLevel( int inLevel ); virtual int getLoggingLevel(); virtual void logString( char *inString, int inLevel ); virtual void logString( char *inLoggerName, char *inString, int inLevel ); protected: int mLoggingLevel; static const char *mDefaultLoggerName; MutexLock *mLock; /** * Generates a string representation of a log message. * * @param inLoggerName the name of the logger * as a \0-terminated string. * Must be destroyed by caller. * @param inString the string to log as a \0-terminated string. * Must be destroyed by caller. * @param inLevel the level to log inString at. * * @return the log message as a \0-terminated string. * Must be destroyed by caller. */ char *generateLogMessage( char *inLoggerName, char *inString, int inLevel ); }; #endif primrose-6+dfsg1.orig/minorGems/util/log/AppLog.h0000644000175000017500000000661007554101514020512 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-30 Jason Rohrer * Wrapped our dynamically allocated static member in a statically * allocated class to avoid memory leaks at program termination. */ #include "minorGems/common.h" #ifndef APP_LOG_INCLUDED #define APP_LOG_INCLUDED #include "Log.h" #include "PrintLog.h" // internally used class class LogPointerWrapper; /** * A singleton wrapper for implementations of the Log interface. * * This class should be the interface for log-access for applications. * * @author Jason Rohrer */ class AppLog { public: /** * These log errors at various levels. * * All char* parameters must be \0-terminated and destroyed by caller. */ static void criticalError( char *inString ); static void criticalError( char *inLoggerName, char *inString ); static void error( char *inString ); static void error( char *inLoggerName, char *inString ); static void warning( char *inString ); static void warning( char *inLoggerName, char *inString ); static void info( char *inString ); static void info( char *inLoggerName, char *inString ); static void detail( char *inString ); static void detail( char *inLoggerName, char *inString ); static void trace( char *inString ); static void trace( char *inLoggerName, char *inString ); /** * Sets the log to use. * Note that this call destroys the current log. * * @param inLog the log to use. * Will be destroyed by this class. */ static void setLog( Log *inLog ); /** * Gets the log being used. * * @return the log being used. * Will be destroyed by this class. */ static Log *getLog(); /** * Sets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @param inLevel one of the defined logging levels. */ static void setLoggingLevel( int inLevel ); /** * Gets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @return one of the defined logging levels. */ static int getLoggingLevel(); protected: // note that all static objects // are destroyed at program termination //static Log *mLog; static LogPointerWrapper mLogPointerWrapper; }; /** * Wrapper for static member pointer to ensure * deletion of static member object at program termination. */ class LogPointerWrapper { public: /** * Constructor allows specification of the object * to wrap and destroy at program termination. * * @param inLog the log object to wrap. * Will be destroyed at program termination if non-NULL. */ LogPointerWrapper( Log *inLog ); /** * Destructor will get called at program termination * if the object is statically allocated. */ ~LogPointerWrapper(); Log *mLog; }; #endif primrose-6+dfsg1.orig/minorGems/util/log/FileLog.h0000644000175000017500000000337707561776211020672 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-November-5 Jason Rohrer * Added support for backing up logs and deleting old log data. */ #include "minorGems/common.h" #ifndef FILE_LOG_INCLUDED #define FILE_LOG_INCLUDED #include "PrintLog.h" #include /** * A file-based implementation of the Log interface. * * @author Jason Rohrer */ class FileLog : public PrintLog { public: /** * Constructs a file log. * * @param inFileName the name of the file to write log messages to. * Must be destroyed by caller. * @param inSecondsBetweenBackups the number of seconds to wait * before making a backup of the current log file (deleting any * old backups), clearing the current log file, and starting * a fresh log in the current log file. Defaults to 3600 * seconds (one hour). Backup logs are saved to inFileName.bakup */ FileLog( char *inFileName, unsigned long inSecondsBetweenBackups = 3600 ); virtual ~FileLog(); /** * Makes a backup of the current log file, deletes old backups, * and clears the current log file. */ void makeBackup(); // overrides PrintLog::logString virtual void logString( char *inLoggerName, char *inString, int inLevel ); protected: FILE *mLogFile; char *mLogFileName; unsigned long mSecondsBetweenBackups; unsigned long mTimeOfLastBackup; static const char *mDefaultLogFileName; }; #endif primrose-6+dfsg1.orig/minorGems/util/log/Makefile0000644000175000017500000000235707436570640020634 0ustar pabspabs# # Modification History # # 2002-February-25 Jason Rohrer # Created. # Changed to be more succinct. # GXX=g++ ROOT_PATH = ../../.. DEBUG_ON_FLAG = -g DEBUG_OFF_FLAG = DEBUG_FLAG = ${DEBUG_OFF_FLAG} TIME_PLATFORM_PATH = unix TIME_PLATFORM = Unix TIME_O = ${ROOT_PATH}/minorGems/system/${TIME_PLATFORM_PATH}/Time${TIME_PLATFORM}.o TIME_H = ${ROOT_PATH}/minorGems/system/Time.h TIME_CPP = ${ROOT_PATH}/minorGems/system/${TIME_PLATFORM_PATH}/Time${TIME_PLATFORM}.cpp testLog: AppLog.o FileLog.o PrintLog.o Log.o testLog.o ${TIME_O} ${GXX} ${DEBUG_FLAG} -o testLog AppLog.o FileLog.o PrintLog.o Log.o testLog.o ${TIME_O} clean: rm -f *.o ${TIME_O} testLog.o: testLog.cpp AppLog.h FileLog.h Log.h ${GXX} ${DEBUG_FLAG} -o testLog.o -c testLog.cpp AppLog.o: AppLog.h AppLog.cpp Log.h PrintLog.h ${GXX} ${DEBUG_FLAG} -o AppLog.o -c AppLog.cpp PrintLog.o: PrintLog.h PrintLog.cpp Log.h PrintLog.h ${TIME_H} ${GXX} ${DEBUG_FLAG} -I${ROOT_PATH} -o PrintLog.o -c PrintLog.cpp FileLog.o: PrintLog.h FileLog.cpp FileLog.h Log.h ${GXX} ${DEBUG_FLAG} -o FileLog.o -c FileLog.cpp Log.o: Log.h Log.cpp ${GXX} ${DEBUG_FLAG} -o Log.o -c Log.cpp ${TIME_O}: ${TIME_H} ${TIME_CPP} ${GXX} ${DEBUG_FLAG} -I${ROOT_PATH} -o ${TIME_O} -c ${TIME_CPP} primrose-6+dfsg1.orig/minorGems/util/log/FileLog.cpp0000644000175000017500000000576607561776211021231 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-13 Jason Rohrer * Added a flush after every write. * * 2002-April-8 Jason Rohrer * Changed to be thread-safe. * * 2002-November-5 Jason Rohrer * Added support for backing up logs and deleting old log data. */ #include "FileLog.h" #include "PrintLog.h" #include "minorGems/util/stringUtils.h" #include "minorGems/io/file/File.h" #include #include const char *FileLog::mDefaultLogFileName = "default.log"; FileLog::FileLog( char *inFileName, unsigned long inSecondsBetweenBackups ) : mLogFile( NULL ), mLogFileName( stringDuplicate( inFileName ) ), mSecondsBetweenBackups( inSecondsBetweenBackups ), mTimeOfLastBackup( time( NULL ) ) { mLogFile = fopen( mLogFileName, "a" ); if( mLogFile == NULL ) { printf( "Log file %s failed to open.\n", mLogFileName ); printf( "Writing log to default file: %s\n", mDefaultLogFileName ); // switch to default log file name delete [] mLogFileName; mLogFileName = stringDuplicate( mDefaultLogFileName ); mLogFile = fopen( mLogFileName, "a" ); if( mLogFile == NULL ) { printf( "Default log file %s failed to open.\n", mLogFileName ); } } } FileLog::~FileLog() { if( mLogFile != NULL ) { fclose( mLogFile ); } delete [] mLogFileName; } void FileLog::logString( char *inLoggerName, char *inString, int inLevel ) { if( mLogFile != NULL ) { if( inLevel <= mLoggingLevel ) { char *message = PrintLog::generateLogMessage( inLoggerName, inString, inLevel ); mLock->lock(); fprintf( mLogFile, "%s\n", message ); fflush( mLogFile ); if( time( NULL ) - mTimeOfLastBackup > mSecondsBetweenBackups ) { makeBackup(); } mLock->unlock(); delete [] message; } } } void FileLog::makeBackup() { fclose( mLogFile ); File *currentLogFile = new File( NULL, mLogFileName ); char *backupFileName = new char[ strlen( mLogFileName ) + 10 ]; sprintf( backupFileName, "%s.backup", mLogFileName ); File *backupLogFile = new File( NULL, backupFileName ); delete [] backupFileName; // copy into backup log file, which will overwrite it currentLogFile->copy( backupLogFile ); delete currentLogFile; delete backupLogFile; // clear main log file and start writing to it again mLogFile = fopen( mLogFileName, "w" ); if( mLogFile == NULL ) { printf( "Log file %s failed to open.\n", mLogFileName ); } mTimeOfLastBackup = time( NULL ); } primrose-6+dfsg1.orig/minorGems/util/log/AppLog.cpp0000644000175000017500000000553507451444376021066 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-30 Jason Rohrer * Wrapped our dynamically allocated static member in a statically * allocated class to avoid memory leaks at program termination. */ #include "AppLog.h" #include "Log.h" #include // wrap our static member in a statically allocated class LogPointerWrapper AppLog::mLogPointerWrapper( new PrintLog ); LogPointerWrapper::LogPointerWrapper( Log *inLog ) : mLog( inLog ) { } LogPointerWrapper::~LogPointerWrapper() { if( mLog != NULL ) { delete mLog; } } void AppLog::criticalError( char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::CRITICAL_ERROR_LEVEL ); } void AppLog::criticalError( char *inLoggerName, char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::CRITICAL_ERROR_LEVEL ); } void AppLog::error( char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::ERROR_LEVEL ); } void AppLog::error( char *inLoggerName, char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::ERROR_LEVEL ); } void AppLog::warning( char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::WARNING_LEVEL ); } void AppLog::warning( char *inLoggerName, char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::WARNING_LEVEL ); } void AppLog::info( char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::INFO_LEVEL ); } void AppLog::info( char *inLoggerName, char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::INFO_LEVEL ); } void AppLog::detail( char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::DETAIL_LEVEL ); } void AppLog::detail( char *inLoggerName, char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::DETAIL_LEVEL ); } void AppLog::trace( char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::TRACE_LEVEL ); } void AppLog::trace( char *inLoggerName, char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::TRACE_LEVEL ); } void AppLog::setLog( Log *inLog ) { int currentLoggingLevel = getLoggingLevel(); if( inLog != mLogPointerWrapper.mLog ) { delete mLogPointerWrapper.mLog; } mLogPointerWrapper.mLog = inLog; setLoggingLevel( currentLoggingLevel ); } Log *AppLog::getLog() { return mLogPointerWrapper.mLog; } void AppLog::setLoggingLevel( int inLevel ) { mLogPointerWrapper.mLog->setLoggingLevel( inLevel ); } int AppLog::getLoggingLevel() { return mLogPointerWrapper.mLog->getLoggingLevel(); } primrose-6+dfsg1.orig/minorGems/util/log/Log.cpp0000644000175000017500000000057107436570021020406 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. */ #include "Log.h" const int Log::DEACTIVATE_LEVEL = 0; const int Log::CRITICAL_ERROR_LEVEL = 1; const int Log::ERROR_LEVEL = 2; const int Log::WARNING_LEVEL = 3; const int Log::INFO_LEVEL = 4; const int Log::DETAIL_LEVEL = 5; const int Log::TRACE_LEVEL = 6; Log::~Log() { } primrose-6+dfsg1.orig/minorGems/util/log/PrintLog.cpp0000644000175000017500000000615010006200435021404 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-11 Jason Rohrer * Added a missing include. * * 2002-April-8 Jason Rohrer * Fixed a casting, dereferencing Win32 compile bug. * Changed to be thread-safe. * Changed to use thread-safe printing function. * * 2002-April-8 Jason Rohrer * Fixed a signed-unsigned mismatch. * * 2004-January-11 Jason Rohrer * Added lock around asctime call. * Increased scope of lock. * * 2004-January-29 Jason Rohrer * Changed to use ctime instead of localtime and asctime. * Improved locking scope. * Changed to use autoSprintf. */ #include "PrintLog.h" #include "minorGems/system/Time.h" #include "minorGems/util/printUtils.h" #include "minorGems/util/stringUtils.h" #include #include #include const char *PrintLog::mDefaultLoggerName = "general"; PrintLog::PrintLog() : mLoggingLevel( Log::TRACE_LEVEL ), mLock( new MutexLock() ) { } PrintLog::~PrintLog() { delete mLock; } void PrintLog::setLoggingLevel( int inLevel ) { mLock->lock(); mLoggingLevel = inLevel; mLock->unlock(); } int PrintLog::getLoggingLevel() { mLock->lock(); int level = mLoggingLevel; mLock->unlock(); return level; } void PrintLog::logString( char *inString, int inLevel ) { logString( (char *)mDefaultLoggerName, inString, inLevel ); } void PrintLog::logString( char *inLoggerName, char *inString, int inLevel ) { // not thread-safe to read mLoggingLevel here // without synchronization. // However, we want logging calls that are above // our level to execute with nearly no overhead. // mutex might be too much overhead.... // Besides, not being thread-safe in this case might // (worst case) result in a missed log entry or // an extra log entry... but setting the logging level should be rare. if( inLevel <= mLoggingLevel ) { char *message = generateLogMessage( inLoggerName, inString, inLevel ); threadPrintF( "%s\n", message ); delete [] message; } } char *PrintLog::generateLogMessage( char *inLoggerName, char *inString, int inLevel ) { unsigned long seconds, milliseconds; Time::getCurrentTime( &seconds, &milliseconds ); // lock around ctime call, since it returns a static buffer mLock->lock(); char *dateString = stringDuplicate( ctime( (time_t *)( &seconds ) ) ); // done with static buffer, since we made a copy mLock->unlock(); // this date string ends with a newline... // get rid of it dateString[ strlen(dateString) - 1 ] = '\0'; char *messageBuffer = autoSprintf( "L%d | %s (%ld ms) | %s | %s", inLevel, dateString, milliseconds, inLoggerName, inString ); delete [] dateString; return messageBuffer; } primrose-6+dfsg1.orig/minorGems/util/log/testLog.cpp0000644000175000017500000000147207436570021021307 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. */ #include "AppLog.h" #include "FileLog.h" #include "Log.h" int main() { AppLog::warning( "A test warning" ); AppLog::warning( "Another test warning" ); AppLog::warning( "mainApp", "And Another test warning" ); AppLog::setLoggingLevel( Log::ERROR_LEVEL ); AppLog::warning( "Yet Another test warning" ); AppLog::error( "mainApp", "A test error" ); AppLog::setLog( new FileLog( "test.log" ) ); // this should be skipped AppLog::warning( "A second test warning" ); // this should not be AppLog::criticalError( "A critical error" ); AppLog::setLog( new FileLog( "test2.log" ) ); // this should be skipped AppLog::warning( "A third test warning" ); return 0; } primrose-6+dfsg1.orig/minorGems/util/log/Log.h0000644000175000017500000000457107554101514020055 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. */ #include "minorGems/common.h" #ifndef LOG_INCLUDED #define LOG_INCLUDED #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * An interface for a class that can perform logging functions. * * @author Jason Rohrer */ class Log { public: // These levels were copied from the JLog framework // by Todd Lauinger static const int DEACTIVATE_LEVEL; static const int CRITICAL_ERROR_LEVEL; static const int ERROR_LEVEL; static const int WARNING_LEVEL; static const int INFO_LEVEL; static const int DETAIL_LEVEL; static const int TRACE_LEVEL; // provided so that virtual deletes work properly virtual ~Log(); /** * Sets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @param inLevel one of the defined logging levels. */ virtual void setLoggingLevel( int inLevel ) = 0; /** * Gets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @return one of the defined logging levels. */ virtual int getLoggingLevel() = 0; /** * Logs a string in this log under the default logger name. * * @param inString the string to log as a \0-terminated string. * Must be destroyed by caller. * @param inLevel the level to log inString at. */ virtual void logString( char *inString, int inLevel ) = 0; /** * Logs a string in this log, specifying a logger name. * * @param inLoggerName the name of the logger * as a \0-terminated string. * Must be destroyed by caller. * @param inString the string to log as a \0-terminated string. * Must be destroyed by caller. * @param inLevel the level to log inString at. */ virtual void logString( char *inLoggerName, char *inString, int inLevel ) = 0; }; #endif primrose-6+dfsg1.orig/minorGems/util/StringBufferOutputStream.h0000644000175000017500000000277210047451312023544 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. * * 2004-May-9 Jason Rohrer * Added function for getting data as a byte array. */ #include "minorGems/common.h" #ifndef STRING_BUFFER_OUTPUT_STREAM_INCLUDED #define STRING_BUFFER_OUTPUT_STREAM_INCLUDED #include "minorGems/util/SimpleVector.h" #include "minorGems/io/OutputStream.h" /** * An output stream that fills a string buffer. * * @author Jason Rohrer */ class StringBufferOutputStream : public OutputStream { public: StringBufferOutputStream(); ~StringBufferOutputStream(); /** * Gets the data writen to this stream since construction as a * \0-terminated string. * * @return a string containing all data written to this stream. * Must be destroyed by caller. */ char *getString(); /** * Gets the data writen to this stream since construction as a * byte array. * * @param outNumBytes pointer to where the array length should be * returned. * * @return an array containingdata written to this stream. * Must be destroyed by caller. */ unsigned char *getBytes( int *outNumBytes ); // implements the OutputStream interface long write( unsigned char *inBuffer, long inNumBytes ); protected: SimpleVector *mCharacterVector; }; #endif primrose-6+dfsg1.orig/minorGems/util/TranslationManager.cpp0000644000175000017500000002126010376100124022661 0ustar pabspabs/* * Modification History * * 2004-October-7 Jason Rohrer * Created. * * 2006-February-19 Jason Rohrer * Fixed an inconsistency in memory management. */ #include "TranslationManager.h" #include #include "minorGems/io/file/File.h" // will be destroyed automatically at program termination TranslationManagerStaticMembers TranslationManager::mStaticMembers; void TranslationManager::setDirectoryName( char *inName ) { mStaticMembers.setDirectoryAndLanguage( inName, mStaticMembers.mLanguageName ); } char *TranslationManager::getDirectoryName() { return stringDuplicate( mStaticMembers.mDirectoryName ); } char **TranslationManager::getAvailableLanguages( int *outNumLanguages ) { File *languageDirectory = new File( NULL, mStaticMembers.mDirectoryName ); if( languageDirectory->exists() && languageDirectory->isDirectory() ) { int numChildFiles; File **childFiles = languageDirectory->getChildFiles( &numChildFiles ); if( childFiles != NULL ) { SimpleVector *languageNames = new SimpleVector(); for( int i=0; igetFileName(); char *extensionPointer = strstr( name, ".txt" ); if( extensionPointer != NULL ) { // terminate string, cutting off extension extensionPointer[0] = '\0'; languageNames->push_back( stringDuplicate( name ) ); } delete [] name; delete childFiles[i]; } delete [] childFiles; char **returnArray = languageNames->getElementArray(); *outNumLanguages = languageNames->size(); delete languageNames; delete languageDirectory; return returnArray; } } delete languageDirectory; // default, if we didn't return above *outNumLanguages = 0; return new char*[0]; } void TranslationManager::setLanguage( char *inLanguageName ) { mStaticMembers.setDirectoryAndLanguage( mStaticMembers.mDirectoryName, inLanguageName ); } const char *TranslationManager::translate( char *inTranslationKey ) { char *translatedString = NULL; SimpleVector *keys = mStaticMembers.mTranslationKeys; SimpleVector *naturalLanguageStrings = mStaticMembers.mNaturalLanguageStrings; if( keys != NULL ) { int numKeys = keys->size(); for( int i=0; igetElement( i ) ) ) == 0 ) { // keys match translatedString = *( naturalLanguageStrings->getElement( i ) ); } } } if( translatedString == NULL ) { // no translation exists // the translation for this key is the key itself // add it to our translation table char *key = stringDuplicate( inTranslationKey ); char *value = stringDuplicate( inTranslationKey ); keys->push_back( key ); naturalLanguageStrings->push_back( value ); // thus, we return a value from our table, just as if a translation // had existed for this string translatedString = value; } return translatedString; } TranslationManagerStaticMembers::TranslationManagerStaticMembers() : mDirectoryName( NULL ), mLanguageName( NULL ), mTranslationKeys( NULL ), mNaturalLanguageStrings( NULL ) { // default setDirectoryAndLanguage( "languages", "English" ); } TranslationManagerStaticMembers::~TranslationManagerStaticMembers() { if( mDirectoryName != NULL ) { delete [] mDirectoryName; } if( mLanguageName != NULL ) { delete [] mLanguageName; } if( mTranslationKeys != NULL ) { int numKeys = mTranslationKeys->size(); for( int i=0; igetElement( i ) ); } delete mTranslationKeys; } if( mNaturalLanguageStrings != NULL ) { int numKeys = mNaturalLanguageStrings->size(); for( int i=0; igetElement( i ) ); } delete mNaturalLanguageStrings; } } void TranslationManagerStaticMembers::setDirectoryAndLanguage( char *inDirectoryName, char *inLanguageName ) { // save temp copies first to allow caller to pass our own members in to us char *tempDirectoryName = stringDuplicate( inDirectoryName ); char *tempLanguageName = stringDuplicate( inLanguageName ); if( mDirectoryName != NULL ) { delete [] mDirectoryName; } if( mLanguageName != NULL ) { delete [] mLanguageName; } mDirectoryName = tempDirectoryName; mLanguageName = tempLanguageName; // clear the old translation table if( mTranslationKeys != NULL ) { int numKeys = mTranslationKeys->size(); for( int i=0; igetElement( i ) ); } delete mTranslationKeys; } if( mNaturalLanguageStrings != NULL ) { int numKeys = mNaturalLanguageStrings->size(); for( int i=0; igetElement( i ) ); } delete mNaturalLanguageStrings; } // now read in the translation table mTranslationKeys = new SimpleVector(); mNaturalLanguageStrings = new SimpleVector(); File *directoryFile = new File( NULL, mDirectoryName ); if( directoryFile->exists() && directoryFile->isDirectory() ) { char *languageFileName = autoSprintf( "%s.txt", mLanguageName ); File *languageFile = directoryFile->getChildFile( languageFileName ); delete [] languageFileName; if( languageFile != NULL ) { char *languageFileFullPath = languageFile->getFullFileName(); FILE *languageFILE = fopen( languageFileFullPath, "r" ); if( languageFILE != NULL ) { char readError = false; while( ! readError ) { char *key = new char[ 100 ]; int numRead = fscanf( languageFILE, "%99s", key ); if( numRead == 1 ) { // skip the first " int readChar = ' '; while( readChar != '"' && readChar != EOF ) { readChar = fgetc( languageFILE ); } if( readChar != EOF ) { char *naturalLanguageString = new char[1000]; // scan a string of up to 999 characters, stopping // at the first " character numRead = fscanf( languageFILE, "%999[^\"]", naturalLanguageString ); if( numRead == 1 ) { // trim the key and string and save them mTranslationKeys->push_back( stringDuplicate( key ) ); mNaturalLanguageStrings->push_back( stringDuplicate( naturalLanguageString ) ); } else { readError = true; } delete [] naturalLanguageString; // skip the trailing " readChar = ' '; while( readChar != '"' && readChar != EOF ) { readChar = fgetc( languageFILE ); } } else { readError = true; } } else { readError = true; } delete [] key; } fclose( languageFILE ); } delete [] languageFileFullPath; delete languageFile; } } delete directoryFile; } primrose-6+dfsg1.orig/minorGems/util/StringBufferOutputStream.cpp0000644000175000017500000000227410047451312024074 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. * * 2004-May-9 Jason Rohrer * Added function for getting data as a byte array. */ #include "minorGems/util/StringBufferOutputStream.h" StringBufferOutputStream::StringBufferOutputStream() : mCharacterVector( new SimpleVector() ) { } StringBufferOutputStream::~StringBufferOutputStream() { delete mCharacterVector; } char *StringBufferOutputStream::getString() { int numChars = mCharacterVector->size(); char *returnArray = new char[ numChars + 1 ]; for( int i=0; igetElement( i ) ) ); } returnArray[ numChars ] = '\0'; return returnArray; } unsigned char *StringBufferOutputStream::getBytes( int *outNumBytes ) { *outNumBytes = mCharacterVector->size(); return mCharacterVector->getElementArray(); } long StringBufferOutputStream::write( unsigned char *inBuffer, long inNumBytes ) { for( int i=0; ipush_back( inBuffer[ i ] ); } return inNumBytes; } primrose-6+dfsg1.orig/minorGems/util/stringUtils.cpp0000644000175000017500000002544710440046700021433 0ustar pabspabs/* * Modification History * * 2003-May-10 Jason Rohrer * Created. * Added a tokenization function. * * 2003-June-14 Jason Rohrer * Added a join function. * * 2003-June-22 Jason Rohrer * Added an autoSprintf function. * * 2003-July-27 Jason Rohrer * Fixed bugs in autoSprintf return values for certain cases. * * 2003-August-12 Jason Rohrer * Added a concatonate function. * * 2003-September-7 Jason Rohrer * Changed so that split returns last part, even if it is empty. * * 2004-January-15 Jason Rohrer * Added work-around for MinGW vsnprintf bug. * * 2006-June-2 Jason Rohrer * Added a stringStartsWith function. */ #include "stringUtils.h" #include "StringBufferOutputStream.h" #include char *stringToLowerCase( const char *inString ) { int length = strlen( inString ); char *returnString = stringDuplicate( inString ); for( int i=0; i stringLength ) { return false; } else { for( int i=0; i *parts = new SimpleVector(); char *workingString = stringDuplicate( inString ); char *workingStart = workingString; int separatorLength = strlen( inSeparator ); char *foundSeparator = strstr( workingString, inSeparator ); while( foundSeparator != NULL ) { // terminate at separator foundSeparator[0] = '\0'; parts->push_back( stringDuplicate( workingString ) ); // skip separator workingString = &( foundSeparator[ separatorLength ] ); foundSeparator = strstr( workingString, inSeparator ); } // add the remaining part, even if it is the empty string parts->push_back( stringDuplicate( workingString ) ); delete [] workingStart; *outNumParts = parts->size(); char **returnArray = parts->getElementArray(); delete parts; return returnArray; } char *join( char **inStrings, int inNumParts, char *inGlue ) { StringBufferOutputStream *outStream = new StringBufferOutputStream(); for( int i=0; iwriteString( inStrings[i] ); outStream->writeString( inGlue ); } // no glue after last string outStream->writeString( inStrings[ inNumParts - 1 ] ); char *returnString = outStream->getString(); delete outStream; return returnString; } char *concatonate( char *inStringA, char *inStringB ) { char **tempArray = new char*[2]; tempArray[ 0 ] = inStringA; tempArray[ 1 ] = inStringB; char *glue = ""; char *result = join( tempArray, 2, glue ); delete [] tempArray; return result; } char *replaceOnce( char *inHaystack, char *inTarget, char *inSubstitute, char *outFound ) { char *haystackCopy = stringDuplicate( inHaystack ); char *fieldTargetPointer = strstr( haystackCopy, inTarget ); if( fieldTargetPointer == NULL ) { // target not found *outFound = false; return haystackCopy; } else { // target found // prematurely terminate haystack copy string at // start of target occurence // (okay, since we're working with a copy of the haystack argument) fieldTargetPointer[0] = '\0'; // pointer to first char after target occurrence char *fieldPostTargetPointer = &( fieldTargetPointer[ strlen( inTarget ) ] ); char *returnString = new char[ strlen( inHaystack ) - strlen( inTarget ) + strlen( inSubstitute ) + 1 ]; sprintf( returnString, "%s%s%s", haystackCopy, inSubstitute, fieldPostTargetPointer ); delete [] haystackCopy; *outFound = true; return returnString; } } char *replaceAll( char *inHaystack, char *inTarget, char *inSubstitute, char *outFound ) { // repeatedly replace once until replacing fails char lastFound = true; char atLeastOneFound = false; char *returnString = stringDuplicate( inHaystack ); while( lastFound ) { char *nextReturnString = replaceOnce( returnString, inTarget, inSubstitute, &lastFound ); delete [] returnString; returnString = nextReturnString; if( lastFound ) { atLeastOneFound = true; } } *outFound = atLeastOneFound; return returnString; } char *replaceTargetListWithSubstituteList( char *inHaystack, SimpleVector *inTargetVector, SimpleVector *inSubstituteVector ) { int numTargets = inTargetVector->size(); char *newHaystack = stringDuplicate( inHaystack ); char tagFound; for( int i=0; igetElement( i ) ), *( inSubstituteVector->getElement( i ) ), &tagFound ); delete [] newHaystack; newHaystack = newHaystackWithReplacements; } return newHaystack; } SimpleVector *tokenizeString( char *inString ) { char *tempString = stringDuplicate( inString ); char *restOfString = tempString; SimpleVector *foundTokens = new SimpleVector(); SimpleVector *currentToken = new SimpleVector(); while( restOfString[0] != '\0' ) { // characters remain // skip whitespace char nextChar = restOfString[0]; while( nextChar == ' ' || nextChar == '\n' || nextChar == '\r' || nextChar == '\t' ) { restOfString = &( restOfString[1] ); nextChar = restOfString[0]; } if( restOfString[0] != '\0' ) { // a token while( nextChar != ' ' && nextChar != '\n' && nextChar != '\r' && nextChar != '\t' && nextChar != '\0' ) { // still not whitespace currentToken->push_back( nextChar ); restOfString = &( restOfString[1] ); nextChar = restOfString[0]; } // reached end of token foundTokens->push_back( currentToken->getElementString() ); currentToken->deleteAll(); } } delete [] tempString; delete currentToken; return foundTokens; } char *autoSprintf( const char* inFormatString, ... ) { int bufferSize = 50; va_list argList; va_start( argList, inFormatString ); char *buffer = new char[ bufferSize ]; int stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); if( stringLength != -1 ) { // follows C99 standard... // stringLength is the length of the string that would have been // written if the buffer was big enough // not room for string and terminating \0 in bufferSize bytes if( stringLength >= bufferSize ) { // need to reprint with a bigger buffer delete [] buffer; bufferSize = stringLength + 1; va_list argList; va_start( argList, inFormatString ); buffer = new char[ bufferSize ]; // can simply use vsprintf now vsprintf( buffer, inFormatString, argList ); va_end( argList ); return buffer; } else { // buffer was big enough // trim the buffer to fit the string char *returnString = stringDuplicate( buffer ); delete [] buffer; return returnString; } } else { // follows old ANSI standard // -1 means the buffer was too small // Note that some buggy non-C99 vsnprintf implementations // (notably MinGW) // do not return -1 if stringLength equals bufferSize (in other words, // if there is not enough room for the trailing \0). // Thus, we need to check for both // (A) stringLength == -1 // (B) stringLength == bufferSize // below. // keep doubling buffer size until it's big enough while( stringLength == -1 || stringLength == bufferSize) { delete [] buffer; if( stringLength == bufferSize ) { // only occurs if vsnprintf implementation is buggy // might as well use the information, though // (instead of doubling the buffer size again) bufferSize = bufferSize + 1; } else { // double buffer size again bufferSize = 2 * bufferSize; } va_list argList; va_start( argList, inFormatString ); buffer = new char[ bufferSize ]; stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); } // trim the buffer to fit the string char *returnString = stringDuplicate( buffer ); delete [] buffer; return returnString; } } primrose-6+dfsg1.orig/minorGems/util/SimpleVector.h0000644000175000017500000001542611144161511021161 0ustar pabspabs// Jason Rohrer // SimpleVector.h /** * * Simple vector template class. Supports pushing at end and random-access deletions. * Dynamically sized. * * * Created 10-24-99 * Mods: * Jason Rohrer 12-11-99 Added deleteAll function * Jason Rohrer 1-30-2000 Changed to return NULL if get called on non-existent element * Jason Rohrer 12-20-2000 Added a function for deleting a particular * element. * Jason Rohrer 12-14-2001 Added a function for getting the index of * a particular element. * Jason Rohrer 1-24-2003 Added a functions for getting an array or * string of all elements. * Jason Rohrer 7-26-2005 Added template <> to explicitly specialized * getElementString. * Jason Rohrer 1-9-2009 Added setElementString method. */ #include "minorGems/common.h" #ifndef SIMPLEVECTOR_INCLUDED #define SIMPLEVECTOR_INCLUDED #include // for memory moving functions const int defaultStartSize = 50; template class SimpleVector { public: SimpleVector(); // create an empty vector SimpleVector(int sizeEstimate); // create an empty vector with a size estimate ~SimpleVector(); void push_back(Type x); // add x to the end of the vector Type *getElement(int index); // get a ptr to element at index in vector int size(); // return the number of allocated elements in the vector bool deleteElement(int index); // delete element at an index in vector /** * Deletes a particular element. Deletes the first element * in vector == to inElement. * * @param inElement the element to delete. * * @return true iff an element was deleted. */ bool deleteElement( Type inElement ); /** * Gets the index of a particular element. Gets the index of the * first element in vector == to inElement. * * @param inElement the element to get the index of. * * @return the index if inElement, or -1 if inElement is not found. */ int getElementIndex( Type inElement ); void deleteAll(); // delete all elements from vector /** * Gets the elements as an array. * * @return the a new array containing all elements in this vector. * Must be destroyed by caller, though elements themselves are * not copied. */ Type *getElementArray(); /** * Gets the char elements as a \0-terminated string. * * @return a \0-terminated string containing all elements in this * vector. * Must be destroyed by caller. */ char *getElementString(); /** * Sets the char elements as a \0-terminated string. * * @param inString a \0-terminated string containing all elements to * this vector with. * Must be destroyed by caller. */ void setElementString( char *inString ); private: Type *elements; int numFilledElements; int maxSize; int minSize; // number of allocated elements when vector is empty }; template inline SimpleVector::SimpleVector() { elements = new Type[defaultStartSize]; numFilledElements = 0; maxSize = defaultStartSize; minSize = defaultStartSize; } template inline SimpleVector::SimpleVector(int sizeEstimate) { elements = new Type[sizeEstimate]; numFilledElements = 0; maxSize = sizeEstimate; minSize = sizeEstimate; } template inline SimpleVector::~SimpleVector() { delete [] elements; } template inline int SimpleVector::size() { return numFilledElements; } template inline Type *SimpleVector::getElement(int index) { if( index < numFilledElements && index >=0 ) { return &(elements[index]); } else return NULL; } template inline bool SimpleVector::deleteElement(int index) { if( index < numFilledElements) { // if index valid for this vector if( index != numFilledElements - 1) { // this spot somewhere in middle // move memory towards front by one spot int sizeOfElement = sizeof(Type); int numBytesToMove = sizeOfElement*(numFilledElements - (index+1)); Type *destPtr = &(elements[index]); Type *srcPtr = &(elements[index+1]); memmove((void *)destPtr, (void *)srcPtr, numBytesToMove); } numFilledElements--; // one less element in vector return true; } else { // index not valid for this vector return false; } } template inline bool SimpleVector::deleteElement( Type inElement ) { int index = getElementIndex( inElement ); if( index != -1 ) { return deleteElement( index ); } else { return false; } } template inline int SimpleVector::getElementIndex( Type inElement ) { // walk through vector, looking for first match. for( int i=0; i inline void SimpleVector::deleteAll() { numFilledElements = 0; if( maxSize > minSize ) { // free memory if vector has grown delete [] elements; elements = new Type[minSize]; // reallocate an empty vector maxSize = minSize; } } template inline void SimpleVector::push_back(Type x) { if( numFilledElements < maxSize) { // still room in vector elements[numFilledElements] = x; numFilledElements++; } else { // need to allocate more space for vector int newMaxSize = maxSize << 1; // double size Type *newAlloc = new Type[newMaxSize]; int sizeOfElement = sizeof(Type); int numBytesToMove = sizeOfElement*(numFilledElements); // move into new space memcpy((void *)newAlloc, (void *) elements, numBytesToMove); // delete old space delete [] elements; elements = newAlloc; maxSize = newMaxSize; elements[numFilledElements] = x; numFilledElements++; } } template inline Type *SimpleVector::getElementArray() { Type *newAlloc = new Type[ numFilledElements ]; int sizeOfElement = sizeof( Type ); int numBytesToCopy = sizeOfElement * numFilledElements; // copy into new space memcpy( (void *)newAlloc, (void *)elements, numBytesToCopy ); return newAlloc; } template <> inline char *SimpleVector::getElementString() { char *newAlloc = new char[ numFilledElements + 1 ]; int sizeOfElement = sizeof( char ); int numBytesToCopy = sizeOfElement * numFilledElements; // copy into new space memcpy( (void *)newAlloc, (void *)elements, numBytesToCopy ); newAlloc[ numFilledElements ] = '\0'; return newAlloc; } template <> inline void SimpleVector::setElementString( char *inString ) { // slow but correct deleteAll(); int numChars = strlen( inString ); for( int i=0; i * * printf( "%s", translate( myKey ) ); * delete [] myKey; * * * will always be correct, whether or not a translation exists, as * will
         *
         * printf( "%s", translate( "MY_KEY" ) );
         * 
*/ static const char *translate( char *inTranslationKey ); protected: static TranslationManagerStaticMembers mStaticMembers; }; /** * Container for static members to allow for their proper destruction * on program termination. * * @author Jason Rohrer */ class TranslationManagerStaticMembers { public: TranslationManagerStaticMembers(); ~TranslationManagerStaticMembers(); /** * Sets the directory name and language name to use, and reads * the translation table from file. * * @param inDirectoryName the directory name. * Must be destroyed by caller. * @param inLanguageName the language name. * Must be destroyed by caller. */ void setDirectoryAndLanguage( char *inDirectoryName, char *inLanguageName ); char *mDirectoryName; char *mLanguageName; // vectors mapping keys to strings SimpleVector *mTranslationKeys; SimpleVector *mNaturalLanguageStrings; }; #endif primrose-6+dfsg1.orig/minorGems/util/printUtils.h0000644000175000017500000000102707554101514020721 0ustar pabspabs/* * Modification History * * 2002-April-8 Jason Rohrer * Created. */ #include "minorGems/common.h" #ifndef PRINT_UTILS_INCLUDED #define PRINT_UTILS_INCLUDED /** * A thread-safe version of printf. * * Note that printf is already thread-safe on certain platforms, * but does not seem to be thread-safe on Win32. * * @param inFormatString the format string to use. * @param ... a variable argument list, with the same usage * pattern as printf. */ int threadPrintF( const char* inFormatString, ... ); #endif primrose-6+dfsg1.orig/minorGems/util/printUtils.cpp0000644000175000017500000000107407455450264021267 0ustar pabspabs/* * Modification History * * 2002-April-8 Jason Rohrer * Created. * * 2002-April-11 Jason Rohrer * Added a missing return value. */ #include "printUtils.h" #include "minorGems/system/MutexLock.h" #include // for variable argument lists #include MutexLock threadPrintFLock; int threadPrintF( const char* inFormatString, ... ) { threadPrintFLock.lock(); va_list argList; va_start( argList, inFormatString ); int returnVal = vprintf( inFormatString, argList ); threadPrintFLock.unlock(); return returnVal; } primrose-6+dfsg1.orig/minorGems/util/test/0000755000175000017500000000000011201637600017344 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/util/test/testSnprintf.mingw.out0000644000175000017500000000055610001574214023724 0ustar pabspabsPrinted string of length 3 to buffer of size 4 with snprintf. Return value = 3 Buffer was null-terminated by snprintf Printed string of length 4 to buffer of size 4 with snprintf. Return value = 4 Buffer was NOT null-terminated by snprintf Printed string of length 5 to buffer of size 4 with snprintf. Return value = -1 Buffer was NOT null-terminated by snprintf primrose-6+dfsg1.orig/minorGems/util/test/testSnprintf.cpp0000644000175000017500000000232410001572273022555 0ustar pabspabs/* * Modification History * * 2004-January-15 Jason Rohrer * Created. */ /** * A test program for snprintf behavior. */ #include #include #include int main() { int numStrings = 3; // test strings of length 3, 4, and 5 const char *testStrings[3] = { "tst", "test", "testt" }; int result; // a buffer of length 4, which IS NOT large // enough to hold the last two testStrings char *buffer = (char*)( malloc( 4 ) ); int i; for( i=0; i * * Modified by Aaron D. Gifford * * NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN * * The original unmodified version is available at: * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "sha1.h" #include #include // for hex encoding #include "minorGems/formats/encodingUtils.h" #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define blk0(i) (block->l[i] = (rol(block->l[i],24)&(sha1_quadbyte)0xFF00FF00) \ |(rol(block->l[i],8)&(sha1_quadbyte)0x00FF00FF)) #else #define blk0(i) block->l[i] #endif #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ^block->l[(i+2)&15]^block->l[i&15],1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); typedef union _BYTE64QUAD16 { sha1_byte c[64]; sha1_quadbyte l[16]; } BYTE64QUAD16; /* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1_Transform(sha1_quadbyte state[5], sha1_byte buffer[64]) { sha1_quadbyte a, b, c, d, e; BYTE64QUAD16 *block; block = (BYTE64QUAD16*)buffer; /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; } /* SHA1_Init - Initialize new context */ void SHA1_Init(SHA_CTX* context) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } /* Run your data through this. */ void SHA1_Update(SHA_CTX *context, sha1_byte *data, unsigned int len) { unsigned int i, j; j = (context->count[0] >> 3) & 63; if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; context->count[1] += (len >> 29); if ((j + len) > 63) { memcpy(&context->buffer[j], data, (i = 64-j)); SHA1_Transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64) { SHA1_Transform(context->state, &data[i]); } j = 0; } else i = 0; memcpy(&context->buffer[j], &data[i], len - i); } /* Add padding and return the message digest. */ void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX *context) { sha1_quadbyte i, j; sha1_byte finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (sha1_byte)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ } SHA1_Update(context, (sha1_byte *)"\200", 1); while ((context->count[0] & 504) != 448) { SHA1_Update(context, (sha1_byte *)"\0", 1); } /* Should cause a SHA1_Transform() */ SHA1_Update(context, finalcount, 8); for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { digest[i] = (sha1_byte) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } /* Wipe variables */ i = j = 0; memset(context->buffer, 0, SHA1_BLOCK_LENGTH); memset(context->state, 0, SHA1_DIGEST_LENGTH); memset(context->count, 0, 8); memset(&finalcount, 0, 8); } unsigned char *computeRawSHA1Digest( unsigned char *inData, int inDataLength ) { SHA_CTX context; SHA1_Init( &context ); // copy into buffer, since this SHA1 implementation seems to overwrite // parts of the data buffer. unsigned char *buffer = new unsigned char[ inDataLength ]; memcpy( (void *)buffer, (void *)inData, inDataLength ); SHA1_Update( &context, buffer, inDataLength ); delete [] buffer; unsigned char *digest = new unsigned char[ SHA1_DIGEST_LENGTH ]; SHA1_Final( digest, &context ); return digest; } unsigned char *computeRawSHA1Digest( char *inString ) { SHA_CTX context; SHA1_Init( &context ); // copy into buffer, since this SHA1 implementation seems to overwrite // parts of the data buffer. int dataLength = strlen( inString ); unsigned char *buffer = new unsigned char[ dataLength ]; memcpy( (void *)buffer, (void *)inString, dataLength ); SHA1_Update( &context, buffer, strlen( inString ) ); delete [] buffer; unsigned char *digest = new unsigned char[ SHA1_DIGEST_LENGTH ]; SHA1_Final( digest, &context ); return digest; } char *computeSHA1Digest( char *inString ) { unsigned char *digest = computeRawSHA1Digest( inString ); char *digestHexString = hexEncode( digest, SHA1_DIGEST_LENGTH ); delete [] digest; return digestHexString; } char *computeSHA1Digest( unsigned char *inData, int inDataLength ) { unsigned char *digest = computeRawSHA1Digest( inData, inDataLength ); char *digestHexString = hexEncode( digest, SHA1_DIGEST_LENGTH ); delete [] digest; return digestHexString; } primrose-6+dfsg1.orig/minorGems/crypto/hashes/sha1sumCompile0000755000175000017500000000011610053166076023031 0ustar pabspabsg++ -I../../.. -o sha1sum sha1sum.cpp sha1.cpp ../../formats/encodingUtils.cppprimrose-6+dfsg1.orig/minorGems/crypto/hashes/sha1sum.cpp0000644000175000017500000000353610053166076022307 0ustar pabspabs/* * Modification History * * 2004-May-20 Jason Rohrer * Created. */ #include "sha1.h" #include "minorGems/formats/encodingUtils.h" #include /** * Prints usage message and exits. * * @param inAppName the name of the app. */ void usage( char *inAppName ); int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 2 ) { usage( inArgs[0] ); } FILE *file = fopen( inArgs[1], "rb" ); if( file == NULL ) { printf( "Failed to open file %s for reading\n\n", inArgs[1] ); usage( inArgs[0] ); } SHA_CTX shaContext; SHA1_Init( &shaContext ); int bufferSize = 5000; unsigned char *buffer = new unsigned char[ bufferSize ]; int numRead = bufferSize; char error = false; // read bytes from file until we run out while( numRead == bufferSize && !error ) { numRead = fread( buffer, 1, bufferSize, file ); if( numRead > 0 ) { SHA1_Update( &shaContext, buffer, numRead ); } else{ error = true; } } fclose( file ); delete [] buffer; if( error ) { printf( "Error reading from file %s\n", inArgs[1] ); } else { unsigned char *rawDigest = new unsigned char[ SHA1_DIGEST_LENGTH ]; SHA1_Final( rawDigest, &shaContext ); // else hash is correct char *digestHexString = hexEncode( rawDigest, SHA1_DIGEST_LENGTH ); printf( "%s %s\n", digestHexString, inArgs[1] ); delete [] rawDigest; delete [] digestHexString; } return 0; } void usage( char *inAppName ) { printf( "Usage:\n\n" ); printf( "\t%s file_to_sum\n", inAppName ); printf( "example:\n" ); printf( "\t%s test.txt\n", inAppName ); exit( 1 ); } primrose-6+dfsg1.orig/minorGems/crypto/hashes/sha1.h0000644000175000017500000000740307731352255021231 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Changed to use minorGems endian.h * Added a function for hashing an entire string to a hex digest. * Added a function for getting a raw digest. * * 2003-September-15 Jason Rohrer * Added support for hashing raw (non-string) data. * Removed legacy C code. */ /* * sha.h * * Originally taken from the public domain SHA1 implementation * written by by Steve Reid * * Modified by Aaron D. Gifford * * NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN * * The original unmodified version is available at: * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef __SHA1_H__ #define __SHA1_H__ #include "minorGems/system/endian.h" /* Make sure you define these types for your architecture: */ typedef unsigned int sha1_quadbyte; /* 4 byte type */ typedef unsigned char sha1_byte; /* single byte type */ /* * Be sure to get the above definitions right. For instance, on my * x86 based FreeBSD box, I define LITTLE_ENDIAN and use the type * "unsigned long" for the quadbyte. On FreeBSD on the Alpha, however, * while I still use LITTLE_ENDIAN, I must define the quadbyte type * as "unsigned int" instead. */ #define SHA1_BLOCK_LENGTH 64 #define SHA1_DIGEST_LENGTH 20 /* The SHA1 structure: */ typedef struct _SHA_CTX { sha1_quadbyte state[5]; sha1_quadbyte count[2]; sha1_byte buffer[SHA1_BLOCK_LENGTH]; } SHA_CTX; void SHA1_Init(SHA_CTX *context); void SHA1_Update(SHA_CTX *context, sha1_byte *data, unsigned int len); void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX* context); /** * Computes a unencoded 20-byte digest from data. * * @param inData the data to hash. * Must be destroyed by caller. * @param inDataLength the length of the data to hash. * Must be destroyed by caller. * * @return the digest as a byte array of length 20. * Must be destroyed by caller. */ unsigned char *computeRawSHA1Digest( unsigned char *inData, int inDataLength ); /** * Computes a unencoded 20-byte digest from an arbitrary string message. * * @param inString the message as a \0-terminated string. * Must be destroyed by caller. * * @return the digest as a byte array of length 20. * Must be destroyed by caller. */ unsigned char *computeRawSHA1Digest( char *inString ); /** * Computes a hex-encoded string digest from data. * * @param inData the data to hash. * Must be destroyed by caller. * @param inDataLength the length of the data to hash. * Must be destroyed by caller. * * @return the digest as a \0-terminated string. * Must be destroyed by caller. */ char *computeSHA1Digest( unsigned char *inData, int inDataLength ); /** * Computes a hex-encoded string digest from an arbitrary string message. * * @param inString the message as a \0-terminated string. * Must be destroyed by caller. * * @return the digest as a \0-terminated string. * Must be destroyed by caller. */ char *computeSHA1Digest( char *inString ); #endif primrose-6+dfsg1.orig/minorGems/crypto/hashes/sha1Test.cpp0000644000175000017500000000476707733372451022440 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * * 2003-September-21 Jason Rohrer * Added test of long string. */ #include "sha1.h" #include #include /** * All parameters must be destroyed by caller. */ void checkHash( char *inString, char *inTestName, char *inCorrectHash ); int main() { /* * Test vectors: * * "abc" * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D * * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 * * A million repetitions of "a" * 34AA 973C D4C4 DAA4 F61E EB2B DBAD 2731 6534 016F */ char *abc = "abc"; char *correctABCHash = "A9993E364706816ABA3E25717850C26C9CD0D89D"; char *mixedAlpha = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; char *correctMixedAlphaHash = "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"; char *correctMillionHash = "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"; int oneMillion = 1000000; char *millionAs = new char[ oneMillion + 1 ]; for( int i=0; i getKeyDown( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? true : false); } getKeyUp( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? false : true); } Sample Mac implementation #include getKeyDown( int vKeyCode ) { KeyMapByteArray keyArray; GetKeys( keyArray ); int arrayInd = vKeyCode >> 3; // divide by 8 to get start array index of key code unsigned char neededByte = keyArray[ arrayInd ]; return (neededByte >> vKeyCode % 8) && 0x01; // trim off bit needed } getKeyUp( int vKeyCode ) { KeyMapByteArray keyArray; GetKeys( keyArray ); int arrayInd = vKeyCode >> 3; // divide by 8 to get start array index of key code unsigned char neededByte = keyArray[ arrayInd ]; return !((neededByte >> vKeyCode % 8) && 0x01); // trim off bit needed, and invert } */primrose-6+dfsg1.orig/minorGems/graphics/filters/0000755000175000017500000000000011201637526020667 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/filters/InvertFilter.h0000644000175000017500000000123307220517106023451 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. */ #ifndef INVERT_FILTER_INCLUDED #define INVERT_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" /** * Filter that inverts the values in a channel. * * @author Jason Rohrer */ class InvertFilter : public ChannelFilter { public: // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); }; inline void InvertFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numPixels = inWidth * inHeight; for( int i=0; i *mFilterVector; }; inline MultiFilter::MultiFilter() : mFilterVector( new SimpleVector() ) { } inline MultiFilter::~MultiFilter() { delete mFilterVector; } inline void MultiFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numFilters = mFilterVector->size(); for( int i=0; igetElement( i ) ); thisFilter->apply( inChannel, inWidth, inHeight ); } } #endif primrose-6+dfsg1.orig/minorGems/graphics/filters/MedianFilter.h0000644000175000017500000000672407301027016023405 0ustar pabspabs/* * Modification History * * 2001-May-15 Jeremy Tavan * Created. * * 2001-May-16 Jeremy Tavan * Modified to use the much faster quick_select * median-finding algorithm. * * 2001-May-17 Jaosn Rohrer * Tried to optimize by moving stuff out of the inner-inner loop. * It helped a bit, but not much. * */ #ifndef MEDIAN_FILTER_INCLUDED #define MEDIAN_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" #include "quickselect.h" int medianFilterCompareInt( const void *x, const void *y ); /** * Median convolution filter. * * @author Jeremy Tavan */ class MedianFilter : public ChannelFilter { public: /** * Constructs a median filter. * * @param inRadius the radius of the box in pixels. */ MedianFilter( int inRadius ); /** * Sets the box radius. * * @param inRadius the radius of the box in pixels. */ void setRadius( int inRadius ); /** * Gets the box radius. * * @return the radius of the box in pixels. */ int getRadius(); // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); private: int mRadius; }; inline MedianFilter::MedianFilter( int inRadius ) : mRadius( inRadius ) { } inline void MedianFilter::setRadius( int inRadius ) { mRadius = inRadius; } inline int MedianFilter::getRadius() { return mRadius; } inline void MedianFilter::apply( double *inChannel, int inWidth, int inHeight ) { // pre-compute an integer version of the channel for the // median alg to use int numPixels = inWidth * inHeight; int *intChannel = new int[ numPixels ]; for( int p=0; p= inHeight ) { endBoxY = inHeight - 1; } int boxSizeY = endBoxY - startBoxY + 1; for( int x=0; x= inWidth ) { endBoxX = inWidth - 1; } int boxSizeX = endBoxX - startBoxX + 1; int *buffer = new int[boxSizeX * boxSizeY]; // sum all pixels in the box around this pixel for( int boxY = startBoxY; boxY<=endBoxY; boxY++ ) { int yBoxIndexContrib = boxY * inWidth; int yBoxContrib = boxSizeX * ( boxY-startBoxY ); for( int boxX = startBoxX; boxX<=endBoxX; boxX++ ) { //buffer[boxSizeX*(boxY-startBoxY)+(boxX-startBoxX)] = (int)(1000.0 * inChannel[yBoxIndexContrib + boxX]); buffer[ yBoxContrib + ( boxX-startBoxX ) ] = intChannel[ yBoxIndexContrib + boxX ]; } } medianChannel[ yIndexContrib + x ] = (double)quick_select( buffer, boxSizeX*boxSizeY ) / 1000.0; delete [] buffer; } } // copy blurred image back into passed-in image memcpy( inChannel, medianChannel, sizeof(double) * inWidth * inHeight ); delete [] medianChannel; delete [] intChannel; } #endif primrose-6+dfsg1.orig/minorGems/graphics/filters/quickselect.h0000644000175000017500000000320607300520500023341 0ustar pabspabs/* * This Quickselect routine is based on the algorithm described in * "Numerical recipies in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 */ #define ELEM_SWAP(a,b) { register int t=(a);(a)=(b);(b)=t; } int quick_select(int arr[], int n) { int low, high; int median; int middle, ll, hh; low = 0 ; high = n-1 ; median = (low + high) / 2; for (;;) { if (high <= low) /* One element only */ return arr[median] ; if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median] ; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP primrose-6+dfsg1.orig/minorGems/graphics/filters/BoxBlurFilter.h0000644000175000017500000001367510500113717023567 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. * * 2001-January-6 Jason Rohrer * Added a getRadius function for completeness. * * 2006-August-22 Jason Rohrer * Fixed major bug: sum for box must start at zero. * * 2006-September-7 Jason Rohrer * Optimized inner loop. * Optimized more, avoiding summing over entire box for each pixel. */ #ifndef BOX_BLUR_FILTER_INCLUDED #define BOX_BLUR_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" /** * Blur convolution filter that uses a box for averaging. * * @author Jason Rohrer */ class BoxBlurFilter : public ChannelFilter { public: /** * Constructs a box filter. * * @param inRadius the radius of the box in pixels. */ BoxBlurFilter( int inRadius ); /** * Sets the box radius. * * @param inRadius the radius of the box in pixels. */ void setRadius( int inRadius ); /** * Gets the box radius. * * @return the radius of the box in pixels. */ int getRadius(); // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); private: int mRadius; }; inline BoxBlurFilter::BoxBlurFilter( int inRadius ) : mRadius( inRadius ) { } inline void BoxBlurFilter::setRadius( int inRadius ) { mRadius = inRadius; } inline int BoxBlurFilter::getRadius() { return mRadius; } inline void BoxBlurFilter::apply( double *inChannel, int inWidth, int inHeight ) { double *blurredChannel = new double[ inWidth * inHeight ]; // optimization: // The sum for a given pixel's box in row N is the sum for the same pixel // in row (N-1) minus one box-row of pixels and plus a box-row of pixels // We don't have to loop over the entire box for each pixel (instead, // we just add the new pixels and subtract the old as the box moves along) char lastRowSumsSet = false; double *lastRowSums = new double[ inWidth ]; // track the sums from single rows of boxes that we have already seen // Thus, when we need to "subtract a row" from our box sum, we can use // the precomputed version double *singleRowBoxSums = new double[ inWidth * inHeight ]; for( int y=0; y= inHeight ) { endBoxY = inHeight - 1; // box hanging over bottom edge // no rows to add to sum addARow = false; } int boxSizeY = endBoxY - startBoxY + 1; for( int x=0; x= inWidth ) { endBoxX = inWidth - 1; } int boxSizeX = endBoxX - startBoxX + 1; // sum all pixels in the box around this pixel double sum = 0; if( ! lastRowSumsSet ) { // do the "slow way" for the first row for( int boxY = startBoxY; boxY<=endBoxY; boxY++ ) { int yBoxIndexContrib = boxY * inWidth; double rowSum = 0; for( int boxX = startBoxX; boxX<=endBoxX; boxX++ ) { rowSum += inChannel[ yBoxIndexContrib + boxX ]; } sum += rowSum; // store row sum for future use singleRowBoxSums[ yBoxIndexContrib + x ] = rowSum; } } else { // we have sum for this pixel from the previous row // use it to avoid looping over entire box again sum = lastRowSums[ x ]; if( addARow ) { // add pixels from row at endBoxY int yBoxIndexContrib = endBoxY * inWidth; double rowSum = 0; for( int boxX = startBoxX; boxX<=endBoxX; boxX++ ) { rowSum += inChannel[ yBoxIndexContrib + boxX ]; } sum += rowSum; // store it for later when we will need to subtract it singleRowBoxSums[ yBoxIndexContrib + x ] = rowSum; } if( subtractARow ) { // subtract pixels from startBoxY of previous row's box int yBoxIndexContrib = (startBoxY - 1) * inWidth; // use pre-computed sum for the row we're subtracting sum -= singleRowBoxSums[ yBoxIndexContrib + x ]; } } // divide by number of pixels to complete the average blurredChannel[ pixelIndex ] = sum / (boxSizeX * boxSizeY); // save to use when computing box sum for next row lastRowSums[ x ] = sum; } // we now have valid last row sums that we can use for // all the rest of the rows lastRowSumsSet = true; } // copy blurred image back into passed-in image memcpy( inChannel, blurredChannel, sizeof(double) * inWidth * inHeight ); delete [] blurredChannel; delete [] lastRowSums; delete [] singleRowBoxSums; } #endif primrose-6+dfsg1.orig/minorGems/graphics/filters/ThresholdFilter.h0000644000175000017500000000265107220517106024143 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. */ #ifndef THRESHOLD_FILTER_INCLUDED #define THRESHOLD_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" /** * Threshold filter. * * @author Jason Rohrer */ class ThresholdFilter : public ChannelFilter { public: /** * Constructs a threshold filter. * * @param inThreshold threshold value. Channel values * above or equal to inThreshold are set to 1, while * all other values are set to 0. */ ThresholdFilter( double inThreshold ); /** * Sets the threshold. * * @param inThreshold threshold value. Channel values * above or equal to inThreshold are set to 1, while * all other values are set to 0. */ void setThreshold( double inThreshold ); // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); private: double mThreshold; }; inline ThresholdFilter::ThresholdFilter( double inThreshold ) : mThreshold( inThreshold ) { } inline void ThresholdFilter::setThreshold( double inThreshold ) { mThreshold = inThreshold; } inline void ThresholdFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numPixels = inWidth * inHeight; for( int i=0; i= mThreshold ) { inChannel[i] = 1.0; } else { inChannel[i] = 0.0; } } } #endif primrose-6+dfsg1.orig/minorGems/graphics/filters/SeamlessFilter.h0000644000175000017500000000740510506006133023757 0ustar pabspabs/* * Modification History * * 2001-January-19 Jason Rohrer * Created. * * 2006-September-25 Jason Rohrer * Added control over blending curve. * Reorderd loop for efficiency. */ #ifndef SEAMLESS_FILTER_INCLUDED #define SEAMLESS_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" #include /** * Filter that turns any image into a seamless tile. * * @author Jason Rohrer */ class SeamlessFilter : public ChannelFilter { public: /** * Constructs a filter. * * @param inBlendCurveExponent the exponent of the blending curve * as we near the edge of the image. Defaults to 1 for a linear * blending curve. Setting to 2 would result in a parabolic * curve which would push the blended area closer to the edge * and leave more high-contrast, unblended image data near * the middle. */ SeamlessFilter( double inBlendCurveExponent = 1 ); // implements the ChannelFilter interface virtual void apply( double *inChannel, int inWidth, int inHeight ); private: double mBlendingCurveExponent; }; inline SeamlessFilter::SeamlessFilter( double inBlendCurveExponent ) : mBlendingCurveExponent( inBlendCurveExponent ) { } inline void SeamlessFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numPixels = inWidth * inHeight; int halfHigh = inHeight/2; int halfWide = inWidth/2; // mix the texture with itself. // as we move closer and closer to the texture edge, we should // start mixing in more and more of the center values double *channelCopy = new double[ numPixels ]; // first, create an image with no seams if tiled horizontally // (getting rid of vertical seams) for( int x=0; x #include "IconMap.h" class GraphicBuffer { public: GraphicBuffer( unsigned long *buff, int buffW, int buffH ); ~GraphicBuffer(); // draw a solid image into the buffer void drawImage( unsigned long *image, int *imageYOffset, int xPos, int yPos, int wide, int high ); // draw a transparent image into the buffer void drawImageAlpha( unsigned long *image, int *imageYOffset, int xPos, int yPos, int wide, int high ); // replace a rectangle in the buffer with bgColor void eraseImage( int xPos, int yPos, int wide, int high, Color &bgColor ); // draw a solid IconMap into the buffer void drawIconMap( IconMap *icon, int xPos, int yPos ); // draw a transparent image into the buffer void drawIconMapAlpha( IconMap *icon, int xPos, int yPos ); // replace a rectangle (over icon) in the buffer with bgColor void eraseIconMap( IconMap *icon, int xPos, int yPos, Color &bgColor ); // set buffer to a new buffer of the same size void setBuffer( unsigned long *buff ); // get the pixel buffer unsigned long *getBuffer(); int getWidth(); int getHeight(); // fill buffer with a color void fill( Color &fillC ); // take a screen shot, save to disc void screenShot( FILE *f ); private: unsigned long *buffer; int bufferHigh; int bufferWide; int *buffYOffset; float invChannelMax; Color utilColor; // color for using composite functions }; inline GraphicBuffer::GraphicBuffer( unsigned long *buff, int buffW, int buffH) : utilColor(0,0,0,0) { invChannelMax = 1 / 255.0; bufferHigh = buffH; bufferWide = buffW; buffer = buff; // precalc'ed y contributions to linear indexing of buffer buffYOffset = new int[bufferHigh]; for( int y=0; y bufferHigh ) { maxY = bufferHigh; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + wide; if( maxX > bufferWide ) { maxX = bufferWide; } for( int y=minY; y bufferHigh ) { maxY = bufferHigh; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + wide; if( maxX > bufferWide ) { maxX = bufferWide; } unsigned long composite = bgColor.composite; for( int y=minY; y bufferHigh ) { maxY = bufferHigh; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + wide; if( maxX > bufferWide ) { maxX = bufferWide; } for( int y=minY; y> 24) * invChannelMax; float oneMinusAlpha = 1-alpha; unsigned long buffARGB = buffer[ buffYContrib + x ]; argb = utilColor.getWeightedComposite( argb, alpha ); buffARGB = utilColor.getWeightedComposite( buffARGB, oneMinusAlpha ); unsigned long sum = utilColor.sumComposite( argb, buffARGB ); buffer[ buffYContrib + x ] = sum; } } } inline void GraphicBuffer::drawIconMap( IconMap *icon, int xPos, int yPos ) { drawImage( icon->imageMap, icon->yOffset, xPos, yPos, icon->wide, icon->high ); } inline void GraphicBuffer::drawIconMapAlpha( IconMap *icon, int xPos, int yPos ) { drawImageAlpha( icon->imageMap, icon->yOffset, xPos, yPos, icon->wide, icon->high ); } inline void GraphicBuffer::eraseIconMap( IconMap *icon, int xPos, int yPos, Color &bgColor ) { eraseImage( xPos, yPos, icon->wide, icon->high, bgColor ); } inline void GraphicBuffer::fill( Color &fillC ) { unsigned long composite = fillC.composite; for( int y=0; y #include #include "Image.h" /** * An RGBA extension of Image. * * @author Jason Rohrer */ class RGBAImage : public Image { public: /** * Constructs an RGBA image. All channels are initialized to 0. * * @param inWidth width of image in pixels. * @param inHeight height of image in pixels. */ RGBAImage( int inWidth, int inHeight ); /** * Constructs an RGBAImage by copying a given image. * The image data is truncated or expaned (with black channels) * to fit the 4 channel RGBA model, * and any selection in inImage is ignored. * * @param inImage the image to copy. Copied internally, so must be * destroyed by the caller. */ RGBAImage( Image *inImage ); /** * Gets the pixel data from this image as a byte array. * * @return a byte array containing pixel data for this image. * Stored in row-major order, with each pixel represented * by 4 bytes in the order RGBA. * Must be destroyed by caller. */ virtual unsigned char *getRGBABytes(); // overrides the Image::filter function virtual void filter( ChannelFilter *inFilter ); virtual void filter( ChannelFilter *inFilter, int inChannel ); // overrides the Image::copy function // since the function is non-virtual in the parent class, // the pointer type should determine which function gets called. RGBAImage *copy(); }; inline RGBAImage::RGBAImage( int inWidth, int inHeight ) : Image( inWidth, inHeight, 4 ) { } inline RGBAImage::RGBAImage( Image *inImage ) // Only init our image's channels to black of inImage doesn't have enough // channels. // This saves time if inImage has 4 or more channels. // Optimization found with profiler. : Image( inImage->getWidth(), inImage->getHeight(), 4, ( inImage->getNumChannels() < 4 ) ) { int minNumChannels = 4; if( inImage->getNumChannels() < minNumChannels ) { minNumChannels = inImage->getNumChannels(); } // if inImage does not have at least 4 channels, // leave our additional channels black // if inImage has extra channels, skip them // copy channels from inImage for( int c=0; cgetChannel( c ); memcpy( mChannels[c], inChannel, mNumPixels * sizeof( double ) ); } } /* inline unsigned char *RGBAImage::getRGBABytes() { int numBytes = mNumPixels * 4; unsigned char *bytes = new unsigned char[ numBytes ]; int pixel = 0; for( int i=0; ipaste( this ); return copiedImage; } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/0000755000175000017500000000000011203741225020375 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/openGL/NoLightingGL.h0000644000175000017500000000121007220267641023036 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. */ #ifndef NO_LIGHTING_GL_INCLUDED #define NO_LIGHTING_GL_INCLUDED #include "LightingGL.h" /** * LightingGL implementation that uses a constant white light everywhere. * * @author Jason Rohrer */ class NoLightingGL : public LightingGL{ public: // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); }; inline void NoLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { outColor->r = 1.0; outColor->g = 1.0; outColor->b = 1.0; } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/RadiosGLView.cpp0000644000175000017500000004061307205611501023404 0ustar pabspabs// Jason Rohrer // RadiosGLView.cpp /** * * OpenGL viewer for RadiosGL rendered scenes * * Created 1-14-2000 * Mods: * Jason Rohrer 1-15-2000 Added timer function to make keyboard * interaction smoother and more intuitive * * Jason Rohrer 1-18-2000 Moved SetMouse call from within mouse handler * to inside re-display function * SetMouse was posting a new mouse event too * quickly, putting the delta-angles back to 0 * before the posted redisplay happened. * * This made view motion jerky on the PC * Fixed it by only centering mouse when it leaves window * (or hits window border) * Added mouse capture to window on PC so that * mouse events outside window border are captured * * Added "o" key control to switch into fullscreen mode */ #define APP_NAME "RadiosGLView" #define SETTINGS_FILE_NAME "RadiosGLView.ini" #define FORWARD_MOTION_TIMER 200 #include #include #include #include #include "gl.h" #include "glut.h" #include "RadiosityConstants.h" #include "Vertex.h" #include "Dither.h" #include "UniversalFileIO.h" // function for force-setting mouse position #include "SetMouse.h" // prototypes void cleanup(); int loadSettings(); void initModel(); void glutMotion(int x, int y); void draw (void); void glutDisplay (void); void glutResize (int w, int h); void glutKeyboard (unsigned char key, int x, int y); void glInit (void); void glutTimer( int value ); void glutIdle( void ); void glutEntry( int state ); // vector typedef float vec3_t[3]; // these are loaded from the ini file int screenCenterX; int screenCenterY; float invScreenCenterX; float invScreenCenterY; int dithering; int invMouse; int fullscreen; char *modelFileName = new char[99]; // window width and height int winW; int winH; long numPatches; Vertex *triangles[3]; Vertex *textAnchors[3]; int startTextID = 13; float translationX = 0; float translationY = 0; float translationZ = 0; // position for view float positionX = 0; float positionY = 25; float positionZ = 0; float speed = 0.5; // speed of motion float rotationSpeed = 1.0; // speed of view rotation // two vectors specifying view direction float lookX = 0; float lookY = 0; float lookZ = 1; float upX = 0; float upY = 1; float upZ = 0; // vector pointing to left to help with rotations float leftX = -1; float leftY = 0; float leftZ = 0; // change in position float deltaPosition = 0; // direction of motion char forwardMode = false; char backwardMode = false; // is mouse engaged for view angle movement char mouseEngaged = false; int lastMouseX = screenCenterX; int lastMouseY = screenCenterY; // set to true during recentering of mouse char ignoreEvent = false; // amount to rotate about axis float rotate = 0.0f; // vector which describes the axis to rotate about vec3_t axis = {1.0, 0.0, 0.0}; // global delta rotation, for use with the mouse vec3_t gRot = {0,0,0}; // global total rotation vec3_t gRotNet = {0,0,0}; FILE *logFile; void draw (void) { glPushMatrix (); glRotatef (-rotate, axis[0], axis[1], axis[2]); glTranslatef (-15.0, 10.0, 5.0); // draws radiosity polygons int textID = startTextID; for( int p=0; p -halfPI && gRotNet[0] + gRot[0] < halfPI ) { float oldUpX = upX; float oldUpY = upY; float oldUpZ = upZ; upX += lookX * gRot[0]; upY += lookY * gRot[0]; upZ += lookZ * gRot[0]; // normalize up float invLength = 1.0 / sqrt(upX*upX + upY*upY + upZ*upZ); upX = upX * invLength; upY = upY * invLength; upZ = upZ * invLength; lookX += oldUpX * -gRot[0]; lookY += oldUpY * -gRot[0]; lookZ += oldUpZ * -gRot[0]; // normalize look invLength = 1.0 / sqrt(lookX*lookX + lookY*lookY + lookZ*lookZ); lookX *= invLength; lookY *= invLength; lookZ *= invLength; gRotNet[0] += gRot[0]; } // now rotate left-right // this should by done by rotating all three vectors around y-axis // only X and Z components will change float cosTheta = cos( gRot[1] ); float sinTheta = sin( gRot[1] ); // first, look direction float oldLookX = lookX; float oldLookZ = lookZ; lookX = cosTheta * oldLookX + sinTheta * oldLookZ; lookZ = -sinTheta * oldLookX + cosTheta * oldLookZ; // then, up direction float oldUpX = upX; float oldUpZ = upZ; upX = cosTheta * oldUpX + sinTheta * oldUpZ; upZ = -sinTheta * oldUpX + cosTheta * oldUpZ; gRotNet[1] += gRot[1]; lastUpX = upX; lastUpY = upY; lastUpZ = upZ; lastLookX = lookX; lastLookY = lookY; lastLookZ = lookZ; } gluLookAt( positionX, positionY, positionZ, positionX + lookX, positionY + lookY, positionZ + lookZ, upX, upY, upZ ); draw (); glutSwapBuffers(); } void glutIdle( void ) { glutPostRedisplay(); } char timing = false; // are we timing interval between key strokes? char keyPress = false; // are we in the middle of a key-down session? void glutTimer( int value ) { // NOTE: This seems to rely on keyboard repeat speed.... // would like to find a better method of using keyboard to move // forward and backward in a 3d environment // Want a key-up, key-down event handler, but this is not available in GLUT!!! if( !timing && (backwardMode || forwardMode) ) { timing = true; // wait one more timer cycle glutTimerFunc(FORWARD_MOTION_TIMER, glutTimer, 1); // reset timer return; } if( timing ) { // expire timers and current motion if( backwardMode ) { backwardMode = false; } if( forwardMode ) { forwardMode = false; } timing = false; keyPress = false; } glutPostRedisplay(); } // called on app start and on resize. void glutResize (int w, int h) { winW = w; winH = h; screenCenterX = winW / 2; screenCenterY = winH / 2; invScreenCenterX = 1/ (float)screenCenterX; invScreenCenterY = 1/ (float)screenCenterY; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glViewport( 0, 0, winW, winH ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 90, winW / winH, 1, 9999 ); glutPostRedisplay(); } // Keyboard handler void glutKeyboard (unsigned char key, int x, int y) { switch (key){ case 'q': case 'Q': exit (1); break; case 'o': case 'O': glutFullScreen(); break; case 'e': case 'E': // move forward forwardMode = true; backwardMode = false; if( !keyPress ) { // start of a new key down keyPress = true; glutTimerFunc(FORWARD_MOTION_TIMER, glutTimer, 1); // set timer } timing = false; // reset key timer break; case 'd': case 'D': // move backward //translationZ -= 1; forwardMode = false; backwardMode = true; if( !keyPress ) { // start of a new key down keyPress = true; glutTimerFunc(FORWARD_MOTION_TIMER, glutTimer, 1); // set timer } timing = false; // reset key timer break; case 'a': case 'A': // increase speed speed += 0.1; break; case 's': case 'S': // decrease speed if( speed >= 0.1 ) speed -= 0.1; else speed = 0; break; case 'z': case 'Z': // increase rotation speed rotationSpeed += 0.1; break; case 'x': case 'X': // decrease rotation speed if( rotationSpeed >= 0.1 ) rotationSpeed -= 0.1; else rotationSpeed = 0; break; case 'm': case 'M': if( mouseEngaged ) { glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); // mouse back on to normal mode mouseEngaged = false; ReleaseMouse(); // stop rotation on mouse disengage gRot[0] = 0; gRot[1] = 0; } else { glutSetCursor( GLUT_CURSOR_NONE ); // cursor off, mouse in view control mode mouseEngaged = true; ignoreEvent = true; CaptureMouse(); SetMouse( screenCenterX, screenCenterY ); } break; break; } glutPostRedisplay (); } // Called when the mouse moves in our app area. void glutMotion(int x, int y) { if( mouseEngaged ) { // only change view if mouse in view mode if( ignoreEvent ) { lastMouseX = x; lastMouseY = y; // make sure mouse back in screen area if( x < winW-5 && x > 5 && y < winH-5 && y > 5 ) { ignoreEvent = false; } else { // try centering again, user might be fiesty SetMouse( screenCenterX, screenCenterY ); } return; } gRot[0] = (lastMouseY - y)*rotationSpeed * invScreenCenterY * invMouse; gRot[1] = (lastMouseX - x)*rotationSpeed * invScreenCenterX; lastMouseX = x; lastMouseY = y; glutPostRedisplay (); // watch for mouse hitting edges of screen if( x >= winW-5 || x <= 5 || y >= winH-5 || y <= 5 ) { ignoreEvent = true; SetMouse( screenCenterX, screenCenterY ); } } } void glutEntry( int state ) { // reign mouse in if it leaves window while engaged if( state == GLUT_LEFT && mouseEngaged ) { ignoreEvent = true; SetMouse( screenCenterX, screenCenterY ); } } // Sets up various OpenGL stuff. void glInit (void) { glEnable (GL_DEPTH_TEST); glEnable (GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CW); } int main (void) { logFile = fopen("RadiosGLView.log", "w"); if( loadSettings() != 0 ) { fprintf( logFile, "Settings file %s failed to open\n", SETTINGS_FILE_NAME ); cleanup(); return 2; // settings didn't load } if( fullscreen ) { glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH |GLUT_FULLSCREEN ); glutFullScreen(); } else { glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH |GLUT_MULTISAMPLE); } glutInitWindowSize( winW, winH ); glutCreateWindow( APP_NAME ); glutKeyboardFunc( glutKeyboard ); glutDisplayFunc( glutDisplay ); glutReshapeFunc( glutResize ); glutPassiveMotionFunc( glutMotion ); glutIdleFunc( glutIdle ); glutEntryFunc( glutEntry ); glInit (); initModel(); glutSetCursor( GLUT_CURSOR_NONE ); // cursor off, mouse in view control mode mouseEngaged = true; ignoreEvent = true; CaptureMouse(); SetMouse( screenCenterX, screenCenterY ); glutMainLoop( ); cleanup(); } void cleanup() { fclose(logFile); delete [] modelFileName; } int loadSettings() { FILE *settingsFile = fopen( SETTINGS_FILE_NAME, "r" ); if( settingsFile == NULL ) { return -1; } char *stringBuffer = new char[99]; // assumes that all parameters are in a specific order // read FULLSCREEN setting fscanf( settingsFile, "%s", stringBuffer ); fscanf( settingsFile, "%d", &fullscreen ); // read DITHER setting fscanf( settingsFile, "%s", stringBuffer ); fscanf( settingsFile, "%d", &dithering ); // read SCREENWIDE setting fscanf( settingsFile, "%s", stringBuffer ); fscanf( settingsFile, "%d", &winW ); // read SCREENHIGH setting fscanf( settingsFile, "%s", stringBuffer ); fscanf( settingsFile, "%d", &winH ); screenCenterX = winW / 2; screenCenterY = winH / 2; invScreenCenterX = 1/ (float)screenCenterX; invScreenCenterY = 1/ (float)screenCenterY; // read MODELFILE setting fscanf( settingsFile, "%s", stringBuffer ); fscanf( settingsFile, "%s", modelFileName ); // read INVERTMOUSE setting fscanf( settingsFile, "%s", stringBuffer ); fscanf( settingsFile, "%d", &invMouse ); // convert 0/1 switch to -1/1 needed for inverting mouse if( invMouse == 0 ) invMouse = 1; else invMouse = -1; fclose( settingsFile ); return 0; } void initModel() { UniversalFileIO fileIO; FILE *sceneFile = fopen( modelFileName, "rb" ); if( sceneFile != NULL ) { fprintf( logFile, "Scene file opened.\n"); } else { return; } numPatches = fileIO.freadLong( sceneFile ); fprintf( logFile, "num patches = %d\n", numPatches); for( int v=0; v<3; v++ ) { triangles[v] = new Vertex[numPatches]; textAnchors[v] = new Vertex[numPatches]; } int textID = startTextID; for( int p=0; p #include #include "TextureGL.h" #include "LightingGL.h" #include "minorGems/math/geometry/Transform3D.h" #include "minorGems/graphics/RGBAImage.h" #include "minorGems/graphics/3d/Primitive3D.h" #include "minorGems/graphics/openGL/NoLightingGL.h" // try and include extensions if multitexture isn't // built-in to gl.h #ifndef GL_ARB_multitexture #include #endif /** * OpenGL primitive object. * * Comprised of a triangle mesh, texture map, and anchor points. * * @author Jason Rohrer */ class PrimitiveGL { public: /** * Constructs a PrimitiveGL. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * primitive is destroyed. * * @param inPrimitive the primitive to base this GL version on. */ PrimitiveGL( Primitive3D *inPrimitive ); ~PrimitiveGL(); /** * Draws the primitive (assumes an active openGL screen). * * @param inTransform the transform to perform on the primitive * before drawing it. * @param inLighting the lighting to use when drawing the primitive. */ void draw( Transform3D *inTransform, LightingGL *inLighting ); /** * Gets the number of parameters associated with this primitive. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this primitive. * * @return the number of animations. */ virtual int getNumAnimations(); /** * Sets a parameter for this primative. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this primative. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this primitive forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this primitive. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this primitive. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); protected: Primitive3D *mPrimitive; TextureGL *mTextureGL; // Equivalent to the public draw(), but does manual multi-texturing // by multi-pass rendering. Does not depend on ARB calls. void drawNoMultitexture( Transform3D *inTransform, LightingGL *inLighting ); }; inline PrimitiveGL::PrimitiveGL( Primitive3D *inPrimitive ) : mPrimitive( inPrimitive ) { int numTextures = mPrimitive->mNumTextures; mTextureGL = new TextureGL( numTextures ); for( int i=0; imTexture[i]->getRGBABytes(); mTextureGL->setTextureData( i, rgba, mPrimitive->mTexture[i]->getWidth(), mPrimitive->mTexture[i]->getHeight() ); delete [] rgba; } } inline PrimitiveGL::~PrimitiveGL() { delete mPrimitive; delete mTextureGL; } // this is the ARB version of draw inline void PrimitiveGL::draw( Transform3D *inTransform, LightingGL *inLighting ) { // check for multi-texture availability before proceeding if( !TextureGL::isMultiTexturingSupported() ) { drawNoMultitexture( inTransform, inLighting ); return; } // first, copy the vertices and translate/rotate/scale them Vector3D **worldVertices = new Vector3D*[ mPrimitive->mNumVertices ]; Vector3D **worldNormals = new Vector3D*[ mPrimitive->mNumVertices ]; for( int i=0; imNumVertices; i++ ) { // copy worldVertices[i] = new Vector3D( mPrimitive->mVertices[i] ); worldNormals[i] = new Vector3D( mPrimitive->mNormals[i] ); // translate/rotate/scale inTransform->apply( worldVertices[i] ); // only rotate normals inTransform->applyNoTranslation( worldNormals[i] ); // normalize to get rid of any scaling worldNormals[i]->normalize(); } // now draw vertices as triangle strips mTextureGL->enable(); int numTextureLayers = mTextureGL->getNumLayers(); int t; if( mPrimitive->isTransparent() ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } else { glDisable( GL_BLEND ); } if( mPrimitive->isBackVisible() ) { glDisable( GL_CULL_FACE ); } else { glEnable( GL_CULL_FACE ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } Color *lightColor = new Color( 0, 0, 0, 1.0 ); // for each strip of triangles for( int y=0; ymHigh-1; y++ ) { // note that we skip the last row of verts, since they are the bottom // of the last strip. int thisRow = y * mPrimitive->mWide; int nextRow = ( y + 1 ) * mPrimitive->mWide; glBegin( GL_TRIANGLE_STRIP ); // draw first triangle // first vert in next row int index = nextRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = nextRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // draw next vertex to complete first "rectangle" index = thisRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // then add rest of vertices as part of strip for( int x=2; xmWide; x++ ) { // every additional pair of vertices completes // another "rectangle" index = nextRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); } glEnd(); } mTextureGL->disable(); // cleanup for( int i=0; imNumVertices; i++ ) { delete worldVertices[i]; delete worldNormals[i]; } delete [] worldVertices; delete [] worldNormals; delete lightColor; } // this is the non-ARB version of draw inline void PrimitiveGL::drawNoMultitexture( Transform3D *inTransform, LightingGL *inLighting ) { // first, copy the vertices and translate/rotate/scale them Vector3D **worldVertices = new Vector3D*[ mPrimitive->mNumVertices ]; Vector3D **worldNormals = new Vector3D*[ mPrimitive->mNumVertices ]; for( int i=0; imNumVertices; i++ ) { // copy worldVertices[i] = new Vector3D( mPrimitive->mVertices[i] ); worldNormals[i] = new Vector3D( mPrimitive->mNormals[i] ); // translate/rotate/scale inTransform->apply( worldVertices[i] ); // only rotate normals inTransform->applyNoTranslation( worldNormals[i] ); // normalize to get rid of any scaling worldNormals[i]->normalize(); } Color *lightColor = new Color( 0, 0, 0, 1.0 ); // now draw vertices as triangle strips mTextureGL->enable(); if( mPrimitive->isTransparent() ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } else { glDisable( GL_BLEND ); } if( mPrimitive->isBackVisible() ) { glDisable( GL_CULL_FACE ); } else { glEnable( GL_CULL_FACE ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } // for each strip of triangles for( int y=0; ymHigh-1; y++ ) { // note that we skip the last row of verts, since they are the bottom // of the last strip. int thisRow = y * mPrimitive->mWide; int nextRow = ( y + 1 ) * mPrimitive->mWide; glBegin( GL_TRIANGLE_STRIP ); // draw first triangle // first vert in next row int index = nextRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = nextRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // draw next vertex to complete first "rectangle" index = thisRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // then add rest of vertices as part of strip for( int x=2; xmWide; x++ ) { // every additional pair of vertices completes // another "rectangle" index = nextRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); } glEnd(); } mTextureGL->disable(); // cleanup for( int i=0; imNumVertices; i++ ) { delete worldVertices[i]; delete worldNormals[i]; } delete [] worldVertices; delete [] worldNormals; delete lightColor; } // these all just wrap the functions of the underlying Primitive3D inline int PrimitiveGL::getNumParameters() { return mPrimitive->getNumParameters(); } inline int PrimitiveGL::getNumAnimations() { return mPrimitive->getNumAnimations(); } inline void PrimitiveGL::setParameter( int inParameterIndex, double inValue ) { mPrimitive->setParameter( inParameterIndex, inValue ); } inline double PrimitiveGL::getParameter( int inParameterIndex ) { return mPrimitive->getParameter( inParameterIndex ); } inline void PrimitiveGL::step( double inStepSize ) { mPrimitive->step( inStepSize ); } inline void PrimitiveGL::startAnimation( int inAnimationIndex ) { mPrimitive->startAnimation( inAnimationIndex ); } inline void PrimitiveGL::stopAnimation( int inAnimationIndex ) { mPrimitive->stopAnimation( inAnimationIndex ); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/AmbientLightingGL.h0000644000175000017500000000243107232125073024042 0ustar pabspabs/* * Modification History * * 2001-January-17 Jason Rohrer * Created. */ #ifndef AMBIENT_LIGHTING_GL_INCLUDED #define AMBIENT_LIGHTING_GL_INCLUDED #include "LightingGL.h" /** * LightingGL implementation that uses constant, specifiable * light values everywhere. Most useful when combined with * directional or point lightings using MultiLighting. * * Setting color to full white makes this lighting equivalent * to a NoLightingGL. * * @author Jason Rohrer */ class AmbientLightingGL : public LightingGL{ public: /** * Constructs an AmbientLighting. * * @param inColor color and intensity of lighting. * Is not copied, so cannot be accessed again by caller. */ AmbientLightingGL( Color *inColor ); ~AmbientLightingGL(); // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); private: Color *mColor; }; inline AmbientLightingGL::AmbientLightingGL( Color *inColor ) : mColor( inColor ) { } inline AmbientLightingGL::~AmbientLightingGL() { delete mColor; } inline void AmbientLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { outColor->r = mColor->r; outColor->g = mColor->g; outColor->b = mColor->b; } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/SingleTextureGL.cpp0000644000175000017500000000430111144105001024112 0ustar pabspabs/* * Modification History * * 2005-February-21 Jason Rohrer * Created. * * 2005-August-24 Jason Rohrer * Added control over texture wrapping. */ #include "SingleTextureGL.h" void SingleTextureGL::setTextureData( Image *inImage ) { // first, convert our image to an RGBAImage RGBAImage *rgbaImage = new RGBAImage( inImage ); if( inImage->getNumChannels() < 4 ) { // we should fill in 1.0 for the alpha channel // since the input image doesn't have an alpha channel double *channel = rgbaImage->getChannel( 3 ); int numPixels = inImage->getWidth() * inImage->getHeight(); for( int i=0; igetRGBABytes(); int error; GLenum texFormat = GL_RGBA; glBindTexture( GL_TEXTURE_2D, mTextureID ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error binding to texture id %d, error = %d\n", (int)mTextureID, error ); } glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); if( mRepeat ) { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); } else { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); } glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexImage2D( GL_TEXTURE_2D, 0, texFormat, inImage->getWidth(), inImage->getHeight(), 0, texFormat, GL_UNSIGNED_BYTE, textureData ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error setting texture data for id %d, error = %d, \"%s\"\n", (int)mTextureID, error, glGetString( error ) ); printf( "Perhaps texture image width or height is not a power of 2\n" "Width = %lu, Height = %lu\n", inImage->getWidth(), inImage->getHeight() ); } delete rgbaImage; delete [] textureData; } primrose-6+dfsg1.orig/minorGems/graphics/openGL/MouseHandlerGL.h0000644000175000017500000000226211062511473023364 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. */ #ifndef MOUSE_HANDLER_GL_INCLUDED #define MOUSE_HANDLER_GL_INCLUDED /** * Interface for an object that can field OpenGL mouse events. * * @author Jason Rohrer */ class MouseHandlerGL { public: virtual ~MouseHandlerGL() { } /** * Callback function for when mouse moves. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mouseMoved( int inX, int inY ) = 0; /** * Callback function for when mouse moves with button depressed. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mouseDragged( int inX, int inY ) = 0; /** * Callback function for when the mouse button is depressed. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mousePressed( int inX, int inY ) = 0; /** * Callback function for when the mouse button is released. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mouseReleased( int inX, int inY ) = 0; }; #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/ScreenGL.h0000644000175000017500000003150111101431674022211 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Added compile instructions for Linux to the comments. * * 2001-February-4 Jason Rohrer * Added a function for getting the view angle. * Added support for keyboard up functions. * Added support for redraw listeners. * Added a missing destructor. * * 2001-August-29 Jason Rohrer * Added support for adding and removing mouse, keyboard, and scene handlers. * * 2001-August-30 Jason Rohrer * Fixed some comments. * * 2001-September-15 Jason Rohrer * Added functions for accessing the screen size. * * 2001-October-13 Jason Rohrer * Added a function for applying the view matrix transformation. * * 2001-October-29 Jason Rohrer * Added a private function that checks for focused keyboard handlers. * * 2004-June-11 Jason Rohrer * Added functions for getting/setting view position. * * 2004-June-14 Jason Rohrer * Added comment about need for glutInit call. * * 2006-December-21 Jason Rohrer * Added functions for changing window size and switching to full screen. * * 2008-September-12 Jason Rohrer * Changed to use glutEnterGameMode for full screen at startup. * Added a 2D graphics mode. * * 2008-September-29 Jason Rohrer * Enabled ignoreKeyRepeat. * * 2008-October-27 Jason Rohrer * Prepared for alternate implementations besides GLUT. * Switched to implementation-independent keycodes. * Added support for setting viewport size separate from screen size. */ #ifndef SCREEN_GL_INCLUDED #define SCREEN_GL_INCLUDED #include "MouseHandlerGL.h" #include "KeyboardHandlerGL.h" #include "SceneHandlerGL.h" #include "RedrawListenerGL.h" #include "minorGems/math/geometry/Vector3D.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/util/SimpleVector.h" // prototypes void callbackResize( int inW, int inH ); void callbackKeyboard( unsigned char inKey, int inX, int inY ); void callbackKeyboardUp( unsigned char inKey, int inX, int inY ); void callbackSpecialKeyboard( int inKey, int inX, int inY ); void callbackSpecialKeyboardUp( int inKey, int inX, int inY ); void callbackMotion( int inX, int inY ); void callbackPassiveMotion( int inX, int inY ); void callbackMouse( int inButton, int inState, int inX, int inY ); void callbackDisplay(); void callbackIdle(); /** * Object that handles general initialization of an OpenGL screen. * * @author Jason Rohrer */ class ScreenGL { public: /** * Constructs a ScreenGL. * * GLUT implementation only: * Before calling this constructor, glutInit must be called with * the application's command-line arguments. For example, if * the application's main function looks like: * * int main( int inNumArgs, char **inArgs ) { ... } * * Then you must call glutInit( &inNumArgs, inArgs ) before * constructing a screen. * * SDL implementation: * Must call SDL_Init() with at least SDL_INIT_VIDEO * as a parameter. * * @param inWide width of screen. * @param inHigh height of screen. * @param inFullScreen set to true for full screen mode. * NOTE that full screen mode requires inWide and inHigh to match * an available screen resolution. * @param inWindowName name to be displayed on title bar of window. * @param inKeyHandler object that will receive keyboard events. * NULL specifies no handler (defaults to NULL). * Must be destroyed by caller. * @param inMouseHandler object that will receive mouse events. * NULL specifies no handler (defaults to NULL). * Must be destroyed by caller. * @param inSceneHandler object that will be called to draw * the scene during in response to redraw events. * NULL specifies no handler (defaults to NULL). * Must be destroyed by caller. */ ScreenGL( int inWide, int inHigh, char inFullScreen, char *inWindowName, KeyboardHandlerGL *inKeyHandler = NULL, MouseHandlerGL *inMouseHandler = NULL, SceneHandlerGL *inSceneHandler = NULL ); /** * Destructor closes and releases the screen. */ ~ScreenGL(); /** * Starts the GLUT main loop. * * Note that this function call never returns. */ void start(); /** * Switches to 2D mode, where no view transforms are applied * * Must be called before start(); */ void switchTo2DMode(); /** * Moves the view position. * * @param inPositionChange directional vector describing motion. * Must be destroyed by caller. */ void moveView( Vector3D *inPositionChange ); /** * Rotates the view. * * @param inOrientationChange angle to rotate view by. * Must be destroyed by caller. */ void rotateView( Angle3D *inOrientationChange ); /** * Gets the angle of the current view direction. * * @return the angle of the current view direction. * Not a copy, so shouldn't be modified or destroyed by caller. */ Angle3D *getViewOrientation(); /** * Gets the current view position. * * @return the position of the current view. * Must be destroyed by caller. */ Vector3D *getViewPosition(); /** * Sets the current view position. * * @param inPosition the new position. * Must be destroyed by caller. */ void setViewPosition( Vector3D *inPosition ); /** * Gets the width of the screen. * * @return the width of the screen, in pixels. */ int getWidth(); /** * Gets the height of the screen. * * @return the height of the screen, in pixels. */ int getHeight(); /** * Switches into full screen mode. * * Use changeWindowSize to switch back out of full screen mode. */ void setFullScreen(); /** * Sets the size of the viewport image in the window. * * Defaults to window size. * * Must be called before screen is started. * * @param inWidth, inHeight the new dimensions, in pixels. */ void setImageSize( int inWidth, int inHeight ); /** * Gets the width of the viewport image. * * @return the width of the viewport, in pixels. */ int getImageWidth(); /** * Gets the height of the viewport image. * * @return the height of the viewport, in pixels. */ int getImageHeight(); /** * Change the window size. * * @param inWidth, inHeight the new dimensions, in pixels. */ void changeWindowSize( int inWidth, int inHeight ); /** * Adds a mouse handler. * * @param inHandler the handler to add Must * be destroyed by caller. * * Must not be called after calling start(). */ void addMouseHandler( MouseHandlerGL *inHandler ); /** * Removes a mouse handler. * * @param inHandler the handler to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeMouseHandler( MouseHandlerGL *inHandler ); /** * Adds a keyboard handler. * * @param inHandler the handler to add Must * be destroyed by caller. * * Must not be called after calling start(). */ void addKeyboardHandler( KeyboardHandlerGL *inHandler ); /** * Removes a keyboard handler. * * @param inHandler the handler to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeKeyboardHandler( KeyboardHandlerGL *inHandler ); /** * Adds a scene handler. * * @param inHandler the handler to add Must * be destroyed by caller. * * Must not be called after calling start(). */ void addSceneHandler( SceneHandlerGL *inHandler ); /** * Removes a scene handler. * * @param inHandler the handler to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeSceneHandler( SceneHandlerGL *inHandler ); /** * Adds a redraw listener. * * @param inListener the listener to add. Must * be destroyed by caller. * * Must not be called after calling start(). */ void addRedrawListener( RedrawListenerGL *inListener ); /** * Removes a redraw listener. * * @param inListener the listener to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeRedrawListener( RedrawListenerGL *inListener ); /** * Applies the current view matrix transformation * to the matrix at the top of the GL_PROJECTION stack. */ void applyViewTransform(); /** * Access the various handlers. */ //KeyboardHandlerGL *getKeyHandler(); //MouseHandlerGL *getMouseHandler(); //SceneHandlerGL *getSceneHandler(); private : // used by various implementations // callbacks (external C functions that can access private members) friend void callbackResize( int inW, int inH ); friend void callbackKeyboard( unsigned char inKey, int inX, int inY ); friend void callbackKeyboardUp( unsigned char inKey, int inX, int inY ); friend void callbackSpecialKeyboard( int inKey, int inX, int inY ); friend void callbackSpecialKeyboardUp( int inKey, int inX, int inY ); friend void callbackMotion( int inX, int inY ); friend void callbackPassiveMotion( int inX, int inY ); friend void callbackMouse( int inButton, int inState, int inX, int inY ); friend void callbackDisplay(); friend void callbackIdle(); // our private members int mWide; int mHigh; // for an viewport image that can be smaller than our screen char mImageSizeSet; int mImageWide; int mImageHigh; char mFullScreen; char m2DMode; Vector3D *mViewPosition; // orientation of 0,0,0 means looking in the direction (0,0,1) // with an up direction of (0,1,0) Angle3D *mViewOrientation; // vectors of handlers and listeners SimpleVector *mMouseHandlerVector; SimpleVector *mKeyboardHandlerVector; SimpleVector *mSceneHandlerVector; SimpleVector *mRedrawListenerVector; /** * Gets whether at least one of our keyboard handlers is focused. * * @return true iff at least one keyboard handler is focused. */ char isKeyboardHandlerFocused(); }; inline void ScreenGL::moveView( Vector3D *inPositionChange ) { mViewPosition->add( inPositionChange ); } inline void ScreenGL::rotateView( Angle3D *inOrientationChange ) { mViewOrientation->add( inOrientationChange ); } inline Angle3D *ScreenGL::getViewOrientation() { return mViewOrientation; } inline Vector3D *ScreenGL::getViewPosition() { return new Vector3D( mViewPosition ); } inline void ScreenGL::setViewPosition( Vector3D *inPosition ) { delete mViewPosition; mViewPosition = new Vector3D( inPosition ); } inline int ScreenGL::getWidth() { return mWide; } inline int ScreenGL::getHeight() { return mHigh; } inline void ScreenGL::setImageSize( int inWidth, int inHeight ) { mImageSizeSet = true; mImageWide = inWidth; mImageHigh = inWidth; } inline int ScreenGL::getImageWidth() { return mImageWide; } inline int ScreenGL::getImageHeight() { return mImageHigh; } inline void ScreenGL::addRedrawListener( RedrawListenerGL *inListener ) { mRedrawListenerVector->push_back( inListener ); } inline void ScreenGL::removeRedrawListener( RedrawListenerGL *inListener ) { mRedrawListenerVector->deleteElement( inListener ); } inline void ScreenGL::addMouseHandler( MouseHandlerGL *inListener ) { mMouseHandlerVector->push_back( inListener ); } inline void ScreenGL::removeMouseHandler( MouseHandlerGL *inListener ) { mMouseHandlerVector->deleteElement( inListener ); } inline void ScreenGL::addKeyboardHandler( KeyboardHandlerGL *inListener ) { mKeyboardHandlerVector->push_back( inListener ); } inline void ScreenGL::removeKeyboardHandler( KeyboardHandlerGL *inListener ) { mKeyboardHandlerVector->deleteElement( inListener ); } inline void ScreenGL::addSceneHandler( SceneHandlerGL *inListener ) { mSceneHandlerVector->push_back( inListener ); } inline void ScreenGL::removeSceneHandler( SceneHandlerGL *inListener ) { mSceneHandlerVector->deleteElement( inListener ); } inline char ScreenGL::isKeyboardHandlerFocused() { for( int h=0; hsize(); h++ ) { KeyboardHandlerGL *handler = *( mKeyboardHandlerVector->getElement( h ) ); if( handler->isFocused() ) { return true; } } // else none were focused return false; } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/testNavigatorGL.cpp0000644000175000017500000000102707343255271024171 0ustar pabspabs/* * Modification History * * 2001-August-29 Jason Rohrer * Created. */ #include "TestSceneHandlerGL.h" #include "SceneNavigatorDisplayGL.h" #include "minorGems/util/random/StdRandomSource.h" // simple test function int main() { StdRandomSource *randSource = new StdRandomSource( 2 ); TestSceneHandlerGL *handler = new TestSceneHandlerGL(); char *name = "test window"; SceneNavigatorDisplayGL *screen = new SceneNavigatorDisplayGL( 200, 200, false, name, handler ); screen->start(); return 0; } primrose-6+dfsg1.orig/minorGems/graphics/openGL/SceneNavigatorDisplayGL.h0000644000175000017500000002046107673013511025240 0ustar pabspabs/* * Modification History * * 2001-August-29 Jason Rohrer * Created. * * 2001-August-30 Jason Rohrer * Fixed some comments. * * 2001-October-29 Jason Rohrer * Changed to move and rotate view at a fixed * time rate, regardless of framerate. * * 2003-June-14 Jason Rohrer * Fixed namespace for exit call. * Added M_PI backup definition. */ #ifndef SCENE_NAVIGATOR_DISPLAY_GL_INCLUDED #define SCENE_NAVIGATOR_DISPLAY_GL_INCLUDED #include "ScreenGL.h" #include "MouseHandlerGL.h" #include "KeyboardHandlerGL.h" #include "SceneHandlerGL.h" #include "RedrawListenerGL.h" #include "minorGems/system/Time.h" #include #include // make sure M_PI is defined #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Subclass of ScreenGL that handles general-purpose 3D scene navigation * rendered through OpenGL. * * Motion is unlimited, though forward-backward motion is confinded * to the x-z plane (the user can move up and down explicitly, however). * * To constrict motion, subclass SceneNavigatorDisplayGL and override * the moveView() function (a member of ScreenGL). * * Compile note: For Linux, add these library flags: * -lGL -lglut -lGLU -L/usr/X11R6/lib * Be sure to include ScreenGL.cpp in the file list passed to the compiler. * * @author Jason Rohrer */ class SceneNavigatorDisplayGL : public ScreenGL, public MouseHandlerGL, public KeyboardHandlerGL, public RedrawListenerGL { public: /** * Constructs a navigator. * * @param inWide the width of the screen in pixels. * @param inHigh the height of the screen in pixels. * @param inFullScreen true iff the display should * fill the screen. * @param inWindowName the name of the display window. * @param inSceenHandler the handler responsible for * drawing the scene. * Must be destroyed by caller. * @param inMoveUnitsPerSecond the number of world * units to move per second when the user makes a move. * Defaults to 1.0 units per second. * @param inRotateRadiansPerSecond the number of * radians to rotate per second when the user makes a rotation. * Defaults to 1.0 radians per second. */ SceneNavigatorDisplayGL( int inWide, int inHigh, char inFullScreen, char *inWindowName, SceneHandlerGL *inSceneHandler, double inMoveUnitsPerSecond = 1.0, double inRotateRadiansPerSecond = 1.0 ); ~SceneNavigatorDisplayGL(); // implements the MouseHandlerGL interface virtual void mouseMoved( int inX, int inY ); virtual void mouseDragged( int inX, int inY ); virtual void mousePressed( int inX, int inY ); virtual void mouseReleased( int inX, int inY ); // implements the KeyboardHandlerGL interface virtual void keyPressed( unsigned char inKey, int inX, int inY ); virtual void specialKeyPressed( int inKey, int inX, int inY ); virtual void keyReleased( unsigned char inKey, int inX, int inY ); virtual void specialKeyReleased( int inKey, int inX, int inY ); // implements the RedrawListener interface virtual void fireRedraw(); private : int mLastMouseX, mLastMouseY; // amount to move and rotate view during each redraw Vector3D *mMoveDirection; Angle3D *mRotationOffset; // keep y movement separate from view direction. double mYMovement; // true if a moving key is currently depressed char mMoving; // true if a rotation key is currently depressed char mRotating; unsigned long mTimeLastRedrawS; unsigned long mTimeLastRedrawMS; double mMoveUnitsPerSecond; double mRotateRadiansPerSecond; }; inline SceneNavigatorDisplayGL::SceneNavigatorDisplayGL( int inWide, int inHigh, char inFullScreen, char *inWindowName, SceneHandlerGL *inSceneHandler, double inMoveUnitsPerSecond, double inRotateRadiansPerSecond ) : ScreenGL( inWide, inHigh, inFullScreen, inWindowName, NULL, NULL, inSceneHandler ), mMoveDirection( new Vector3D( 0, 0, 0 ) ), mRotationOffset( new Angle3D( 0, 0, 0 ) ), mMoving( false ), mRotating( false ), mYMovement( 0 ), mMoveUnitsPerSecond( inMoveUnitsPerSecond ), mRotateRadiansPerSecond( inRotateRadiansPerSecond ) { // add ourself to the superclass' listener lists addMouseHandler( this ); addKeyboardHandler( this ); addRedrawListener( this ); Time::getCurrentTime( &mTimeLastRedrawS, &mTimeLastRedrawMS ); } inline void SceneNavigatorDisplayGL::mouseMoved( int inX, int inY ) { //printf( "mouse moved to (%d, %d)\n", inX, inY ); } inline void SceneNavigatorDisplayGL::mouseDragged( int inX, int inY ) { int delX = inX - mLastMouseX; int delY = inY - mLastMouseY; Angle3D *rotAngle = new Angle3D( delY / 50, delX/50, 0 ); //mScreen->rotateView( rotAngle ); delete rotAngle; mLastMouseX = inX; mLastMouseY = inY; } inline void SceneNavigatorDisplayGL::mousePressed( int inX, int inY ) { } inline void SceneNavigatorDisplayGL::mouseReleased( int inX, int inY ) { } inline void SceneNavigatorDisplayGL::keyPressed( unsigned char inKey, int inX, int inY ) { if( inKey == 'y' || inKey == 'Y' ) { // turn view downwards mRotationOffset->mX = M_PI/20; } else if( inKey == 'h' || inKey == 'H' ) { // turn view upwards mRotationOffset->mX = -M_PI/20; } if( inKey == 's' || inKey == 'S' ) { // turn to the left mRotationOffset->mY = M_PI/20; } else if( inKey == 'f' || inKey == 'F' ) { // turn to the right mRotationOffset->mY = -M_PI/20; } if( inKey == 'i' || inKey == 'I' ) { // move upwards mYMovement = 1; } else if( inKey == 'k' || inKey == 'K' ) { // move downwards mYMovement = -1; } if( inKey == 'j' || inKey == 'J' ) { // strafe to the left mMoveDirection->mX = 1; } else if( inKey == 'l' || inKey == 'L' ) { // strafe to the right mMoveDirection->mX = -1; } if( inKey == 'e' || inKey == 'E' ) { // move forward mMoveDirection->mZ = 1; } else if( inKey == 'd' || inKey == 'D' ) { // move backward mMoveDirection->mZ = -1; } else if( inKey == 'q' || inKey == 'Q' ) { // quit ::exit( 0 ); } } inline void SceneNavigatorDisplayGL::keyReleased( unsigned char inKey, int inX, int inY ) { if( inKey == 'e' || inKey == 'E' ) { mMoveDirection->mZ = 0; } else if( inKey == 'd' || inKey == 'D' ) { mMoveDirection->mZ = 0; } if( inKey == 'j' || inKey == 'J' ) { mMoveDirection->mX = 0; } else if( inKey == 'l' || inKey == 'L' ) { mMoveDirection->mX = 0; } if( inKey == 'i' || inKey == 'I' ) { mYMovement = 0; } else if( inKey == 'k' || inKey == 'K' ) { mYMovement = 0; } if( inKey == 's' || inKey == 'S' ) { mRotationOffset->mY = 0; } else if( inKey == 'f' || inKey == 'F' ) { mRotationOffset->mY = 0; } if( inKey == 'y' || inKey == 'Y' ) { mRotationOffset->mX = 0; } else if( inKey == 'h' || inKey == 'H' ) { mRotationOffset->mX = 0; } } inline void SceneNavigatorDisplayGL::specialKeyPressed( int inKey, int inX, int inY ) { } inline void SceneNavigatorDisplayGL::specialKeyReleased( int inKey, int inX, int inY ) { } inline void SceneNavigatorDisplayGL::fireRedraw() { unsigned long currentTimeS; unsigned long currentTimeMS; Time::getCurrentTime( ¤tTimeS, ¤tTimeMS ); unsigned long deltaMS = Time::getMillisecondsSince( mTimeLastRedrawS, mTimeLastRedrawMS ); mTimeLastRedrawS = currentTimeS; mTimeLastRedrawMS = currentTimeMS; // compute the number of units to move to maintain // a constant speed of mUnitsPerSecond double unitsToMove = mMoveUnitsPerSecond * ( deltaMS / 1000.0 ); double radiansToRotate = mRotateRadiansPerSecond * ( deltaMS / 1000.0 ); // scale our rotation offset Angle3D *scaledRotationOffset = new Angle3D( mRotationOffset ); scaledRotationOffset->scale( radiansToRotate ); // rotate the view in the super class rotateView( scaledRotationOffset ); delete scaledRotationOffset; Vector3D *move = new Vector3D( mMoveDirection ); // scale our move direction move->scale( unitsToMove ); Angle3D *rotation = new Angle3D( getViewOrientation() ); // only rotate movement direction about y axis // we don't want view y direction to affect the direction of movement rotation->mX = 0; rotation->mZ = 0; move->rotate( rotation ); delete rotation; // now add in y movement, scaled move->mY = mYMovement * unitsToMove; // move the view in the superclass moveView( move ); delete move; } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/SingleTextureGL.h0000644000175000017500000000713611144105001023570 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * * 2005-February-21 Jason Rohrer * Added comments about channel ordering. * Created a cpp file for static init and longer function definitions. * * 2005-August-24 Jason Rohrer * Added control over texture wrapping. * * 2006-September-20 Jason Rohrer * Changed type of mTextureID to avoid compile warnings on MacOSX. */ #ifndef SINGLE_TEXTURE_GL_INCLUDED #define SINGLE_TEXTURE_GL_INCLUDED #include #include #include #include "minorGems/graphics/Image.h" #include "minorGems/graphics/RGBAImage.h" /** * A single-layer OpenGL 32-bit texture map. * * This is essentially a simplified version of TextureGL. * * @author Jason Rohrer */ class SingleTextureGL { public: /** * Constructs a texture map, specifying texture data. * * Note that this constructor can only be called * after a GL context has been setup. * * @param inImage the image to use as a source * for texture data. The image should have * 4 channels. Any extra channels are ignored, * and black is set into additional texture * channels if inImage has too few channels. * Must be destroyed by caller, and can be * destroyed as soon as this constructor returns. * Channels are ordered as RGBA. * Must be destroyed by caller. * @param inRepeat true to repeat (tile) texture. * Defaults to true. * * Note that width and height must each be powers of 2 and * not larger than 256 (for 3DFX compatability). Additionally, * for 3DFX compatability, the aspect ratio should not exceed 8:1. */ SingleTextureGL( Image *inImage, char inRepeat = true ); /** * The OpenGL texture is deleted when the SingleTextureGL object is * destroyed. */ ~SingleTextureGL(); /** * Sets the data for this texture. * * @param inImage the image to use as a source * for texture data. The image should have * 4 channels. Any extra channels are ignored, * and black is set into additional texture * channels if inImage has too few channels. * Must be destroyed by caller, and can be * destroyed as soon as this constructor returns. * Channels are ordered as RGBA. * Must be destroyed by caller. * * Note that width and height must each be powers of 2 and * not larger than 256 (for 3DFX compatability). Additionally, * for 3DFX compatability, the aspect ratio should not exceed 8:1. */ void setTextureData( Image *inImage ); /** * Enables this texture. */ void enable(); /** * Disables this texture and all of its layers. */ void disable(); private: char mRepeat; GLuint mTextureID; }; inline SingleTextureGL::SingleTextureGL( Image *inImage, char inRepeat ) : mRepeat( inRepeat ) { glGenTextures( 1, &mTextureID ); int error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error generating new texture ID, error = %d, \"%s\"\n", error, glGetString( error ) ); } setTextureData( inImage ); } inline SingleTextureGL::~SingleTextureGL() { glDeleteTextures( 1, &mTextureID ); } inline void SingleTextureGL::enable() { glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, mTextureID ); int error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error binding texture id %d, error = %d\n", (int)mTextureID, error ); } } inline void SingleTextureGL::disable() { glDisable( GL_TEXTURE_2D ); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/ScreenGL_SDL.cpp0000644000175000017500000004310011160574751023255 0ustar pabspabs/* * Modification History * * 2008-October-27 Jason Rohrer * Created. Copied structure from GLUT version (ScreenGL.cpp). * * 2009-March-19 Jason Rohrer * UNICODE support for keyboard input of symbols. */ #include "ScreenGL.h" #include #include #include #include #include #include #include "minorGems/util/stringUtils.h" /* ScreenGL to be accessed by callback functions. * * Note that this is a bit of a hack, but the callbacks * require a C-function (not a C++ member) and have fixed signatures, * so there's no way to pass the current screen into the functions. * * This hack prevents multiple instances of the ScreenGL class from * being used simultaneously. * * Even worse for SLD, because this hack is carried over from GLUT. * SDL doesn't even require C callbacks (you provide the event loop). */ ScreenGL *currentScreenGL; // maps SDL-specific special (non-ASCII) key-codes (SDLK) to minorGems key // codes (MG_KEY) int mapSDLSpecialKeyToMG( int inSDLKey ); // for ascii key char mapSDLKeyToASCII( int inSDLKey ); // prototypes /* void callbackResize( int inW, int inH ); void callbackKeyboard( unsigned char inKey, int inX, int inY ); void callbackMotion( int inX, int inY ); void callbackPassiveMotion( int inX, int inY ); void callbackMouse( int inButton, int inState, int inX, int inY ); void callbackDisplay(); void callbackIdle(); */ ScreenGL::ScreenGL( int inWide, int inHigh, char inFullScreen, char *inWindowName, KeyboardHandlerGL *inKeyHandler, MouseHandlerGL *inMouseHandler, SceneHandlerGL *inSceneHandler ) : mWide( inWide ), mHigh( inHigh ), mImageWide( inWide ), mImageHigh( inHigh ), mFullScreen( inFullScreen ), m2DMode( false ), mViewPosition( new Vector3D( 0, 0, 0 ) ), mViewOrientation( new Angle3D( 0, 0, 0 ) ), mMouseHandlerVector( new SimpleVector() ), mKeyboardHandlerVector( new SimpleVector() ), mSceneHandlerVector( new SimpleVector() ), mRedrawListenerVector( new SimpleVector() ) { // add handlers if NULL (the default) was not passed in for them if( inMouseHandler != NULL ) { addMouseHandler( inMouseHandler ); } if( inKeyHandler != NULL ) { addKeyboardHandler( inKeyHandler ); } if( inSceneHandler != NULL ) { addSceneHandler( inSceneHandler ); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); int flags = SDL_OPENGL; if( mFullScreen ) { flags = flags | SDL_FULLSCREEN; } // current color depth SDL_Surface *screen = SDL_SetVideoMode( mWide, mHigh, 0, flags); if ( screen == NULL ) { printf( "Couldn't set %dx%d GL video mode: %s\n", mWide, mHigh, SDL_GetError() ); } SDL_WM_SetCaption( inWindowName, NULL ); // turn off repeat SDL_EnableKeyRepeat( 0, 0 ); SDL_EnableUNICODE( true ); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } ScreenGL::~ScreenGL() { delete mViewPosition; delete mViewOrientation; delete mRedrawListenerVector; delete mMouseHandlerVector; delete mKeyboardHandlerVector; delete mSceneHandlerVector; } void ScreenGL::start() { currentScreenGL = this; // call our resize callback (GLUT used to do this for us when the // window was created) callbackResize( mWide, mHigh ); // main loop while( true ) { callbackDisplay(); // handle all pending events SDL_Event event; while( SDL_PollEvent( &event ) ) { switch( event.type ) { case SDL_KEYDOWN: case SDL_KEYUP: { int mouseX, mouseY; SDL_GetMouseState( &mouseX, &mouseY ); // check if special key int mgKey = mapSDLSpecialKeyToMG( event.key.keysym.sym ); if( mgKey != 0 ) { if( event.type == SDL_KEYDOWN ) { callbackSpecialKeyboard( mgKey, mouseX, mouseY ); } else { callbackSpecialKeyboardUp( mgKey, mouseX, mouseY ); } } else { char asciiKey; // try unicode first if( ( event.key.keysym.unicode & 0xFF80 ) == 0 ) { asciiKey = event.key.keysym.unicode & 0x7F; } else { // else unicode-to-ascii failed // fall back asciiKey = mapSDLKeyToASCII( event.key.keysym.sym ); } if( asciiKey != 0 ) { // shift and caps cancel each other if( ( ( event.key.keysym.mod & KMOD_SHIFT ) && !( event.key.keysym.mod & KMOD_CAPS ) ) || ( !( event.key.keysym.mod & KMOD_SHIFT ) && ( event.key.keysym.mod & KMOD_CAPS ) ) ) { asciiKey = toupper( asciiKey ); } if( event.type == SDL_KEYDOWN ) { callbackKeyboard( asciiKey, mouseX, mouseY ); } else { callbackKeyboardUp( asciiKey, mouseX, mouseY ); } } } } break; case SDL_MOUSEMOTION: if( event.motion.state & SDL_BUTTON( 1 ) || event.motion.state & SDL_BUTTON( 2 ) || event.motion.state & SDL_BUTTON( 3 ) ) { callbackMotion( event.motion.x, event.motion.y ); } else { callbackPassiveMotion( event.motion.x, event.motion.y ); } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: callbackMouse( event.button.button, event.button.state, event.button.x, event.button.y ); break; } } } } void ScreenGL::switchTo2DMode() { m2DMode = true; } void ScreenGL::setFullScreen() { //glutFullScreen(); } void ScreenGL::changeWindowSize( int inWidth, int inHeight ) { //glutReshapeWindow( inWidth, inHeight ); } void ScreenGL::applyViewTransform() { // compute view angle // default angle is 90, but we want to force a 1:1 aspect ratio to avoid // distortion. // If our screen's width is different than its height, we need to decrease // the view angle so that the angle coresponds to the smaller dimension. // This keeps the zoom factor constant in the smaller dimension. // Of course, because of the way perspective works, only one Z-slice // will have a constant zoom factor // The zSlice variable sets the distance of this slice from the picture // plane double zSlice = .31; double maxDimension = mWide; if( mHigh > mWide ) { maxDimension = mHigh; } double aspectDifference = fabs( mWide / 2 - mHigh / 2 ) / maxDimension; // default angle is 90 degrees... half the angle is PI/4 double angle = atan( tan( M_PI / 4 ) + aspectDifference / zSlice ); // double it to get the full angle angle *= 2; // convert to degrees angle = 360 * angle / ( 2 * M_PI ); // set up the projection matrix glMatrixMode( GL_PROJECTION ); glLoadIdentity(); //gluPerspective( 90, mWide / mHigh, 1, 9999 ); gluPerspective( angle, 1, 1, 9999 ); // set up the model view matrix glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); // create default view and up vectors, // then rotate them by orientation angle Vector3D *viewDirection = new Vector3D( 0, 0, 1 ); Vector3D *upDirection = new Vector3D( 0, 1, 0 ); viewDirection->rotate( mViewOrientation ); upDirection->rotate( mViewOrientation ); // get a point out in front of us in the view direction viewDirection->add( mViewPosition ); // look at takes a viewer position, // a point to look at, and an up direction gluLookAt( mViewPosition->mX, mViewPosition->mY, mViewPosition->mZ, viewDirection->mX, viewDirection->mY, viewDirection->mZ, upDirection->mX, upDirection->mY, upDirection->mZ ); delete viewDirection; delete upDirection; } void callbackResize( int inW, int inH ) { ScreenGL *s = currentScreenGL; s->mWide = inW; s->mHigh = inH; int bigDimension = s->mImageWide; if( bigDimension < s->mImageHigh ) { bigDimension = s->mImageHigh; } int excessW = s->mWide - bigDimension; int excessH = s->mHigh - bigDimension; // viewport is square of biggest image dimension, centered on screen glViewport( excessW / 2, excessH / 2, bigDimension, bigDimension ); } void callbackKeyboard( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyPressed( inKey, inX, inY ); } } } void callbackKeyboardUp( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyReleased( inKey, inX, inY ); } } } void callbackSpecialKeyboard( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyPressed( inKey, inX, inY ); } } } void callbackSpecialKeyboardUp( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyReleased( inKey, inX, inY ); } } } void callbackMotion( int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseDragged( inX, inY ); } } void callbackPassiveMotion( int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseMoved( inX, inY ); } } void callbackMouse( int inButton, int inState, int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseMoved( inX, inY ); if( inState == SDL_PRESSED ) { handler->mousePressed( inX, inY ); } else if( inState == SDL_RELEASED ) { handler->mouseReleased( inX, inY ); } else { printf( "Error: Unknown mouse state received from SDL\n" ); } } } void callbackDisplay() { ScreenGL *s = currentScreenGL; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // fire to all redraw listeners // do this first so that they can update our view transform // this makes control much more responsive for( int r=0; rmRedrawListenerVector->size(); r++ ) { RedrawListenerGL *listener = *( s->mRedrawListenerVector->getElement( r ) ); listener->fireRedraw(); } if( ! s->m2DMode ) { // apply our view transform s->applyViewTransform(); } // fire to all handlers for( int h=0; hmSceneHandlerVector->size(); h++ ) { SceneHandlerGL *handler = *( currentScreenGL->mSceneHandlerVector->getElement( h ) ); handler->drawScene(); } SDL_GL_SwapBuffers(); } void callbackIdle() { //glutPostRedisplay(); } int mapSDLSpecialKeyToMG( int inSDLKey ) { switch( inSDLKey ) { case SDLK_F1: return MG_KEY_F1; case SDLK_F2: return MG_KEY_F2; case SDLK_F3: return MG_KEY_F3; case SDLK_F4: return MG_KEY_F4; case SDLK_F5: return MG_KEY_F5; case SDLK_F6: return MG_KEY_F6; case SDLK_F7: return MG_KEY_F7; case SDLK_F8: return MG_KEY_F8; case SDLK_F9: return MG_KEY_F9; case SDLK_F10: return MG_KEY_F10; case SDLK_F11: return MG_KEY_F11; case SDLK_F12: return MG_KEY_F12; case SDLK_LEFT: return MG_KEY_LEFT; case SDLK_UP: return MG_KEY_UP; case SDLK_RIGHT: return MG_KEY_RIGHT; case SDLK_DOWN: return MG_KEY_DOWN; case SDLK_PAGEUP: return MG_KEY_PAGE_UP; case SDLK_PAGEDOWN: return MG_KEY_PAGE_DOWN; case SDLK_HOME: return MG_KEY_HOME; case SDLK_END: return MG_KEY_END; case SDLK_INSERT: return MG_KEY_INSERT; default: return 0; } } char mapSDLKeyToASCII( int inSDLKey ) { switch( inSDLKey ) { case SDLK_UNKNOWN: return 0; case SDLK_BACKSPACE: return 8; case SDLK_TAB: return 9; case SDLK_CLEAR: return 12; case SDLK_RETURN: return 13; case SDLK_PAUSE: return 19; case SDLK_ESCAPE: return 27; case SDLK_SPACE: return ' '; case SDLK_EXCLAIM: return '!'; case SDLK_QUOTEDBL: return '"'; case SDLK_HASH: return '#'; case SDLK_DOLLAR: return '$'; case SDLK_AMPERSAND: return '&'; case SDLK_QUOTE: return '\''; case SDLK_LEFTPAREN: return '('; case SDLK_RIGHTPAREN: return ')'; case SDLK_ASTERISK: return '*'; case SDLK_PLUS: return '+'; case SDLK_COMMA: return ','; case SDLK_MINUS: return '-'; case SDLK_PERIOD: return '.'; case SDLK_SLASH: return '/'; case SDLK_0: return '0'; case SDLK_1: return '1'; case SDLK_2: return '2'; case SDLK_3: return '3'; case SDLK_4: return '4'; case SDLK_5: return '5'; case SDLK_6: return '6'; case SDLK_7: return '7'; case SDLK_8: return '8'; case SDLK_9: return '9'; case SDLK_COLON: return ':'; case SDLK_SEMICOLON: return ';'; case SDLK_LESS: return '<'; case SDLK_EQUALS: return '='; case SDLK_GREATER: return '>'; case SDLK_QUESTION: return '?'; case SDLK_AT: return '@'; case SDLK_LEFTBRACKET: return '['; case SDLK_BACKSLASH: return '\\'; case SDLK_RIGHTBRACKET: return ']'; case SDLK_CARET: return '^'; case SDLK_UNDERSCORE: return '_'; case SDLK_BACKQUOTE: return '`'; case SDLK_a: return 'a'; case SDLK_b: return 'b'; case SDLK_c: return 'c'; case SDLK_d: return 'd'; case SDLK_e: return 'e'; case SDLK_f: return 'f'; case SDLK_g: return 'g'; case SDLK_h: return 'h'; case SDLK_i: return 'i'; case SDLK_j: return 'j'; case SDLK_k: return 'k'; case SDLK_l: return 'l'; case SDLK_m: return 'm'; case SDLK_n: return 'n'; case SDLK_o: return 'o'; case SDLK_p: return 'p'; case SDLK_q: return 'q'; case SDLK_r: return 'r'; case SDLK_s: return 's'; case SDLK_t: return 't'; case SDLK_u: return 'u'; case SDLK_v: return 'v'; case SDLK_w: return 'w'; case SDLK_x: return 'x'; case SDLK_y: return 'y'; case SDLK_z: return 'z'; case SDLK_DELETE: return 127; default: return 0; } } primrose-6+dfsg1.orig/minorGems/graphics/openGL/TestSceneHandlerGL.h0000644000175000017500000000275007343452732024204 0ustar pabspabs/* * Modification History * * 2001-August-29 Jason Rohrer * Created. * * 2001-August-30 Jason Rohrer * Added random triangels for testing. */ #ifndef TEST_SCENE_HANDLER_GL_INCLUDED #define TEST_SCENE_HANDLER_GL_INCLUDED #include #include "SceneHandlerGL.h" #include "minorGems/util/random/StdRandomSource.h" /** * A test scene implementation. * * @author Jason Rohrer */ class TestSceneHandlerGL : public SceneHandlerGL { public: // implements the SceneHandlerGL interface virtual void drawScene(); }; void TestSceneHandlerGL::drawScene() { glDisable( GL_TEXTURE_2D ); glDisable( GL_CULL_FACE ); StdRandomSource source( 0 ); glBegin( GL_TRIANGLES ); { for( int i=0; i<10; i++ ) { glColor4f( source.getRandomFloat(), source.getRandomFloat(), source.getRandomFloat(), 1.0 ); glVertex3f( source.getRandomFloat() * 100, source.getRandomFloat() * 100, source.getRandomFloat() * 100 ); glColor4f( source.getRandomFloat(), source.getRandomFloat(), source.getRandomFloat(), 1.0 ); glVertex3f( source.getRandomFloat() * 100, source.getRandomFloat() * 100, source.getRandomFloat() * 100 ); glColor4f( source.getRandomFloat(), source.getRandomFloat(), source.getRandomFloat(), 1.0 ); glVertex3f( source.getRandomFloat() * 100, source.getRandomFloat() * 100, source.getRandomFloat() * 100 ); } } glEnd(); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/ObjectGL.h0000644000175000017500000001172507253777626022235 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. * * 2001-January-6 Jason Rohrer * Added some missing includes. * * 2001-January-16 Jason Rohrer * Changed to use a Transform3D instead of Vectors, Angles, and scales for * each primitive in the object. Changed draw() function to take a Transform3D. * Fixed a memory leak in the draw() function. * * 2001-March-14 Jason Rohrer * Added support for paramatization and temporal animations. */ #ifndef OBJECT_GL_INCLUDED #define OBJECT_GL_INCLUDED #include #include "PrimitiveGL.h" #include "LightingGL.h" #include "minorGems/math/geometry/Transform3D.h" #include "minorGems/graphics/3d/Object3D.h" /** * OpenGL object. * * Comprised of a collection of primitives. * * @author Jason Rohrer */ class ObjectGL { public: /** * Constructs an Object. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * object is destroyed. * * @param inObject the Object3D to base this GL version on. */ ObjectGL( Object3D *inObject ); ~ObjectGL(); /** * Draws the object. * * @param inTransform the transform to apply to the object before * drawing it. * @param inLighting the lighting to use when drawing the object. */ void draw( Transform3D *inTransform, LightingGL *inLighting ); /** * Gets the number of parameters associated with this object. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this object. * * @return the number of animations. */ virtual int getNumAnimations(); /** * Sets a parameter for this object. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this object. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this object forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this object. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this object. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); private: Object3D *mObject; // GL versions of the primitives PrimitiveGL **mPrimitives; }; inline ObjectGL::ObjectGL( Object3D *inObject ) : mObject( inObject ) { mPrimitives = new PrimitiveGL*[ mObject->mNumPrimitives ]; for( int i=0; imNumPrimitives; i++ ) { mPrimitives[i] = new PrimitiveGL( mObject->mPrimitives[i] ); } } inline ObjectGL::~ObjectGL() { for( int i=0; imNumPrimitives; i++ ) { delete mPrimitives[i]; } delete [] mPrimitives; delete mObject; } inline void ObjectGL::draw( Transform3D *inTransform, LightingGL *inLighting ) { for( int i=0; imNumPrimitives; i++ ) { // need to transform the position of primitive within object // copy the transform for this primitive Transform3D *primTransform = new Transform3D( mObject->mTransform[i] ); // add the object transform to the end of it primTransform->transform( inTransform ); mPrimitives[i]->draw( primTransform, inLighting ); delete primTransform; } } // these just pass the function call on to the underlying Object3D inline int ObjectGL::getNumParameters() { return mObject->getNumParameters(); } inline int ObjectGL::getNumAnimations() { return mObject->getNumAnimations(); } inline void ObjectGL::setParameter( int inParameterIndex, double inValue ) { mObject->setParameter( inParameterIndex, inValue ); } inline double ObjectGL::getParameter( int inParameterIndex ) { return mObject->getParameter( inParameterIndex ); } inline void ObjectGL::step( double inStepSize ) { mObject->step( inStepSize ); } inline void ObjectGL::startAnimation( int inAnimationIndex ) { mObject->startAnimation( inAnimationIndex ); } inline void ObjectGL::stopAnimation( int inAnimationIndex ) { mObject->stopAnimation( inAnimationIndex ); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/testNavigatorGLcompile0000755000175000017500000000030207343255360024756 0ustar pabspabsg++ -g -o testNavigatorGL -I/usr/X11R6/include -I../../.. -L/usr/X11R6/lib -lGL -lglut -lGLU -lX11 -lXi -lXext -lXmu ScreenGL.cpp testNavigatorGL.cpp ../../../minorGems/io/linux/TypeIOLinux.cpp primrose-6+dfsg1.orig/minorGems/graphics/openGL/MultiLightingGL.h0000644000175000017500000000441507220445427023566 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. */ #ifndef MULTI_LIGHTING_GL_INCLUDED #define MULTI_LIGHTING_GL_INCLUDED #include #include "LightingGL.h" #include "minorGems/util/SimpleVector.h" /** * A LightingGL implementation that contains a collection of * LightingGLs. * * @author Jason Rohrer */ class MultiLightingGL : public LightingGL { public: /** * Constructs a MultiLighting. */ MultiLightingGL(); ~MultiLightingGL(); /** * Adds a lighting to this MultiLighting. * * @param inLighting lighting to add. Is not * destroyed when the MultiLighting is destroyed. */ void addLighting( LightingGL *inLighting ); /** * Removes a lighting to this MultiLighting. * * @param inLighting lighting to remove. */ void removeLighting( LightingGL *inLighting ); // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); private: SimpleVector *mLightingVector; }; inline MultiLightingGL::MultiLightingGL() : mLightingVector( new SimpleVector() ) { } inline MultiLightingGL::~MultiLightingGL() { delete mLightingVector; } inline void MultiLightingGL::addLighting( LightingGL *inLighting ) { mLightingVector->push_back( inLighting ); } inline void MultiLightingGL::removeLighting( LightingGL *inLighting ) { mLightingVector->deleteElement( inLighting ); } inline void MultiLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { int numLightings = mLightingVector->size(); outColor->r = 0; outColor->g = 0; outColor->b = 0; // sum lighting contributions from each lighting for( int i=0; igetElement( i ) ); thisLighting->getLighting( inPoint, inNormal, tempColor ); outColor->r += tempColor->r; outColor->g += tempColor->g; outColor->b += tempColor->b; delete tempColor; } // clip color components: if( outColor->r > 1.0 ) { outColor->r = 1.0; } if( outColor->g > 1.0 ) { outColor->g = 1.0; } if( outColor->b > 1.0 ) { outColor->b = 1.0; } } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/DirectionLightingGL.h0000644000175000017500000000331007220445427024405 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. */ #ifndef DIRECTION_LIGHTING_GL_INCLUDED #define DIRECTION_LIGHTING_GL_INCLUDED #include #include "LightingGL.h" /** * A LightingGL implementation with a single point light source * at distance infinity. * * @author Jason Rohrer */ class DirectionLightingGL : public LightingGL { public: /** * Constructs a DirectionLighting. * * @param inColor color of lighting for a surface * that is facing directly into the light source. * Is not copied, so cannot be accessed again by caller. * @param inDirection incoming direction of light source. * Is not copied, so cannot be accessed again by caller. */ DirectionLightingGL( Color *inColor, Vector3D *inDirection ); ~DirectionLightingGL(); // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); private: Color *mColor; // direction pointing *towards* light source Vector3D *mDirection; }; inline DirectionLightingGL::DirectionLightingGL( Color *inColor, Vector3D *inDirection ) : mColor( inColor ), mDirection( inDirection ) { // reverse the passed-in direction mDirection->scale( -1 ); } inline DirectionLightingGL::~DirectionLightingGL() { delete mColor; delete mDirection; } inline void DirectionLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { double dot = inNormal->dot( mDirection ); if( dot > 0 ) { outColor->r = mColor->r * dot; outColor->g = mColor->g * dot; outColor->b = mColor->b * dot; } else { outColor->r = 0; outColor->g = 0; outColor->b = 0; } } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/KeyboardHandlerGL.h0000644000175000017500000000723411101363573024040 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-February-4 Jason Rohrer * Added key release functions. * * 2001-October-29 Jason Rohrer * Added fuction for querying a handler's focus. * * 2008-October-27 Jason Rohrer * Switched to implementation-independent keycodes. */ #ifndef KEYBOARD_HANDLER_GL_INCLUDED #define KEYBOARD_HANDLER_GL_INCLUDED // special key codes #define MG_KEY_F1 0x0001 #define MG_KEY_F2 0x0002 #define MG_KEY_F3 0x0003 #define MG_KEY_F4 0x0004 #define MG_KEY_F5 0x0005 #define MG_KEY_F6 0x0006 #define MG_KEY_F7 0x0007 #define MG_KEY_F8 0x0008 #define MG_KEY_F9 0x0009 #define MG_KEY_F10 0x000A #define MG_KEY_F11 0x000B #define MG_KEY_F12 0x000C #define MG_KEY_LEFT 0x0064 #define MG_KEY_UP 0x0065 #define MG_KEY_RIGHT 0x0066 #define MG_KEY_DOWN 0x0067 #define MG_KEY_PAGE_UP 0x0068 #define MG_KEY_PAGE_DOWN 0x0069 #define MG_KEY_HOME 0x006A #define MG_KEY_END 0x006B #define MG_KEY_INSERT 0x006C /** * Interface for an object that can field OpenGL keystrokes. * * @author Jason Rohrer */ class KeyboardHandlerGL { public: virtual ~KeyboardHandlerGL() { } /** * Gets whether this handler is focused (in other words, * whether this handler wants to reserve keyboard * events for itself). * * If no registered handler is focused, then all * registered handlers receive keyboard events. However, * if some handlers are focused, then only focused handlers * receive keyboard events. * * Note that in general, handlers should be unfocused. * A default implementation is included in this interface, * so handlers that do not care about focus can ignore * this function. * * @return true iff this handler is focused. */ virtual char isFocused(); /** * Callback function for when an ASCII-representable key is pressed. * * @param inKey ASCII representation of the pressed key. * @param inX x position of mouse when key was pressed. * @param inY y position of mouse when key was pressed. */ virtual void keyPressed( unsigned char inKey, int inX, int inY ) = 0; /** * Callback function for when an ASCII-representable key is released. * * @param inKey ASCII representation of the released key. * @param inX x position of mouse when key was released. * @param inY y position of mouse when key was released. */ virtual void keyReleased( unsigned char inKey, int inX, int inY ) = 0; /** * Callback function for when an special key is pressed. * * @param inKey integer constant representation of the pressed key. * @param inX x position of mouse when key was pressed. * @param inY y position of mouse when key was pressed. */ virtual void specialKeyPressed( int inKey, int inX, int inY ) = 0; /** * Callback function for when an special key is released. * * @param inKey integer constant representation of the released key. * @param inX x position of mouse when key was released. * @param inY y position of mouse when key was released. */ virtual void specialKeyReleased( int inKey, int inX, int inY ) = 0; }; inline char KeyboardHandlerGL::isFocused() { return false; } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/testScreenGL.cpp0000644000175000017500000000113607236561234023457 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-February-2 Jason Rohrer * Fixed the random seed for testing. */ #include "TestHandlerGL.h" #include "ScreenGL.h" #include "minorGems/util/random/StdRandomSource.h" // simple test function int main() { StdRandomSource *randSource = new StdRandomSource( 2 ); TestHandlerGL *handler = new TestHandlerGL( randSource, 30 ); char *name = "test window"; ScreenGL *screen = new ScreenGL( 200, 200, false, name, handler, handler, handler ); handler->setupPrimitives(); screen->start(); } primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/0000755000175000017500000000000011201637527021170 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/glGUITest.cpp0000644000175000017500000000755407351520325023514 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * Added support for testing ButtonGL. * * 2001-September-16 Jason Rohrer * Added support for testing StickyButtonGL. * Added support for testing MultiButtonGL. * Added support for testing MouseCursorRegionGL. * * 2001-September-16 Jason Rohrer * Added support for testing SliderGL. */ #include "SliderGL.h" #include "MouseCursorRegionGL.h" #include "MultiButtonGL.h" #include "GUIPanelGL.h" #include "GUIContainerGL.h" #include "GUITranslatorGL.h" #include "ButtonGL.h" #include "StickyButtonGL.h" #include "minorGems/graphics/Color.h" #include "minorGems/graphics/openGL/ScreenGL.h" #include "minorGems/graphics/converters/BMPImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" // prototype /** * Loads an image from a BMP file. * * @param inFileName the name of the file to load from. * * @return the loaded image, or NULL if reading from the file fails. */ Image *loadBMPImage( char *inFileName ); // a test program for gl-based guis int main() { Image *buttonUpImage = loadBMPImage( "test.bmp" ); if( buttonUpImage == NULL ) { printf( "image loading failed.\n" ); return 1; } Image *buttonDownImage = loadBMPImage( "test2.bmp" ); if( buttonUpImage == NULL ) { printf( "image loading failed.\n" ); return 1; } Image *sliderImage = loadBMPImage( "test3.bmp" ); if( sliderImage == NULL ) { printf( "image loading failed.\n" ); return 1; } // construct the screen first so that other GL calls work ScreenGL *screen = new ScreenGL( 400, 300, false, "Test GL GUI" ); // construct a button with these images ButtonGL *button = new ButtonGL( 0.45, 0.45, 0.1, 0.1, buttonUpImage, buttonDownImage ); StickyButtonGL *stickyButton = new StickyButtonGL( 0.45, 0.56, 0.1, 0.1, buttonUpImage->copy(), buttonDownImage->copy() ); int numMultiButton = 4; Image **pressedImages = new Image*[numMultiButton]; Image **unpressedImages = new Image*[numMultiButton]; for( int i=0; icopy(); unpressedImages[i] = buttonUpImage->copy(); } double gutterFraction = 0.125; MultiButtonGL *multiButton = new MultiButtonGL( 0.4, 0.67, 0.2, 0.2, numMultiButton, unpressedImages, pressedImages, gutterFraction ); SliderGL *slider = new SliderGL( 0.35, 0.34, 0.3, 0.1, sliderImage, 0.33333, new Color( 0, 0, 0), new Color( 1.0f, 0, 0 ), new Color( 0.5f, 0.5f, 0.5f ), new Color( 0.6f, 0.6f, 0.6f ) ); GUIContainerGL *container = new GUIContainerGL( 0, 0, 1, 1 ); GUITranslatorGL *translator = new GUITranslatorGL( container, screen ); screen->addRedrawListener( translator ); screen->addMouseHandler( translator ); GUIPanelGL *panel = new GUIPanelGL( 0.25, 0.25, 0.5, 0.7, new Color( 0.25f, 0.25f, 0.25f ) ); panel->add( button ); panel->add( stickyButton ); panel->add( multiButton ); panel->add( slider ); container->add( panel ); MouseCursorRegionGL *cursor = new MouseCursorRegionGL( 0, 0, 1.0, 1.0, 0.125, new Color( 0, 0, 1.0f ), new Color( 0, 0, .75f ) ); container->add( cursor ); GUIPanelGL *panel2 = new GUIPanelGL( 0, 0, 0.25, 1, new Color( 0, 1.0f, 0 ) ); container->add( panel2 ); container->add( cursor ); screen->start(); delete translator; // this deletes container too delete screen; return 0; } Image *loadBMPImage( char *inFileName ) { // load images for the button File *imageFile = new File( NULL, inFileName, strlen( inFileName ) ); FileInputStream *imageStream = new FileInputStream( imageFile ); BMPImageConverter *converter = new BMPImageConverter(); Image *returnImage = converter->deformatImage( imageStream ); delete imageFile; delete imageStream; delete converter; return returnImage; } primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/LabelGL.h0000644000175000017500000000550711071025205022577 0ustar pabspabs/* * Modification History * * 2001-October-13 Jason Rohrer * Created. * * 2001-October-29 Jason Rohrer * Added a missing destructor. * * 2006-December-19 Jason Rohrer * Made destructor virtual. * * 2008-October-1 Jason Rohrer * Added function for getting TextGL. */ #ifndef LABEL_GL_INCLUDED #define LABEL_GL_INCLUDED #include "GUIComponentGL.h" #include "TextGL.h" /** * A text label for OpenGL-based GUIs. * * @author Jason Rohrer */ class LabelGL : public GUIComponentGL { public: /** * Constructs a label. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inString the text to display in this label. * Is copied internally, so must be destroyed * by caller if not const. * @param inText the text object to use when drawing * this label. Must be destroyed by caller after * this class is destroyed. */ LabelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, char *inString, TextGL *inText ); virtual ~LabelGL(); /** * Sets the text displayed by this label. * * @param inString the text to display in this label. * Is copied internally, so must be destroyed * by caller if not const. */ void setText( char *inString ); /** * Gets the text displayed by this label. * * @return the text to display in this label. * Must not be destroyed or modified by caller. */ char *getText(); /** * Gets the TextGL object used to draw this label. * * @return the TextGL object. * Must not be destroyed by caller until after this class is * destroyed. */ TextGL *getTextGL() { return mText; } // override fireRedraw in GUIComponentGL virtual void fireRedraw(); protected: TextGL *mText; char *mString; }; inline LabelGL::LabelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, char *inString, TextGL *inText ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mText( inText ), mString( NULL ) { setText( inString ); } inline LabelGL::~LabelGL() { if( mString != NULL ) { delete [] mString; } } inline void LabelGL::setText( char *inString ) { if( mString != NULL ) { delete [] mString; } int length = strlen( inString ) + 1; mString = new char[ length ]; memcpy( mString, inString, length ); } inline char *LabelGL::getText() { return mString; } inline void LabelGL::fireRedraw() { mText->drawText( mString, mAnchorX, mAnchorY, mWidth, mHeight ); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/GUIComponentGL.h0000644000175000017500000001414411071025065024070 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * Changed to use normalized floating point coordinates. * Fixed some compile bugs. * Changed to extend the GUIComponent class. * * 2001-October-29 Jason Rohrer * Added support for focus. * * 2006-July-4 Jason Rohrer * Added support for disabled components. * * 2008-October-1 Jason Rohrer * Added position changing and gettting functions. */ #ifndef GUI_COMPONENT_GL_INCLUDED #define GUI_COMPONENT_GL_INCLUDED #include "minorGems/graphics/openGL/RedrawListenerGL.h" #include "minorGems/ui/GUIComponent.h" /** * A base class for all OpenGL GUI components. * * Note that all coordinates are specified in a normalized * [0,1.0] space, where the screen is spanned by this [0,1.0] range. * * @author Jason Rohrer */ class GUIComponentGL : public GUIComponent, public RedrawListenerGL { public: virtual ~GUIComponentGL(); /** * Sets the position of this component. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. */ void setPosition( double inAnchorX, double inAnchorY, double inWidth, double inHeight ); // functions for getting position double getAnchorX() { return mAnchorX; } double getAnchorY() { return mAnchorY; } double getWidth() { return mWidth; } double getHeight() { return mHeight; } /** * Sets the enabled state of this component. * * @param inEnabled true to enable, or false to disable. */ virtual void setEnabled( char inEnabled ); /** * Gets the enabled state of this component. * * @return true to enable, or false to disable. */ virtual char isEnabled(); /** * Tests whether a point is inside this component. * * @param inX the x value to check. * @param inY the y value to check. * * @return true iff the point is insided this component. */ virtual char isInside( double inX, double inY ); /** * Sets this component's focus status. * * Note that this component may ignore this function call * and configure its own focus (for example, some * components are never focused). * * The default implementation ignores this call * and is never focused. * * @param inFocus true iff this component should be focused. */ virtual void setFocus( char inFocus ); // the implementations below do nothing, but they allow // subclasses to pick which input they care about (and which // functions they want to override) // implements a normalized (to [0,1.0] version // of a MouseHandlerGL-like interface virtual void mouseMoved( double inX, double inY ); virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); // implements a normalized (to [0,1.0] version // of a KeyboardHandlerGL-like interface virtual char isFocused(); virtual void keyPressed( unsigned char inKey, double inX, double inY ); virtual void specialKeyPressed( int inKey, double inX, double inY ); virtual void keyReleased( unsigned char inKey, double inX, double inY ); virtual void specialKeyReleased( int inKey, double inX, double inY ); // implements the RedrawListenerGL interface virtual void fireRedraw(); protected: /** * Constructs a component. * * Should only be called by subclass constructors. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. */ GUIComponentGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ); double mAnchorX; double mAnchorY; double mWidth; double mHeight; char mEnabled; }; inline GUIComponentGL::GUIComponentGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ) : mAnchorX( inAnchorX ), mAnchorY( inAnchorY ), mWidth( inWidth ), mHeight( inHeight ), mEnabled( true ) { } inline GUIComponentGL::~GUIComponentGL() { } inline void GUIComponentGL::setPosition( double inAnchorX, double inAnchorY, double inWidth, double inHeight ) { mAnchorX = inAnchorX; mAnchorY = inAnchorY; mWidth = inWidth; mHeight = inHeight; } inline void GUIComponentGL::setEnabled( char inEnabled ) { mEnabled = inEnabled; } inline char GUIComponentGL::isEnabled() { return mEnabled; } inline char GUIComponentGL::isInside( double inX, double inY ) { if( inX >= mAnchorX && inX < mAnchorX + mWidth && inY >= mAnchorY && inY < mAnchorY + mHeight ) { return true; } else { return false; } } inline void GUIComponentGL::mouseMoved( double inX, double inY ) { } inline void GUIComponentGL::mouseDragged( double inX, double inY ) { } inline void GUIComponentGL::mousePressed( double inX, double inY ) { } inline void GUIComponentGL::mouseReleased( double inX, double inY ) { } inline void GUIComponentGL::setFocus( char inFocus ) { // default implementation ignores this call } inline char GUIComponentGL::isFocused() { return false; } inline void GUIComponentGL::keyPressed( unsigned char inKey, double inX, double inY ) { } inline void GUIComponentGL::specialKeyPressed( int inKey, double inX, double inY ) { } inline void GUIComponentGL::keyReleased( unsigned char inKey, double inX, double inY ) { } inline void GUIComponentGL::specialKeyReleased( int inKey, double inX, double inY ) { } inline void GUIComponentGL::fireRedraw() { } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/GUIPanelGL.h0000644000175000017500000000371710500316045023166 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * * 2006-July-3 Jason Rohrer * Fixed warnings. * * 2006-September-8 Jason Rohrer * Made alpha-aware. */ #ifndef GUI_PANEL_GL_INCLUDED #define GUI_PANEL_GL_INCLUDED #include "GUIComponentGL.h" #include "GUIContainerGL.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/graphics/Color.h" #include /** * A container with a background color that is drawn * behind the components. * * @author Jason Rohrer */ class GUIPanelGL : public GUIContainerGL { public: /** * Constructs a panel. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inColor the background color for this panel. * Will be destroyed when this class is destroyed. */ GUIPanelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Color *inColor ); virtual ~GUIPanelGL(); // override fireRedraw() in GUIComponentGL virtual void fireRedraw(); protected: Color *mColor; }; inline GUIPanelGL::GUIPanelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Color *inColor ) : GUIContainerGL( inAnchorX, inAnchorY, inWidth, inHeight ), mColor( inColor ) { } inline GUIPanelGL::~GUIPanelGL() { delete mColor; } inline void GUIPanelGL::fireRedraw() { // draw our background color as a rectangle glColor4f( mColor->r, mColor->g, mColor->b, mColor->a ); glBegin( GL_QUADS ); { glVertex2d( mAnchorX, mAnchorY ); glVertex2d( mAnchorX + mWidth, mAnchorY ); glVertex2d( mAnchorX + mWidth, mAnchorY + mHeight ); glVertex2d( mAnchorX, mAnchorY + mHeight ); } glEnd(); // call the supercalss redraw GUIContainerGL::fireRedraw(); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/test3.bmp0000644000175000017500000003006607352744545022752 0ustar pabspabsBM606(@@0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?BB>BB>BB?BB?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?AA>EDED?AA@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?AA=GG:QP6][3fd3fd6][:QP=GG?AA@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>ED9RQ2ig)$$*|3ec:QP>ED?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?BB;ML3ec'*}6][BB@@@@@@@@@@@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?BBBB@@@@@@@@@?@@?@@?@@?@@?@@?@@>@@>@@>@@>AA=AA=@@=@@>@@>@@?@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@>BB:NN/om !2ig;LL?BB@@@@@@@@@?@@?@@>@@>@@>@@=@@<@@;CC;GG;II:II:HG;DD@@>@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@>CC9RQ-wt #3fd@@<@@;AA:DD9FF8IH7LK5RP2YX3_]2_^3YX6PO9HG@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@=BB8TS,wt "2fe=GG@@@@@@?@@?BB;BB9FF7LK5RQ3XW1^\/ec*ro&%'*ur/ca4SR8HG;AA=@@>@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@?@@?@@>@@@@>AA=ED@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@?@@>@@=BB9PO.ol  '|4ZY:GG9KK6WV2db*rp&|y#  #,ig3RP8EE;@@=@@>@@>@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@>@@>@@>@@>@@>@@>@@>@@>@@>@@>@@>@@>@@@@>@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@>@@>@@>@@>@@>@@=@@=@@=@@=@@=@@=@@=@@;AA8II2^]$#'{x$ !,lj4QP8DD;@@<@@=@@>@@>@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@>@@=@@=@@=@@=@@<@@<@@;@@;@@<@@<@@<@@;@@9HG4XW(yw  &/ba6LK9CC;@@<@@=@@=@@>@@>@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@=@@<@@;@@:@@9@@:@@9@@9@@:@@9@@:@@9AA7GG4TT*pnýſ ",pn5TS9EE:AA<@@<@@=@@=@@>@@>@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@=@@;@@:@@8AA6CC6BC5CC5CC6AB7@B7AB8DD6JJ3WV*omž  %,qo4YW9GF;@@;@@<@@=@@=@@=@@>@@>@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@<@@:A@8DD4HH2LM1NO0NP0MO1IL3GJ4GJ5JL3RR0`_%zx  $'{x,qo1ca7UT;HG@@>@@>@@>@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@<@@8FE4ON/XX,`a*df*ch)_f*Yb,U].T[.V[-``)pn  Ľ%zw,ge1[Z4UT7ON:JIAA>@@>@@=@@=@@=@@>@@>@@>@@>@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@;CC6NM0^\)on#{| y s"l}$iw&kt&ux!",ml3XW9IHBB?BB?@@@@@?@@?@@>@@>@@>@@>@@?@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@:GG3XW+qo!  '|z/hf4WU;JJ>DD?AA@@@@@@@@@?@@>@@>@@>@@>@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@>@@=@@:II2_^&~   !(|y1kh6[Z;NM=FF?BB?AA>AA=@@>@@>@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@=@@:II1a`% » (0nl5^]8TS;NM;II;GG@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@;HH4[Z' %+|y/pn3cb8WV;ML>ED?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>DD9RQ/ro ¼$,yv5`^;NM>CC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@BB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?BB;KK7XW1ed)vv# "2ig;NM>BB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?BB=GG@@8JK+dh  '/pn7ZXAA>BB@@=CC;JJ:NM8RQ4VV&lq hl&TT-ML0NN5QP8NMDD?AA@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>AA;GG5VU0ec,qo*yw(yx  v_d&LM.CC3BB8BB;BB=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=AA:IH2]\)vu" o|Y_%GJ,@@3@@9@@<@@=@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@>@@:ED3YY'yx oyW]$FH+@@2@@:@@<@@=@@>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@=@@@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@<@@8FF.[Z"}  kl TT(DD0@@7@@<@@=@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@=@@:BB5LM*de ig$SR-DD6@@;@@=@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@=@@:DD3PQ(gj   !ki*SR2ED:@@<@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@=@@:DD2QQ(ei}   ü  'ge0NN9CC<@@>@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@=@@:CC3NO*`c!s{   &qp*fe)hiz}   $xu/XW9GG<@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@=@@;@@5II-XZ%hny w'jn,^_0TT2QQ.VW'jl#   #/_]:II>AA?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@<@@7DD1OO+\`%jptz}x q$gq*\a0QT3JJ4FF4HH0OP)bc!)pn*ro" ƿ%1^];II>AA?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@:@@5EE0PP,Z](ag&em&fo'ck*[b.RV2IK6DE8AA7@A6CD1LN)]a w   +ig0_],ec&xu*sp6VU=GG?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@>@@<@@:@@6EE3KK1PR/SV/RV0OS2JK6DE7@A:@@9@@8@@7AC2IM*X_!o} +ih2VU2RQ0[Y)ig%zw"#)wt1`^9ML>CC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@>@@=@@:@@9BB8DD7EE7EE8CC9AA:@@;@@<@@;@@9@@7AB3GK,T]#gy )nm2TS5II5JI2RQ.\Z,fd*mj+nk-hf1[Z7NM@@=@@=@@<@@<@@=@@=@@=@@=@@=@@<@@:@@8@A4EI.OX&`rw *sq4UT8FF8CC6FE5KJ4PO3SR4TR6ON8II@@>@@=@@<@@:@@7BE2JR+Wf"k  +sp5UT9FF:AA9@@9CB9ED9FE:EE:CC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@>@@=@@<@@9@C6EJ1NY*\n#q .lj7QP:DD;@@<@@<@@<@@<@@=@@=@@=@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@>@@=@@<@@:AD7FL3NX.[i&r(4][:KJ@@>@@?@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@>@@>@@=@@<@@;AB:DG8LP3W],mr&##*~2ec9QP=ED>@@>@@?@@?@@?@@?@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@?@@>@@>@@=@@<@@AA>@@>@@?@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?@@?@@?@@?@@>AA>EDED?AA@@@?@@?@@?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?@@?BB>BB>BB?BB?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/ImageButtonGL.h0000644000175000017500000000632110576755645024024 0ustar pabspabs/* * Modification History * * 2006-July-3 Jason Rohrer * Created. * * 2007-March-17 Jason Rohrer * Enabled blending (why was it off?) */ #ifndef IMAGE_BUTTON_GL_INCLUDED #define IMAGE_BUTTON_GL_INCLUDED #include "ButtonGL.h" #include "minorGems/graphics/Image.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" #include /** * A textured button for GL-based GUIs. * * @author Jason Rohrer */ class ImageButtonGL : public ButtonGL { public: /** * Constructs a button. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inUnpressedImage the image to display * when this button is unpressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * @param inPressedImage the image to display * when this button is pressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. */ ImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage, Image *inPressedImage ); ~ImageButtonGL(); // implements the ButtonGL interface virtual void drawPressed(); virtual void drawUnpressed(); protected: Image *mUnpressedImage; Image *mPressedImage; SingleTextureGL *mUnpressedTexture; SingleTextureGL *mPressedTexture; SingleTextureGL *mCurrentTexture; /** * Draw this button using a specific texture. * * @param inTexture the texture. * Destroyed by caller. */ void drawWithTexture( SingleTextureGL *inTexture ); }; inline ImageButtonGL::ImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage, Image *inPressedImage ) : ButtonGL( inAnchorX, inAnchorY, inWidth, inHeight ), mUnpressedImage( inUnpressedImage ), mPressedImage( inPressedImage ) { mUnpressedTexture = new SingleTextureGL( mUnpressedImage ); mPressedTexture = new SingleTextureGL( mPressedImage ); mCurrentTexture = mUnpressedTexture; } inline ImageButtonGL::~ImageButtonGL() { delete mUnpressedImage; delete mPressedImage; delete mUnpressedTexture; delete mPressedTexture; } inline void ImageButtonGL::drawPressed() { drawWithTexture( mPressedTexture ); } inline void ImageButtonGL::drawUnpressed() { drawWithTexture( mUnpressedTexture ); } inline void ImageButtonGL::drawWithTexture( SingleTextureGL *inTexture ) { // set our texture inTexture->enable(); glColor3f( 1.0f, 1.0f, 1.0f ); //glDisable( GL_BLEND ); glBegin( GL_QUADS ); { glTexCoord2f( 0, 1.0f ); glVertex2d( mAnchorX, mAnchorY ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( mAnchorX + mWidth, mAnchorY ); glTexCoord2f( 1.0f, 0 ); glVertex2d( mAnchorX + mWidth, mAnchorY + mHeight ); glTexCoord2f( 0, 0 ); glVertex2d( mAnchorX, mAnchorY + mHeight ); } glEnd(); inTexture->disable(); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/GUIContainerGL.h0000644000175000017500000001731310542027215024052 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * Changed to use normalized floating point coordinates. * Fixed some compile bugs. * Changed so that mouse released events are passed to all components. * * 2001-October-29 Jason Rohrer * Added support for focus, including mouse-release to focus. * * 2001-November-2 Jason Rohrer * Changed to send keyboard events only to focused components, * regardless of mouse position. * * 2006-July-3 Jason Rohrer * Fixed warnings. * * 2006-September-8 Jason Rohrer * Switched to passing mouse motion events to all components. * * 2006-December-14 Jason Rohrer * Added function for testing containment. */ #ifndef GUI_CONTAINER_GL_INCLUDED #define GUI_CONTAINER_GL_INCLUDED #include "GUIComponentGL.h" #include "minorGems/util/SimpleVector.h" /** * A container full of gui components that delegates * redraw and ui events to the contained components. * * @author Jason Rohrer */ class GUIContainerGL : public GUIComponentGL { public: /** * Constructs a container. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. */ GUIContainerGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ); virtual ~GUIContainerGL(); /** * Adds a component to this container. * * Note that the added component should lie within the bounds * of this container (or else event delegation may not function * properly). * * @param inComponent the component to add. Is destroyed * when this container is destroyed. */ virtual void add( GUIComponentGL *inComponent ); /** * Removes a component from this container. * * @param inComponent the component to remove. Must be * destroyed by the caller. * * @return true iff the component was removed successfully. */ virtual char remove( GUIComponentGL *inComponent ); /** * Gets whether this container contains a given component. * * @param inComponent the component to look for. * * @return true if inComponent is in this container. */ virtual char contains( GUIComponentGL *inComponent ); // the implementations below delegate events to appropriate // contained components // override functions in GUIComponentGL virtual void mouseMoved( double inX, double inY ); virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual char isFocused(); virtual void keyPressed( unsigned char inKey, double inX, double inY ); virtual void specialKeyPressed( int inKey, double inX, double inY ); virtual void keyReleased( unsigned char inKey, double inX, double inY ); virtual void specialKeyReleased( int inKey, double inX, double inY ); virtual void fireRedraw(); protected: SimpleVector *mComponentVector; }; inline GUIContainerGL::GUIContainerGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mComponentVector( new SimpleVector() ) { } inline GUIContainerGL::~GUIContainerGL() { // delete each contained component for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); delete component; } delete mComponentVector; } inline void GUIContainerGL::add( GUIComponentGL *inComponent ) { mComponentVector->push_back( inComponent ); } inline char GUIContainerGL::remove( GUIComponentGL *inComponent ) { return mComponentVector->deleteElement( inComponent ); } inline char GUIContainerGL::contains( GUIComponentGL *inComponent ) { int index = mComponentVector->getElementIndex( inComponent ); if( index >= 0 ) { return true; } else { return false; } } inline void GUIContainerGL::mouseMoved( double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->mouseMoved( inX, inY ); } } inline void GUIContainerGL::mouseDragged( double inX, double inY ) { // released events should be passed to all components // so that a pressed component can react if the mouse // is dragged elsewhere for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->mouseDragged( inX, inY ); } } inline void GUIContainerGL::mousePressed( double inX, double inY ) { // only pass pressed events to components // that contain the coordinate pressed for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); if( component->isInside( inX, inY ) ) { component->mousePressed( inX, inY ); } } } inline void GUIContainerGL::mouseReleased( double inX, double inY ) { // first, unfocus all components for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->setFocus( false ); } // released events should be passed to all components // so that a pressed component can react if the mouse // is released elsewhere for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->mouseReleased( inX, inY ); // focus any components hit by the release directly if( component->isInside( inX, inY ) ) { component->setFocus( true ); } } } inline char GUIContainerGL::isFocused() { // we are focused if any of our sub-components are focused for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); if( component->isFocused() ) { return true; } } // else, none focused return false; } inline void GUIContainerGL::keyPressed( unsigned char inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->keyPressed( inKey, inX, inY ); } } } inline void GUIContainerGL::specialKeyPressed( int inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->specialKeyPressed( inKey, inX, inY ); } } } inline void GUIContainerGL::keyReleased( unsigned char inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->keyReleased( inKey, inX, inY ); } } } inline void GUIContainerGL::specialKeyReleased( int inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->specialKeyReleased( inKey, inX, inY ); } } } inline void GUIContainerGL::fireRedraw() { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->fireRedraw(); } } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/test.bmp0000644000175000017500000001406607352744545022671 0ustar pabspabsBM66(@ ɫԱĚηԺɛխڡΕ؝ьҕদꡡɍ؍ؙ󛛛؛ʏ֓ӕҕ҇Ǐ͑堠ܑɖ󲲲򨨨磣˷͕ﱱʤɘƏБ򲲲ؖϊŌ䓓ʏ靝ܚ떖㰰禦ߠ议Íɗ坝墢ߠ칹✜Ց񻻻۲Щɡݍ돏Ӗ㞞primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/MultiButtonGL.h0000644000175000017500000001603707371145520024061 0ustar pabspabs/* * Modification History * * 2001-September-16 Jason Rohrer * Created. * * 2001-November-3 Jason Rohrer * Fixed a gutter size bug that occurred when there was * only one row or column. * Changed so that rows are filled before adding new columns. * Fixed a bug in setSelectedIndex. */ #ifndef MULTI_BUTTON_GL_INCLUDED #define MULTI_BUTTON_GL_INCLUDED #include "GUIContainerGL.h" #include "StickyButtonGL.h" #include "minorGems/graphics/Image.h" #include "minorGems/ui/event/ActionListenerList.h" #include "minorGems/ui/event/ActionListener.h" #include "minorGems/ui/GUIComponent.h" #include #include /** * A set of buttons that allows only one to be depressed * at a time. * * @author Jason Rohrer */ class MultiButtonGL : public GUIContainerGL, public ActionListener, public ActionListenerList { public: /** * Constructs a set of buttons. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inNumButtons the number of buttons in the set. * @param inUnpressedImages the images to display * when each button is unpressed. Images must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * @param inPressedImages the images to display * when each button is pressed. Images must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * @param inGutterFraction the fraction of each row * and column that should be taken up by the gutters * (the spaces between buttons). In [0, 1.0]. */ MultiButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, int inNumButtons, Image **inUnpressedImages, Image **inPressedImages, double inGutterFraction ); ~MultiButtonGL(); /** * Sets the currently depressed button. * * Note that if this function causes a change * in the state of the set, an action will * be fired to all registered listeners. * * @param inButtonIndex the index of the button to depress. */ void setSelectedButton( int inButtonIndex ); /** * Gets the index of the currently depressed button. * * Note that if this function causes a change * in the state of the set, an action will * be fired to all registered listeners. * * @return the index of the button that is depressed. */ int getSelectedButton(); // we don't need to override any mouse // or redraw functions, since the container // and the buttons should handle these correctly // implements the ActionListener interface virtual void actionPerformed( GUIComponent *inTarget ); protected: int mNumButtons; StickyButtonGL **mButtons; int mSelectedIndex; char mIgnoreEvents; /** * Maps a button in mButtons to its index in the * mButtons array. * * @param inButton the button to get an index for. * * @return the index of inButton in the mButtons array. */ int buttonToIndex( StickyButtonGL *inButton ); }; inline MultiButtonGL::MultiButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, int inNumButtons, Image **inUnpressedImages, Image **inPressedImages, double inGutterFraction ) : GUIContainerGL( inAnchorX, inAnchorY, inWidth, inHeight ), mNumButtons( inNumButtons ), mButtons( new StickyButtonGL*[inNumButtons] ), mSelectedIndex( 0 ), mIgnoreEvents( false ) { int numColumns = (int)( sqrt( mNumButtons ) ); int numRows = mNumButtons / numColumns; while( numRows * numColumns < mNumButtons ) { numRows++; } // determine gutter and button sizes double gutterSizeX; double gutterSizeY; if( numRows == 1 ) { gutterSizeY = 0; } else { gutterSizeY = ( inHeight * inGutterFraction ) / ( numRows - 1 ); } if( numColumns == 1 ) { gutterSizeX = 0; } else { gutterSizeX = ( inWidth * inGutterFraction ) / ( numColumns - 1 ); } double buttonSizeX = ( inWidth * ( 1 - inGutterFraction ) ) / ( numColumns ); double buttonSizeY = ( inHeight * ( 1 - inGutterFraction ) ) / ( numRows ); // setup each button int buttonIndex = 0; for( int r=0; r= mNumButtons ) { // jump out of our loop if we run out of buttons c = numColumns; r = numRows; } } } // now we've added all of our buttons // press one of them before we add any listeners mButtons[ mSelectedIndex ]->setPressed( true ); // now add ourselves as an action listener to each button for( int i=0; iaddActionListener( this ); } // delete the arrays pointing to the images, since // they are no longer needed delete [] inUnpressedImages; delete [] inPressedImages; } inline MultiButtonGL::~MultiButtonGL() { // note that we don't need to delete the buttons // themselves, since they will be deleted by GUIContainer // destructor delete [] mButtons; } inline void MultiButtonGL::setSelectedButton( int inButtonIndex ) { // simply press the appropriate button, and let the // action handlers do the rest mButtons[ inButtonIndex ]->setPressed( true ); } inline int MultiButtonGL::getSelectedButton() { return mSelectedIndex; } inline void MultiButtonGL::actionPerformed( GUIComponent *inTarget ) { if( !mIgnoreEvents ) { int buttonIndex = buttonToIndex( (StickyButtonGL*)inTarget ); // if another button is being pressed if( buttonIndex != mSelectedIndex && mButtons[ buttonIndex ]->isPressed() ) { // unpress the old button, ignoring the resulting event mIgnoreEvents = true; mButtons[ mSelectedIndex ]->setPressed( false ); mIgnoreEvents = false; mSelectedIndex = buttonIndex; fireActionPerformed( this ); } // else if our selected button is being unpressed else if( buttonIndex == mSelectedIndex && !( mButtons[ buttonIndex ]->isPressed() ) ) { // don't allow it to become unpressed // re-press it, ignoring the resulting event mIgnoreEvents = true; mButtons[ mSelectedIndex ]->setPressed( true ); mIgnoreEvents = false; // don't fire an action, since our state // has not changed } } } inline int MultiButtonGL::buttonToIndex( StickyButtonGL *inButton ) { for( int i=0; i /** * A textured button for GL-based GUIs that draws one image with a shadow * to show pressed/unpressed status. * * @author Jason Rohrer */ class ShadowImageButtonGL : public ButtonGL { public: /** * Constructs a button. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inUnpressedImage the image to display * when this button is unpressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. */ ShadowImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage ); ~ShadowImageButtonGL(); // implements the ButtonGL interface virtual void drawPressed(); virtual void drawUnpressed(); protected: Image *mUnpressedImage; SingleTextureGL *mUnpressedTexture; /** * Draw this button with an optional z offset above it's shadow. * * @param inOffset true to draw the button above its shadow. */ void drawWithOffset( char inOffset ); }; inline ShadowImageButtonGL::ShadowImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage ) : ButtonGL( inAnchorX, inAnchorY, inWidth, inHeight ), mUnpressedImage( inUnpressedImage ) { mUnpressedTexture = new SingleTextureGL( mUnpressedImage ); } inline ShadowImageButtonGL::~ShadowImageButtonGL() { delete mUnpressedImage; delete mUnpressedTexture; } inline void ShadowImageButtonGL::drawPressed() { drawWithOffset( false ); } inline void ShadowImageButtonGL::drawUnpressed() { drawWithOffset( true ); } inline void ShadowImageButtonGL::drawWithOffset( char inOffset ) { // calculate offset for shadow double xOffset = mWidth * 0.05; double yOffset = mHeight * 0.05; // use smaller double offset = xOffset; if( yOffset < xOffset ) { offset = yOffset; } // set our texture mUnpressedTexture->enable(); // shadow first glColor4f( 0.0, 0.0, 0.0, 0.5 ); // shadow in lower left corner glBegin( GL_QUADS ); { glTexCoord2f( 0, 1.0f ); glVertex2d( mAnchorX, mAnchorY ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY ); glTexCoord2f( 1.0f, 0 ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY + mHeight - offset ); glTexCoord2f( 0, 0 ); glVertex2d( mAnchorX, mAnchorY + mHeight - offset ); } glEnd(); // now button image glColor4f( 1.0, 1.0, 1.0, 10 ); double anchorOffset = 0; if( inOffset ) { // put it in upper right corner anchorOffset = offset; offset = 0; } glBegin( GL_QUADS ); { glTexCoord2f( 0, 1.0f ); glVertex2d( mAnchorX + anchorOffset, mAnchorY + anchorOffset ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY + anchorOffset ); glTexCoord2f( 1.0f, 0 ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY + mHeight - offset ); glTexCoord2f( 0, 0 ); glVertex2d( mAnchorX + anchorOffset, mAnchorY + mHeight - offset ); } glEnd(); mUnpressedTexture->disable(); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/TextFieldGL.h0000644000175000017500000002341111103150443023441 0ustar pabspabs/* * Modification History * * 2001-October-29 Jason Rohrer * Created. * * 2001-November-2 Jason Rohrer * Added support for cursor position. * Added support for clicking to reposition the cursor. * Fixed an array out-of-bounds bug in the keyReleased function. * * 2008-September-29 Jason Rohrer * Improved text width handling and cursor spacing. * Added length limit. * * 2008-October-27 Jason Rohrer * Switched to implementation-independent keycodes. * Switched to key press (instead of release) events. * * 2008-November-1 Jason Rohrer * Added support for forced upper case. */ #ifndef TEXT_FIELD_GL_INCLUDED #define TEXT_FIELD_GL_INCLUDED #include "GUIComponentGL.h" #include "TextGL.h" #include "minorGems/graphics/Color.h" #include "minorGems/util/stringUtils.h" /** * A text field for OpenGL-based GUIs. * * @author Jason Rohrer */ class TextFieldGL : public GUIComponentGL { public: /** * Constructs a text field. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inString the text to display in this text field. * Is copied internally, so must be destroyed * by caller if not const. * @param inText the text object to use when drawing * this textField. Must be destroyed by caller after * this class is destroyed. * @param inBorderColor the color of this field's border. * Will be destroyed when this class is destroyed. * @param inFocusedBorderColor the color of this field's border * when the field is focused. * Will be destroyed when this class is destroyed. * @param inBackgroundColor the color of this field's background. * Will be destroyed when this class is destroyed. * @param inCursorColor the color of this field's cursor line. * Will be destroyed when this class is destroyed. * @param inLengthLimit the length limit for the entered string, * or -1 for no limit. Defaults to -1. * @param inForceUppercase true to force upper case for text entered. * Defaults to false. */ TextFieldGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, char *inString, TextGL *inText, Color *inBorderColor, Color *inFocusedBorderColor, Color *inBackgroundColor, Color *inCursorColor, int inLengthLimit = -1, char inForceUppercase = false ); ~TextFieldGL(); /** * Sets the text displayed by this text field. * * @param inString the text to display in this text field. * Is copied internally, so must be destroyed * by caller if not const. */ void setText( char *inString ); /** * Gets the text displayed by this text field. * * @return the text to display in this textField. * Must not be destroyed or modified by caller. */ char *getText(); // override functions in GUIComponentGL virtual void setFocus( char inFocus ); virtual char isFocused(); virtual void keyPressed( unsigned char inKey, double inX, double inY ); virtual void specialKeyPressed( int inKey, double inX, double inY ); virtual void keyReleased( unsigned char inKey, double inX, double inY ); virtual void specialKeyReleased( int inKey, double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual void fireRedraw(); protected: /** * Adjusts the cursor position to bring it in bounds of the * current string. */ void fixCursorPosition(); TextGL *mText; char *mString; Color *mBorderColor; Color *mFocusedBorderColor; Color *mBackgroundColor; Color *mCursorColor; Color *mCurrentBorderColor; int mLengthLimit; char mForceUppercase; char mFocused; // cursor position, in number of characters int mCursorPosition; }; inline TextFieldGL::TextFieldGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, char *inString, TextGL *inText, Color *inBorderColor, Color *inFocusedBorderColor, Color *inBackgroundColor, Color *inCursorColor, int inLengthLimit, char inForceUppercase ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mText( inText ), mString( NULL ), mBorderColor( inBorderColor ), mFocusedBorderColor( inFocusedBorderColor ), mBackgroundColor( inBackgroundColor ), mCursorColor( inCursorColor ), mCurrentBorderColor( inBorderColor ), mLengthLimit( inLengthLimit ), mForceUppercase( inForceUppercase ), mFocused( false ), mCursorPosition( 0 ) { setText( inString ); } inline TextFieldGL::~TextFieldGL() { if( mString != NULL ) { delete [] mString; } delete mBorderColor; delete mFocusedBorderColor; delete mBackgroundColor; delete mCursorColor; } inline void TextFieldGL::setText( char *inString ) { if( mString != NULL ) { delete [] mString; } int length = strlen( inString ) + 1; mString = new char[ length ]; memcpy( mString, inString, length ); } inline char *TextFieldGL::getText() { return mString; } inline void TextFieldGL::setFocus( char inFocus ) { mFocused = inFocus; if( mFocused ) { mCurrentBorderColor = mFocusedBorderColor; } else { mCurrentBorderColor = mBorderColor; } } inline char TextFieldGL::isFocused() { return mFocused; } inline void TextFieldGL::keyPressed( unsigned char inKey, double inX, double inY ) { //printf( "key press: %d\n", inKey ); // backspace and delete if( inKey == 127 || inKey == 8 ) { if( mCursorPosition != 0 ) { int length = strlen( mString ); if( length != 0 ) { char *newString = new char[ length ]; // copy mString up to the last char before the deleted char memcpy( newString, mString, mCursorPosition-1 ); // copy the portion of mString after the deleted char // this will include the trailing \0 memcpy( &( newString[mCursorPosition-1] ), &( mString[mCursorPosition] ), length - mCursorPosition + 1 ); setText( newString ); delete [] newString; mCursorPosition--; } } } // allowable character key, from space up to tilde // ignore after length limit reached else if( inKey >= 32 && inKey <= 126 && ( mLengthLimit < 0 || (int)strlen( mString ) < mLengthLimit ) ) { // add a character to our string int oldStringLength = strlen( mString ) + 2; int length = oldStringLength + 2; char *newString = new char[ length ]; if( mCursorPosition != 0 ) { // copy chars up to cursor position memcpy( newString, mString, mCursorPosition ); } // copy chars after cursor position, including trailing \0 memcpy( &( newString[mCursorPosition+1] ), &( mString[mCursorPosition] ), oldStringLength - mCursorPosition + 1 ); if( mForceUppercase ) { inKey = toupper( inKey ); } // now stick in the inserted char newString[ mCursorPosition ] = inKey; setText( newString ); delete [] newString; mCursorPosition++; } // else a non-valid key hit } inline void TextFieldGL::specialKeyPressed( int inKey, double inX, double inY ) { switch( inKey ) { case MG_KEY_RIGHT: mCursorPosition++; break; case MG_KEY_LEFT: mCursorPosition--; default: break; } fixCursorPosition(); } inline void TextFieldGL::keyReleased( unsigned char inKey, double inX, double inY ) { } inline void TextFieldGL::specialKeyReleased( int inKey, double inX, double inY ) { } inline void TextFieldGL::mouseReleased( double inX, double inY ) { if( isInside( inX, inY ) ) { mCursorPosition = (int)( 0.5 + strlen( mString ) * ( inX - mAnchorX ) / mWidth ); } } inline void TextFieldGL::fixCursorPosition() { if( mCursorPosition < 0 ) { mCursorPosition = 0; } else { int stringLength = strlen( mString ); if( mCursorPosition > stringLength ) { mCursorPosition = stringLength; } } } inline void TextFieldGL::fireRedraw() { // offset to give text room double offset = mHeight * 0.1; // draw the background glColor3f( mBackgroundColor->r, mBackgroundColor->g, mBackgroundColor->b ); glBegin( GL_QUADS ); { glVertex2d( mAnchorX - offset, mAnchorY - offset ); glVertex2d( mAnchorX - offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY - offset ); } glEnd(); double charWidth = mHeight * strlen( mString ); // draw the text mText->drawText( mString, mAnchorX, mAnchorY, charWidth, mHeight ); if( mFocused ) { // draw the cursor glColor3f( mCursorColor->r, mCursorColor->g, mCursorColor->b ); glBegin( GL_LINES ); { // make a temp sub-string and measure its length char *substring = stringDuplicate( mString ); substring[ mCursorPosition ] = '\0'; double subWidth = mText->measureTextWidth( substring ) * mHeight + offset; delete [] substring; double cursorViewX = mAnchorX + subWidth; glVertex2d( cursorViewX, mAnchorY ); glVertex2d( cursorViewX, mAnchorY + mHeight ); } glEnd(); } // draw the border on top of the text and cursor glColor3f( mCurrentBorderColor->r, mCurrentBorderColor->g, mCurrentBorderColor->b ); glBegin( GL_LINE_LOOP ); { glVertex2d( mAnchorX - offset, mAnchorY - offset ); glVertex2d( mAnchorX - offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY - offset ); } glEnd(); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/SliderGL.h0000644000175000017500000001760607353535634023031 0ustar pabspabs/* * Modification History * * 2001-September-17 Jason Rohrer * Created. * * 2001-September-21 Jason Rohrer * Fixed a bug in thumb positioning in response to mouse position. * * 2001-September-23 Jason Rohrer * Fixed a bug in icon color clearing. */ #ifndef SLIDER_GL_INCLUDED #define SLIDER_GL_INCLUDED #include "GUIComponentGL.h" #include "minorGems/graphics/Image.h" #include "minorGems/graphics/Color.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" #include "minorGems/ui/event/ActionListenerList.h" #include /** * A textured slider for GL-based GUIs. * * @author Jason Rohrer */ class SliderGL : public GUIComponentGL, public ActionListenerList { public: /** * Constructs a slider. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inIconImage the image to display * to the left of this slider. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * If set to NULL, then no icon will be drawn. * @param inIconWidthFraction the fraction of the slider's * width that should be taken up by the icon. * @param inBarStartColor the color on the left end of * the slider bar. * Will be destroyed when this class is destroyed. * @param inBarEndColor the color on the right end of * the slider bar. * Will be destroyed when this class is destroyed. * @param inThumbColor the color of the slider thumb. * Will be destroyed when this class is destroyed. * @param inBorderColor the color of the slider border. * Will be destroyed when this class is destroyed. */ SliderGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inIconImage, double inIconWidthFraction, Color *inBarStartColor, Color *inBarEndColor, Color *inThumbColor, Color *inBorderColor ); ~SliderGL(); /** * Gets the position of the slider thumb. * * @return the thumb position, in [0,1.0]. */ double getThumbPosition(); /** * Sets the position of the slider thumb. * * Note that if the slider thumb position changes * as a result of this call, then an action * will be fired to all registered listeners. * * @param inPosition the thumb position, in [0,1.0]. */ void setThumbPosition( double inPosition ); // override funxtions in GUIComponentGL virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual void fireRedraw(); protected: SingleTextureGL *mIconTexture; double mIconWidthFraction; Color *mBarStartColor; Color *mBarEndColor; Color *mThumbColor; Color *mBorderColor; double mThumbPosition; // true iff the slider is currently being dragged char mDragging; }; inline SliderGL::SliderGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inIconImage, double inIconWidthFraction, Color *inBarStartColor, Color *inBarEndColor, Color *inThumbColor, Color *inBorderColor ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mIconWidthFraction( inIconWidthFraction ), mBarStartColor( inBarStartColor ), mBarEndColor( inBarEndColor ), mThumbColor( inThumbColor ), mBorderColor( inBorderColor ), mThumbPosition( 0.5 ), mDragging( false ) { if( inIconImage != NULL ) { mIconTexture = new SingleTextureGL( inIconImage ); // the image is no longer needed delete inIconImage; } else { mIconTexture = NULL; } } inline SliderGL::~SliderGL() { if( mIconTexture != NULL ) { delete mIconTexture; } delete mBarStartColor; delete mBarEndColor; delete mThumbColor; delete mBorderColor; } inline double SliderGL::getThumbPosition() { return mThumbPosition; } inline void SliderGL::setThumbPosition( double inPosition ) { if( mThumbPosition != inPosition ) { mThumbPosition = inPosition; fireActionPerformed( this ); } } inline void SliderGL::mouseDragged( double inX, double inY ) { if( mDragging ) { double barWidth = mWidth * ( 1 - mIconWidthFraction ); double iconEndX = mAnchorX + mWidth - barWidth; double thumbWidth = 0.1 * barWidth; // we want the mouse centered over the thumb double thumbUsableBarWidth = barWidth - thumbWidth; mThumbPosition = ( inX - ( iconEndX + 0.5 * thumbWidth ) ) / thumbUsableBarWidth; if( mThumbPosition > 1 ) { mThumbPosition = 1; } else if( mThumbPosition < 0 ) { mThumbPosition = 0; } // fire to listeners fireActionPerformed( this ); } } inline void SliderGL::mousePressed( double inX, double inY ) { mDragging = true; } inline void SliderGL::mouseReleased( double inX, double inY ) { // always stop dragging on a release mDragging = false; } inline void SliderGL::fireRedraw() { // these values will change below if there is an icon double barStartX = mAnchorX; double barWidth = mWidth; if( mIconTexture != NULL ){ // first, draw the icon // set our texture mIconTexture->enable(); double textureStartX = mAnchorX; double textureStartY = mAnchorY; double textureEndX = mAnchorX + mIconWidthFraction * mWidth; double textureEndY = mAnchorY + mHeight; glBegin( GL_QUADS ); { // make sure our color is set to white for our texture // (to avoid leftover colors) glColor3f( 1.0, 1.0, 1.0 ); glTexCoord2f( 0, 1.0f ); glVertex2d( textureStartX, textureStartY ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( textureEndX, textureStartY ); glTexCoord2f( 1.0f, 0 ); glVertex2d( textureEndX, textureEndY ); glTexCoord2f( 0, 0 ); glVertex2d( textureStartX, textureEndY ); } glEnd(); mIconTexture->disable(); barWidth = mWidth * ( 1 - mIconWidthFraction ); barStartX = textureEndX; } // end check for a non-NULL icon texture // now, draw the slider bar double barHeight = 0.5 * mHeight; // center the bar vertically double barStartY = mAnchorY + ( mHeight - barHeight ) * 0.5; // draw its gradient-filled center glBegin( GL_QUADS ); { // start of bar glColor3f( mBarStartColor->r, mBarStartColor->g, mBarStartColor->b ); glVertex2d( barStartX, barStartY ); glVertex2d( barStartX, barStartY + barHeight ); // end of bar glColor3f( mBarEndColor->r, mBarEndColor->g, mBarEndColor->b ); glVertex2d( barStartX + barWidth, barStartY + barHeight ); glVertex2d( barStartX + barWidth, barStartY ); } glEnd(); // draw it's border glColor3f( mBorderColor->r, mBorderColor->g, mBorderColor->b ); glBegin( GL_LINE_LOOP ); { glVertex2d( barStartX, barStartY ); glVertex2d( barStartX, barStartY + barHeight ); glVertex2d( barStartX + barWidth, barStartY + barHeight ); glVertex2d( barStartX + barWidth, barStartY ); } glEnd(); // now draw the thumb // draw a thumb that is 1/10th as wide as the bar double thumbWidth = 0.1 * barWidth; // we don't want the thumb going off the ends of the bar double thumbUsableBarWidth = barWidth - thumbWidth; double thumbStartX = mThumbPosition * thumbUsableBarWidth + barStartX; double thumbEndX = thumbStartX + thumbWidth; glColor3f( mThumbColor->r, mThumbColor->g, mThumbColor->b ); glBegin( GL_QUADS ); { glVertex2d( thumbStartX, mAnchorY ); glVertex2d( thumbStartX, mAnchorY + mHeight ); glVertex2d( thumbEndX, mAnchorY + mHeight ); glVertex2d( thumbEndX, mAnchorY ); } glEnd(); // draw it's border glColor3f( mBorderColor->r, mBorderColor->g, mBorderColor->b ); glBegin( GL_LINE_LOOP ); { glVertex2d( thumbStartX, mAnchorY ); glVertex2d( thumbStartX, mAnchorY + mHeight ); glVertex2d( thumbEndX, mAnchorY + mHeight ); glVertex2d( thumbEndX, mAnchorY ); } glEnd(); } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/TextGL.h0000644000175000017500000004333611070212056022507 0ustar pabspabs/* * Modification History * * 2001-October-13 Jason Rohrer * Created. * Changed to support alpha-blended fonts, even for 3-channel font textures. * Fixed a bug in the font coloring. * * 2001-November-3 Jason Rohrer * Fixed some missing includes. * * 2006-December-26 Jason Rohrer * Added support for variable-width characers. * * 2007-March-4 Jason Rohrer * Added support for character z coordinates. * * 2007-March-15 Jason Rohrer * Added support for pixelated characters. Fixed font spacing issue. * * 2008-September-29 Jason Rohrer * Added support for font images with non-power-of-2 dimensions. */ #ifndef TEXT_GL_INCLUDED #define TEXT_GL_INCLUDED #include #include #include #include #include "minorGems/graphics/Color.h" #include "minorGems/graphics/Image.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" /** * A class for drawing text strings to an OpenGL context. * Fonts are texture maps. * * @author Jason Rohrer */ class TextGL { public: /** * Constructs a gl text object. * * Note that this function can only be called * after an OpenGL drawing context has been created. * * @param inImage the image to use as a font texture. * Must be a square image and should have dimensions that are a * power of 2. * If dimensions are not a power of 2, then class will compensate * by padding image. * Fonts in the image are assumed to be in row-major ASCII order, * with 16 characters per row. * Must be destroyed by caller. Can be destroyed as soon as * this constructor returns. * @param inUseAlpha true iff alpha blending should * be used when rendering the font textures. If alpha * blending is enabled and the image has only 3 channels, * only the red channel (channel 0) * of the image is used: it is interpreted as the alpha * channel for a white fontset. * @param inFixedWidth true iff font should be displayed in fixed * width mode. If false, a width will be measured for each * character from the alpha channel. If inUseAlpha is false, * the font is always fixed width. Defaults to true. * @param inCharacterSpacingFraction the extra width-fraction of * spacing around each character. A fraction of a full character * width. Space is added on *both* sides of character. * Defaults to 0.1 * @param inSpaceWidthFraction the fraction of a full character width * occupied by a space. Defaults to 1.0 (a full width). */ TextGL( Image *inImage, char inUseAlpha = false, char inFixedWidth = true, double inCharacterSpacingFraction = 0.1, double inSpaceWidthFraction = 1.0 ); virtual ~TextGL(); /** * Sets the main color of the font. * * If the gradient color is non-NULL, this color will be at the * top of the fonts. Otherwise, the entire extent * of the font will be this color. * * @param inColor the main color of the font. * Will be destroyed when this class is destroyed. */ void setFontColor( Color *inColor ); /** * Gets the main color of the font. * * If the gradient color is non-NULL, this color will be at the * top of the fonts. Otherwise, the entire extent * of the font will be this color. * * @return the main color of the font. * Will be destroyed when this class is destroyed. */ Color *getFontColor(); /** * Sets the gradient color of the font. * * If non-NULL, this color will be at the * bottom of the fonts. * * @param inColor the gradient color of the font, or * NULL to disable the gradient. * Will be destroyed when this class is destroyed. */ void setGradientColor( Color *inColor ); /** * Gets the gradient color of the font. * * If non-NULL, this color will be at the * bottom of the fonts. * * @return the gradient color of the font, or * NULL if disable gradient disabled. * Will be destroyed when this class is destroyed. */ Color *getGradientColor(); /** * Sets the z coordinate for font drawing. * * Defaults to 0. * * @param inZ the z coordinate. */ void setFontZ( double inZ ); /** * Sets smothing. * * @param inSmooth true to enable smoothing of font texture (linear * interpolation) or false to show pure texture pixels (nearest * neighbor). */ void setSmoothing( char inSmooth ); /** * Draws a text string into a specified region of the * context. Text is squeezed to fit into the region. * * Uses the currently active OpenGL projection settings. * * @param inString the \0-delimited string to draw. * Must be destroyed by caller if not const. * @param inX the x coordinate of the region's lower-left * corner. * @param inY the y coordinate of the region's lower-left * corner. * @param inWidth the width of the region. * @param inHeight the height of the region. */ void drawText( char *inString, double inX, double inY, double inWidth, double inHeight ); /** * Measures the width of a string of text. * * @inString the string to measure. Destroyed by caller. * * @return the width of the display text in character height * units. A return value of 8.5 means the string would be as * wide as 8.5 characters are high (if the string was displayed * with a 1:1 aspect ratio). */ double measureTextWidth( char *inString ); protected: double mXImageFractionUsed; double mYImageFractionUsed; Color *mFontColor; Color *mGradientColor; double mZ; char mSmooth; SingleTextureGL *mFontTexture; char mUseAlpha; double *mStartWidthFractionMetrics; double *mEndWidthFractionMetrics; /** * Draws a character into a specified region of the * context. The character is squeezed to fit into the region. * * Uses the currently active OpenGL projection settings. * * @param inCharacter the character to draw. * @param inX the x coordinate of the region's lower-left * corner. * @param inY the y coordinate of the region's lower-left * corner. * @param inWidth the width of the region. * @param inHeight the height of the region. * @param outUsedWidth pointer to where the actual width used * by this character should be returned. */ void drawCharacter( char inCharacter, double inX, double inY, double inWidth, double inHeight, double *outUsedWidth ); /** * Generates internal character width metrics from a font image. * * @param inFontImage the font image. Destroyed by caller. * @param inFixedWidth, inSpaceWidthFraction, * inCharacterSpacingFractionsame as parameters for the TextGL * constructor. */ void generateCharacterWidths( Image *inFontImage, char inFixedWidth, double inCharacterSpacingFraction, double inSpaceWidthFraction ); }; inline TextGL::TextGL( Image *inImage, char inUseAlpha, char inFixedWidth, double inCharacterSpacingFraction, double inSpaceWidthFraction ) : mXImageFractionUsed( 1.0 ), mYImageFractionUsed( 1.0 ), mFontColor( new Color( 1.0f, 1.0f, 1.0f, 1.0f ) ), mGradientColor( NULL ), mZ( 0 ), mSmooth( false ), mUseAlpha( inUseAlpha ), mStartWidthFractionMetrics( new double[ 256 ] ), mEndWidthFractionMetrics( new double[ 256 ] ) { // pad image to next power of 2 in each dimension int w = inImage->getWidth(); int h = inImage->getHeight(); int paddedW = w; int paddedH = h; double log2w = log( w ) / log( 2 ); double log2h = log( h ) / log( 2 ); int next2PowerW = (int)( ceil( log2w ) ); int next2PowerH = (int)( ceil( log2h ) ); if( next2PowerW != log2w ) { paddedW = (int)( pow( 2, next2PowerW ) ); mXImageFractionUsed = (double)w / (double)paddedW; } if( next2PowerH != log2h ) { paddedH = (int)( pow( 2, next2PowerH ) ); mYImageFractionUsed = (double)h / (double)paddedH; } // pad the image int numChannels = inImage->getNumChannels(); Image paddedImage( paddedW, paddedH, numChannels, true ); for( int c=0; cgetChannel( c ); for( int y=0; ygetChannel(3), paddedImage.getChannel(0), numPixels * sizeof( double ) ); // set other channels to white for( int c=0; c<3; c++ ) { double *channel = fontImage->getChannel( c ); for( int p=0; penable(); if( mSmooth ) { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); } else { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); } glBegin( GL_QUADS ); { if( mGradientColor != NULL ) { glColor4f( mGradientColor->r, mGradientColor->g, mGradientColor->b, mGradientColor->a ); } else { glColor4f( mFontColor->r, mFontColor->g, mFontColor->b, mFontColor->a ); } glTexCoord2f( textureStartX, textureStartY ); glVertex3d( charStartX, charStartY, mZ ); glTexCoord2f( textureEndX, textureStartY ); glVertex3d( charEndX, charStartY, mZ ); glColor4f( mFontColor->r, mFontColor->g, mFontColor->b, mFontColor->a ); glTexCoord2f( textureEndX, textureEndY ); glVertex3d( charEndX, charEndY, mZ ); glTexCoord2f( textureStartX, textureEndY ); glVertex3d( charStartX, charEndY, mZ ); } glEnd(); mFontTexture->disable(); } inline void TextGL::generateCharacterWidths( Image *inFontImage, char inFixedWidth, double inCharacterSpacingFraction, double inSpaceWidthFraction ) { if( mUseAlpha && ! inFixedWidth ) { double *alphaChannel = inFontImage->getChannel( 3 ); int imageWidth = inFontImage->getWidth(); // image must be square, so ignore height //int imageHeight = inFontImage->getHeight(); int pixelsPerCharacter = (int)( mXImageFractionUsed * imageWidth ) / 16; // look at each row and column in texture image for( int r=0; r<16; r++ ) { int charStartY = pixelsPerCharacter * r; int charEndY = charStartY + pixelsPerCharacter; for( int c=0; c<16; c++ ) { int charStartX = pixelsPerCharacter * c; int charEndX = charStartX + pixelsPerCharacter; // by "ink", I mean part of the image that has a non-zero // alpha // we want to find how far this character stretches to the // left and right within it's fixed-width region int smallestXWithInk = charEndX; int largestXWithInk = charStartX; for( int x=charStartX; x 0 ) { // hit some ink if( x < smallestXWithInk ) { smallestXWithInk = x; } if( x > largestXWithInk ) { largestXWithInk = x; } } } } int i = r * 16 + c; if( smallestXWithInk <= largestXWithInk ) { mStartWidthFractionMetrics[ i ] = (double)( smallestXWithInk - charStartX ) / (double)pixelsPerCharacter; mEndWidthFractionMetrics[ i ] = (double)( largestXWithInk - charStartX ) / (double)pixelsPerCharacter; mStartWidthFractionMetrics[ i ] -= inCharacterSpacingFraction; mEndWidthFractionMetrics[ i ] += inCharacterSpacingFraction; } else { // empty character image // treat as a space mStartWidthFractionMetrics[ i ] = 0; mEndWidthFractionMetrics[ i ] = inSpaceWidthFraction; } } } } else { // not using alpha (or fixed width requested) // fix width for( int i=0; i<256; i++ ) { mStartWidthFractionMetrics[ i ] = 0 - inCharacterSpacingFraction; mEndWidthFractionMetrics[ i ] = 1 + inCharacterSpacingFraction; } // special case for space mStartWidthFractionMetrics[ 32 ] = 0; mEndWidthFractionMetrics[ 32 ] = inSpaceWidthFraction; } } inline double TextGL::measureTextWidth( char *inString ) { double width = 0; int numChars = strlen( inString ); for( int i=0; i #include "minorGems/graphics/openGL/MouseHandlerGL.h" #include "minorGems/graphics/openGL/KeyboardHandlerGL.h" #include "minorGems/graphics/openGL/SceneHandlerGL.h" #include "minorGems/graphics/openGL/ScreenGL.h" /** * A class that translates coordinates for a gui component. * * Notes on intended use: * This class is best used as a wrapper for the entire * GL-based gui. In this case, the component passed to the * constructor would be a GUIContainerGL containing the * entire GUI. This class can be thought of as a wrapper * for interfacing size-independent GUI components to the * screen. * * @author Jason Rohrer */ class GUITranslatorGL : public MouseHandlerGL, public KeyboardHandlerGL, public SceneHandlerGL { public: /** * Constructs a translator. * * @param inComponent the component for which events * will be translated and delegated. All events will * be delegated to inComponent, regardless of whether the * events pass the inComponent->isInside() test. * Will be destroyed when this class is destroyed. * @param inScreen the screen whose size is used during * event translation. Must be destroyed by caller after * this class is destroyed. */ GUITranslatorGL( GUIComponentGL *inComponent, ScreenGL *inScreen ); virtual ~GUITranslatorGL(); /** * Translates screen coordinates to gui coordinates. * * @param inX the x value of the screen coordinate. * @param inY the y value of the screen coordinate. * @param outX a pointer to an value in which the gui x * component will be returned. * @param outY a pointer to an value in which the gui y * component will be returned. */ void translate( int inX, int inY, double *outX, double *outY ); /** * Translates screen coordinates to gui coordinates. * * @param inX the x value of the screen coordinate. * * @return the gui x component will be returned. */ double translateX( int inX ); /** * Translates screen coordinates to gui coordinates. * * @param inX the x value of the screen coordinate. * * @return the gui x component will be returned. */ double translateY( int inY ); // implements the MouseHandlerGL interface virtual void mouseMoved( int inX, int inY ); virtual void mouseDragged( int inX, int inY ); virtual void mousePressed( int inX, int inY ); virtual void mouseReleased( int inX, int inY ); // implements the KeyboardHandlerGL interface virtual char isFocused(); virtual void keyPressed( unsigned char inKey, int inX, int inY ); virtual void specialKeyPressed( int inKey, int inX, int inY ); virtual void keyReleased( unsigned char inKey, int inX, int inY ); virtual void specialKeyReleased( int inKey, int inX, int inY ); // implements the SceneHandlerGL interface virtual void drawScene(); protected: GUIComponentGL *mComponent; ScreenGL *mScreen; /** * Gets the factor by which screen coordinates need * to be multiplied to get gui coordinates. * * @return the translation factor to multiply by. */ double getTranslationFactor(); }; inline GUITranslatorGL::GUITranslatorGL( GUIComponentGL *inComponent, ScreenGL *inScreen ) : mComponent( inComponent ), mScreen( inScreen ) { } inline GUITranslatorGL::~GUITranslatorGL() { delete mComponent; } inline void GUITranslatorGL::translate( int inX, int inY, double *outX, double *outY ) { *outX = translateX( inX ); *outY = translateY( inY ); } inline double GUITranslatorGL::translateX( int inX ) { return inX * getTranslationFactor(); } inline double GUITranslatorGL::translateY( int inY ) { int height = mScreen->getImageHeight(); return ( height - inY ) * getTranslationFactor(); } inline double GUITranslatorGL::getTranslationFactor() { double width = (double)( mScreen->getImageWidth() ); double height = (double)( mScreen->getImageHeight() ); if( width <= height ) { return 1.0 / width; } else { return 1.0 / height; } } inline void GUITranslatorGL::mouseMoved( int inX, int inY ) { mComponent->mouseMoved( translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::mouseDragged( int inX, int inY ) { mComponent->mouseDragged( translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::mousePressed( int inX, int inY ) { mComponent->mousePressed( translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::mouseReleased( int inX, int inY ) { mComponent->mouseReleased( translateX( inX ), translateY( inY ) ); } inline char GUITranslatorGL::isFocused() { return mComponent->isFocused(); } inline void GUITranslatorGL::keyPressed( unsigned char inKey, int inX, int inY ) { mComponent->keyPressed( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::specialKeyPressed( int inKey, int inX, int inY ) { mComponent->specialKeyPressed( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::keyReleased( unsigned char inKey, int inX, int inY ) { mComponent->keyReleased( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::specialKeyReleased( int inKey, int inX, int inY ) { mComponent->specialKeyReleased( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::drawScene() { // setup orthographic projection matrices before // telling our component to draw itself // (thus, the component can draw in [0.0, 1.0] space // with no regard to screen size) // Ack: // some of this code was adapted from NeHe's tutorial #17, // which can be found at http://nehe.gamedev.net glMatrixMode( GL_PROJECTION ); // Select The Projection Matrix glPushMatrix(); // Store The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix // setup an orthographic projection for our 2d gui // the shorter screen dimension gets mapped to the range [0,1], // and the longer dimension extends beyond 1.0 // (0,0) is always locked to the lower left corner of the screen // we don't care about z for 2d gui's, so just select // the region around 0 double zStart = -1; double zEnd = 1; double width = mScreen->getImageWidth(); double height = mScreen->getImageHeight(); // put the excess on the top or the right if( width > height ) { double excess = width - height; double excessFraction = excess / height; glOrtho( 0, 1 + excessFraction, 0 - excessFraction / 2, 1 + excessFraction / 2, zStart, zEnd ); } else { double excess = height - width; double excessFraction = excess / width; glOrtho( 0 - excessFraction / 2, 1 + excessFraction / 2, 0, 1 + excessFraction, zStart, zEnd ); } glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix glPushMatrix(); // Store The Modelview Matrix // set the model view matrix to the identity glLoadIdentity(); glDisable( GL_DEPTH_TEST ); glDisable( GL_CULL_FACE ); // draw our gui mComponent->fireRedraw(); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); // restore the matrices glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix glPopMatrix(); // Restore The Old Modelview Matrix glMatrixMode( GL_PROJECTION ); // Select The Projection Matrix glPopMatrix(); // Restore The Old Projection Matrix } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/glGUITestCompile0000755000175000017500000000042507351044134024234 0ustar pabspabsg++ -g -o glGUITest -I/usr/X11R6/include -I../../../.. -L/usr/X11R6/lib -lGL -lglut -lGLU -lX11 -lXi -lXext -lXmu glGUITest.cpp ../../../../minorGems/graphics/openGL/ScreenGL.cpp ../../../../minorGems/io/linux/TypeIOLinux.cpp ../../../../minorGems/io/file/linux/PathLinux.cpp primrose-6+dfsg1.orig/minorGems/graphics/openGL/gui/MouseCursorRegionGL.h0000644000175000017500000000750007351276771025233 0ustar pabspabs/* * Modification History * * 2001-September-16 Jason Rohrer * Created. */ #ifndef MOUSE_CURSOR_REGION_GL_INCLUDED #define MOUSE_CURSOR_REGION_GL_INCLUDED #include "minorGems/graphics/openGL/gui/GUIComponentGL.h" #include "minorGems/graphics/Color.h" #include /** * A region in a GL-based gui where a mouse cursor * will be displayed. * * @author Jason Rohrer */ class MouseCursorRegionGL : public GUIComponentGL { public: /** * Constructs a mouse cursor region. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inCursorFraction the fraction of the * region to be filled by the cursor. * @param inUnpressedColor the color to draw the * cursor with when the mouse is unpressed. * Will be destroyed when this class is destroyed. * @param inPressedColor the color to draw the * cursor with when the mouse is pressed. * Will be destroyed when this class is destroyed. */ MouseCursorRegionGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, double inCursorFraction, Color *inUnpressedColor, Color *inPressedColor ); ~MouseCursorRegionGL(); // override functions in GUIComponentGL virtual void mouseMoved( double inX, double inY ); virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual void fireRedraw(); protected: double mCursorFraction; double mMouseLocationX; double mMouseLocationY; Color *mUnpressedColor; Color *mPressedColor; Color *mCurrentColor; }; inline MouseCursorRegionGL::MouseCursorRegionGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, double inCursorFraction, Color *inUnpressedColor, Color *inPressedColor ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mCursorFraction( inCursorFraction ), mUnpressedColor( inUnpressedColor ), mPressedColor( inPressedColor ), mMouseLocationX( -1 ), mMouseLocationY( -1 ) { mCurrentColor = mUnpressedColor; } inline MouseCursorRegionGL::~MouseCursorRegionGL() { delete mUnpressedColor; delete mPressedColor; } inline void MouseCursorRegionGL::mouseMoved( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mUnpressedColor; } inline void MouseCursorRegionGL::mouseReleased( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mUnpressedColor; } inline void MouseCursorRegionGL::mouseDragged( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mPressedColor; } inline void MouseCursorRegionGL::mousePressed( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mPressedColor; } inline void MouseCursorRegionGL::fireRedraw() { if( isInside( mMouseLocationX, mMouseLocationY ) ) { // set our color glColor3f( mCurrentColor->r, mCurrentColor->g, mCurrentColor->b ); double cursorLineLengthX = mCursorFraction * mWidth; double cursorLineLengthY = mCursorFraction * mHeight; // horizontal line glBegin( GL_LINES ); { glVertex2d( mMouseLocationX - 0.5 * cursorLineLengthX, mMouseLocationY ); glVertex2d( mMouseLocationX + 0.5 * cursorLineLengthX, mMouseLocationY ); } glEnd(); // vertical line glBegin( GL_LINES ); { glVertex2d( mMouseLocationX, mMouseLocationY - 0.5 * cursorLineLengthY ); glVertex2d( mMouseLocationX, mMouseLocationY + 0.5 * cursorLineLengthY ); } glEnd(); } } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/testScreenGLcompile0000755000175000017500000000021407220267517024246 0ustar pabspabsg++ -g -o testScreenGL -I../../.. -lGL -lglut -lGLU -L/usr/X11R6/lib ScreenGL.cpp testScreenGL.cpp ../../../minorGems/util/random/Noise.cpp primrose-6+dfsg1.orig/minorGems/graphics/openGL/RadiosGLView.ini0000644000175000017500000000013207205611501023371 0ustar pabspabsFULLSCREEN 1 DITHER 1 SCREENWIDE 640 SCREENHIGH 480 MODELFILE radiosity.out INVERTMOUSE 0 primrose-6+dfsg1.orig/minorGems/graphics/openGL/RedrawListenerGL.h0000644000175000017500000000112511062511473023725 0ustar pabspabs/* * Modification History * * 2001-February-4 Jason Rohrer * Created. */ #ifndef REDRAW_LISTENER_GL_INCLUDED #define REDRAW_LISTENER_GL_INCLUDED /** * Interface for an object that will be called at the beginning of * every openGL redraw. * * @author Jason Rohrer */ class RedrawListenerGL { public: virtual ~RedrawListenerGL() { } /** * Tells the redraw listener that a redraw is occuring. * * Note that the redraw operation waits for this call to return * before proceeding. */ virtual void fireRedraw() = 0; }; #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/SceneHandlerGL.h0000644000175000017500000000073511062511474023335 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. */ #ifndef SCENE_HANDLER_GL_INCLUDED #define SCENE_HANDLER_GL_INCLUDED /** * Interface for an object that can draw a scene onto a ScreenGL. * * @author Jason Rohrer */ class SceneHandlerGL { public: virtual ~SceneHandlerGL() { } /** * Draws a scene of objects into a ScreenGL. */ virtual void drawScene() = 0; }; #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/ScreenGL.cpp0000644000175000017500000003330111101427161022540 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-31 Jason Rohrer * Fixed a bug in the fullscreen code. * * 2001-February-4 Jason Rohrer * Added support for keyboard up functions. * Added support for redraw listeners. * Added missing initialization. * * 2001-August-29 Jason Rohrer * Added support for vectors of mouse, keyboard, and scene handlers. * * 2001-September-15 Jason Rohrer * Fixed a bug in passing redraw events to the redraw listeners. * * 2001-October-13 Jason Rohrer * Added a function for applying the view matrix transformation. * Removed unneeded code from the glutResize function. * * 2001-October-29 Jason Rohrer * Added support for focusable keyboard handlers. * * 2001-October-29 Jason Rohrer * Added support for focusable keyboard handlers. * * 2004-August-30 Jason Rohrer * Fixed distortion issues when screen aspect ratio is not 1:1. * * 2005-February-7 Jason Rohrer * Fixed bug of incorrect GL matrix stack usage. Now fog works correctly. * * 2005-February-21 Jason Rohrer * Removed incorrect call to glPopMatrix. * * 2005-March-4 Jason Rohrer * Changed to call redraw listeners before applying view transform. * * 2006-December-21 Jason Rohrer * Added functions for changing window size and switching to full screen. * * 2008-September-12 Jason Rohrer * Changed to use glutEnterGameMode for full screen at startup. * Added a 2D graphics mode. * * 2008-September-29 Jason Rohrer * Enabled ignoreKeyRepeat. * * 2008-October-27 Jason Rohrer * Prepared for alternate implementations besides GLUT. * Switched to implementation-independent keycodes. * Added support for setting viewport size separate from screen size. */ /* * Compile note: For Linux, add these library flags: * -lGL -lglut -lGLU -L/usr/X11R6/lib */ #include "ScreenGL.h" #include #include #include #include #include "minorGems/util/stringUtils.h" /* ScreenGL to be accessed by callback functions. * * Note that this is a bit of a hack, but the callbacks * require a C-function (not a C++ member) and have fixed signatures, * so there's no way to pass the current screen into the functions. * * This hack prevents multiple instances of the ScreenGL class from * being used simultaneously. */ ScreenGL *currentScreenGL; // maps GLUT-specific special key-codes (GLUT_KEY) to minorGems key codes\ // (MG_KEY) int mapGLUTKeyToMG( int inGLUTKey ); ScreenGL::ScreenGL( int inWide, int inHigh, char inFullScreen, char *inWindowName, KeyboardHandlerGL *inKeyHandler, MouseHandlerGL *inMouseHandler, SceneHandlerGL *inSceneHandler ) : mWide( inWide ), mHigh( inHigh ), mImageSizeSet( false ), mImageWide( inWide ), mImageHigh( inHigh ), mFullScreen( inFullScreen ), m2DMode( false ), mViewPosition( new Vector3D( 0, 0, 0 ) ), mViewOrientation( new Angle3D( 0, 0, 0 ) ), mMouseHandlerVector( new SimpleVector() ), mKeyboardHandlerVector( new SimpleVector() ), mSceneHandlerVector( new SimpleVector() ), mRedrawListenerVector( new SimpleVector() ) { // add handlers if NULL (the default) was not passed in for them if( inMouseHandler != NULL ) { addMouseHandler( inMouseHandler ); } if( inKeyHandler != NULL ) { addKeyboardHandler( inKeyHandler ); } if( inSceneHandler != NULL ) { addSceneHandler( inSceneHandler ); } if( mFullScreen ) { glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); //| GLUT_FULLSCREEN ); } else { glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); } if( !mFullScreen ) { glutInitWindowSize( mWide, mHigh ); glutCreateWindow( inWindowName ); } else { // use game mode for full screen char *gameMode = autoSprintf( "%dx%d:32", mWide, mHigh ); glutGameModeString( gameMode ); if( glutGameModeGet( GLUT_GAME_MODE_POSSIBLE ) ) { glutEnterGameMode(); delete [] gameMode; } else { printf( "The full-screen mode %s is not available\n", gameMode ); delete [] gameMode; exit(1); } } glutIgnoreKeyRepeat( 1 ); glutKeyboardFunc( callbackKeyboard ); glutKeyboardUpFunc( callbackKeyboardUp ); glutSpecialFunc( callbackSpecialKeyboard ); glutSpecialUpFunc( callbackSpecialKeyboardUp ); glutReshapeFunc( callbackResize ); glutMotionFunc( callbackMotion ); glutMouseFunc( callbackMouse ); glutPassiveMotionFunc( callbackPassiveMotion ); glutDisplayFunc( callbackDisplay ); glutIdleFunc( callbackIdle ); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } ScreenGL::~ScreenGL() { if( mFullScreen ) { glutLeaveGameMode(); } delete mViewPosition; delete mViewOrientation; delete mRedrawListenerVector; delete mMouseHandlerVector; delete mKeyboardHandlerVector; delete mSceneHandlerVector; } void ScreenGL::start() { currentScreenGL = this; glutMainLoop(); } void ScreenGL::switchTo2DMode() { m2DMode = true; } void ScreenGL::setFullScreen() { glutFullScreen(); } void ScreenGL::changeWindowSize( int inWidth, int inHeight ) { glutReshapeWindow( inWidth, inHeight ); } void ScreenGL::applyViewTransform() { // compute view angle // default angle is 90, but we want to force a 1:1 aspect ratio to avoid // distortion. // If our screen's width is different than its height, we need to decrease // the view angle so that the angle coresponds to the smaller dimension. // This keeps the zoom factor constant in the smaller dimension. // Of course, because of the way perspective works, only one Z-slice // will have a constant zoom factor // The zSlice variable sets the distance of this slice from the picture // plane double zSlice = .31; double maxDimension = mWide; if( mHigh > mWide ) { maxDimension = mHigh; } double aspectDifference = fabs( mWide / 2 - mHigh / 2 ) / maxDimension; // default angle is 90 degrees... half the angle is PI/4 double angle = atan( tan( M_PI / 4 ) + aspectDifference / zSlice ); // double it to get the full angle angle *= 2; // convert to degrees angle = 360 * angle / ( 2 * M_PI ); // set up the projection matrix glMatrixMode( GL_PROJECTION ); glLoadIdentity(); //gluPerspective( 90, mWide / mHigh, 1, 9999 ); gluPerspective( angle, 1, 1, 9999 ); // set up the model view matrix glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); // create default view and up vectors, // then rotate them by orientation angle Vector3D *viewDirection = new Vector3D( 0, 0, 1 ); Vector3D *upDirection = new Vector3D( 0, 1, 0 ); viewDirection->rotate( mViewOrientation ); upDirection->rotate( mViewOrientation ); // get a point out in front of us in the view direction viewDirection->add( mViewPosition ); // look at takes a viewer position, // a point to look at, and an up direction gluLookAt( mViewPosition->mX, mViewPosition->mY, mViewPosition->mZ, viewDirection->mX, viewDirection->mY, viewDirection->mZ, upDirection->mX, upDirection->mY, upDirection->mZ ); delete viewDirection; delete upDirection; } void callbackResize( int inW, int inH ) { ScreenGL *s = currentScreenGL; s->mWide = inW; s->mHigh = inH; if( ! s->mImageSizeSet ) { // keep image size same as screen size s->mImageWide = inW; s->mImageHigh = inH; } int bigDimension = s->mImageWide; if( bigDimension < s->mImageHigh ) { bigDimension = s->mImageHigh; } int excessW = s->mWide - bigDimension; int excessH = s->mHigh - bigDimension; // viewport is square of biggest image dimension, centered on screen // (to ensure a 1:1 aspect ratio) glViewport( excessW / 2, excessH / 2, bigDimension, bigDimension ); /* if( s->mWide >= s->mHigh ) { int excess = s->mWide - s->mHigh; glViewport( 0, -excess / 2, s->mWide, s->mWide ); } else { int excess = s->mHigh - s->mWide; glViewport( -excess / 2, 0, s->mHigh, s->mHigh ); } */ glutPostRedisplay(); } void callbackKeyboard( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyPressed( inKey, inX, inY ); } } } void callbackKeyboardUp( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyReleased( inKey, inX, inY ); } } } void callbackSpecialKeyboard( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyPressed( mapGLUTKeyToMG( inKey ), inX, inY ); } } } void callbackSpecialKeyboardUp( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyReleased( mapGLUTKeyToMG( inKey ), inX, inY ); } } } void callbackMotion( int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseDragged( inX, inY ); } } void callbackPassiveMotion( int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseMoved( inX, inY ); } } void callbackMouse( int inButton, int inState, int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseMoved( inX, inY ); if( inState == GLUT_DOWN ) { handler->mousePressed( inX, inY ); } else if( inState == GLUT_UP ) { handler->mouseReleased( inX, inY ); } else { printf( "Error: Unknown mouse state received from OpenGL\n" ); } } } void callbackDisplay() { ScreenGL *s = currentScreenGL; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // fire to all redraw listeners // do this first so that they can update our view transform // this makes control much more responsive for( int r=0; rmRedrawListenerVector->size(); r++ ) { RedrawListenerGL *listener = *( s->mRedrawListenerVector->getElement( r ) ); listener->fireRedraw(); } if( ! s->m2DMode ) { // apply our view transform s->applyViewTransform(); } // fire to all handlers for( int h=0; hmSceneHandlerVector->size(); h++ ) { SceneHandlerGL *handler = *( currentScreenGL->mSceneHandlerVector->getElement( h ) ); handler->drawScene(); } glutSwapBuffers(); } void callbackIdle() { glutPostRedisplay(); } int mapGLUTKeyToMG( int inGLUTKey ) { switch( inGLUTKey ) { case GLUT_KEY_F1: return MG_KEY_F1; case GLUT_KEY_F2: return MG_KEY_F2; case GLUT_KEY_F3: return MG_KEY_F3; case GLUT_KEY_F4: return MG_KEY_F4; case GLUT_KEY_F5: return MG_KEY_F5; case GLUT_KEY_F6: return MG_KEY_F6; case GLUT_KEY_F7: return MG_KEY_F7; case GLUT_KEY_F8: return MG_KEY_F8; case GLUT_KEY_F9: return MG_KEY_F9; case GLUT_KEY_F10: return MG_KEY_F10; case GLUT_KEY_F11: return MG_KEY_F11; case GLUT_KEY_F12: return MG_KEY_F12; case GLUT_KEY_LEFT: return MG_KEY_LEFT; case GLUT_KEY_UP: return MG_KEY_UP; case GLUT_KEY_RIGHT: return MG_KEY_RIGHT; case GLUT_KEY_DOWN: return MG_KEY_DOWN; case GLUT_KEY_PAGE_UP: return MG_KEY_PAGE_UP; case GLUT_KEY_PAGE_DOWN: return MG_KEY_PAGE_DOWN; case GLUT_KEY_HOME: return MG_KEY_HOME; case GLUT_KEY_END: return MG_KEY_END; case GLUT_KEY_INSERT: return MG_KEY_INSERT; default: return 0; } } primrose-6+dfsg1.orig/minorGems/graphics/openGL/TestHandlerGL.h0000644000175000017500000002707207343227173023231 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-9 Jason Rohrer * Changed to use new Primitive3D implementations. * * 2001-January-16 Jason Rohrer * Changed to use new Translate3D class for drawing primitives. * * 2001-January-30 Jason Rohrer * Updated to comply with new Primitive3D interface. * * 2001-January-31 Jason Rohrer * Added definition of M_PI if not automatically defined. * Added a quit key handler. * Added multitexturing to central quad to test multitexture implementations. * Had to recommit because of lost log message. * * 2001-February-2 Jason Rohrer * Fixed a bug in the way textures were generated. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. * * 2001-August-29 Jason Rohrer * Fixed to use new KeyboardHandler interface. */ #ifndef TEST_HANDLER_GL_INCLUDED #define TEST_HANDLER_GL_INCLUDED #include #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #include "ScreenGL.h" #include "MouseHandlerGL.h" #include "KeyboardHandlerGL.h" #include "SceneHandlerGL.h" #include "PrimitiveGL.h" #include "ObjectGL.h" #include "minorGems/graphics/3d/LathePrimitive3D.h" #include "minorGems/graphics/3d/LandscapePrimitive3D.h" #include "TextureGL.h" #include "LightingGL.h" #include "NoLightingGL.h" #include "DirectionLightingGL.h" #include "MultiLightingGL.h" #include "minorGems/math/geometry/Vector3D.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/graphics/Color.h" #include "minorGems/graphics/RGBAImage.h" #include "minorGems/graphics/filters/BoxBlurFilter.h" #include "minorGems/graphics/filters/ThresholdFilter.h" #include "minorGems/graphics/filters/InvertFilter.h" #include "minorGems/util/random/RandomSource.h" #include "minorGems/util/random/Noise.h" #include "minorGems/graphics/Image.h" /** * Test class for ScreenGL implementation. * * Draws a simple polygon. * * @author Jason Rohrer */ class TestHandlerGL : public MouseHandlerGL, public KeyboardHandlerGL, public SceneHandlerGL { public: TestHandlerGL( RandomSource *inRandSource, int inNumTriangles ); ~TestHandlerGL(); /** * Sets up primitives. Must be called *after* OpenGL context is * constructed. */ void setupPrimitives(); // implement the MouseHandlerGL interface void mouseMoved( int inX, int inY ); void mouseDragged( int inX, int inY ); void mousePressed( int inX, int inY ); void mouseReleased( int inX, int inY ); // implement the KeyboardHandlerGL interface void keyPressed( unsigned char inKey, int inX, int inY ); void specialKeyPressed( int inKey, int inX, int inY ); void keyReleased( unsigned char inKey, int inX, int inY ); void specialKeyReleased( int inKey, int inX, int inY ); // implement the SceneHandlerGL interface void drawScene(); private: RandomSource *mRandSource; int mNumTriangles; Vector3D ***mTriangles; Color ***mColors; PrimitiveGL *mPrimitive; PrimitiveGL *mPrimitive2; PrimitiveGL *mPrimitive3; LightingGL *mLightingA; LightingGL *mLightingB; MultiLightingGL *mLighting; double mCurrentAngle; double mAngleStep; }; TestHandlerGL::TestHandlerGL( RandomSource *inRandSource, int inNumTriangles ) : mRandSource( inRandSource ), mNumTriangles( inNumTriangles ), mTriangles( new Vector3D**[inNumTriangles] ), mColors( new Color**[inNumTriangles] ) { mLightingA = new DirectionLightingGL( new Color( 1.0, 1.0, 1.0 ), new Vector3D( 0, 0, 1 ) ); mLightingB = new DirectionLightingGL( new Color( 0, 0, 1.0 ), new Vector3D( 1, 1, 0 ) ); mLighting = new MultiLightingGL(); mLighting->addLighting( mLightingA ); mLighting->addLighting( mLightingB ); for( int i=0; igetRandomDouble() * 10, mRandSource->getRandomDouble() * 10 - 5, mRandSource->getRandomDouble() * 10 ); mColors[i][j] = new Color( mRandSource->getRandomFloat(), mRandSource->getRandomFloat(), mRandSource->getRandomFloat(), mRandSource->getRandomFloat() ); } } } TestHandlerGL::~TestHandlerGL() { for( int i=0; igetChannel(0), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(1), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(2), textSize, textSize, fPower, true, mRandSource ); Image *selection = new Image( textSize, textSize, 1 ); genFractalNoise2d( selection->getChannel(0), textSize, textSize, fPower, true, mRandSource ); BoxBlurFilter *blur = new BoxBlurFilter( 10 ); ThresholdFilter *threshold = new ThresholdFilter( 0.5 ); InvertFilter *invert = new InvertFilter(); selection->filter( threshold ); noiseImage->setSelection( selection ); //noiseImage->filter(invert); delete blur; delete threshold; delete invert; noiseImage->clearSelection(); delete selection; /*for( int t=0; tcopy(); //double *alpha = imageArray[1]->getChannel(3); //int numPixels = imageArray[1]->getWidth() * imageArray[1]->getHeight(); //for( int p=0; psetTransparent( true ); // all passed in args will be destroyed when primitive is destroyed // setup second primitive Vector3D **latheCurve = new Vector3D*[4]; latheCurve[0] = new Vector3D( 0.5, 1, 0 ); latheCurve[1] = new Vector3D( 1, 0.5, 0 ); latheCurve[2] = new Vector3D( 1, -0.5, 0 ); latheCurve[3] = new Vector3D( 0.5, -1, 0 ); noiseImage = new RGBAImage( textSize, textSize ); genFractalNoise2d( noiseImage->getChannel(0), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(1), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(2), textSize, textSize, fPower, true, mRandSource ); Primitive3D *lathePrimitive3D = new LathePrimitive3D( 4, latheCurve, 15, 2 * M_PI, noiseImage ); lathePrimitive3D->setTransparent( false ); mPrimitive2 = new PrimitiveGL( lathePrimitive3D ); //mPrimitive2->setBackVisible( true ); // all passed in args will be destroyed when primitive is destroyed noiseImage = new RGBAImage( textSize, textSize ); genFractalNoise2d( noiseImage->getChannel(0), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(1), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(2), textSize, textSize, fPower, true, mRandSource ); int landSize = 20; unsigned long *intHeights = new unsigned long[ landSize * landSize ]; genFractalNoise2d( intHeights, landSize, landSize ); double *heights = new double[ landSize * landSize ]; for( int l=0; lr, mColors[p][v]->g, mColors[p][v]->b, mColors[p][v]->a ); glVertex3f( mTriangles[p][v]->mX, mTriangles[p][v]->mY, mTriangles[p][v]->mZ ); } } glEnd(); */ Vector3D *pos = new Vector3D( 0, 0, 10 ); Angle3D *rot = new Angle3D( mCurrentAngle, mCurrentAngle, 0 ); //Angle3D *rot = new Angle3D( 0, 0, 0 ); Transform3D *trans = new Transform3D(); trans->scale( 5 ); trans->rotate( rot ); trans->translate( pos ); //mPrimitive->setBackVisible( false ); mPrimitive->draw( trans, mLighting ); delete rot; delete pos; delete trans; pos = new Vector3D( 0, -10, 10 ); rot = new Angle3D( 0, mCurrentAngle, 0 ); trans = new Transform3D(); trans->scale( 20 ); trans->rotate( rot ); trans->translate( pos ); mPrimitive3->draw( trans, mLighting ); delete rot; delete pos; delete trans; pos = new Vector3D( 0, 5, 0 ); rot = new Angle3D( M_PI, mCurrentAngle, 0 ); trans = new Transform3D(); trans->scale( 20 ); trans->rotate( rot ); trans->translate( pos ); //mPrimitive3->setBackVisible( false ); //mPrimitive3->draw( trans, mLighting ); delete rot; delete pos; delete trans; mCurrentAngle += mAngleStep; } #endif primrose-6+dfsg1.orig/minorGems/graphics/openGL/TextureGL.h0000644000175000017500000002335507236121004022437 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-19 Jason Rohrer * Added support for multi-texturing. Now a TextureGL no longer has * an overall width and height (each layer can have a different size). * Also, a TextureGL no longer has an overall ID. * Got rid of an old, commented-out interface in the process. * Changed how multi-textures are blended. Settled on using MODULATE * for all layers of the texture, since nothing else produces results * that are compatible with vertex lighting. * * 2001-January-30 Jason Rohrer * Changed to check for GL version 1.2 before using 1.2 features. * Now we assume multi-texture is defined (because of the availability * of glext), but we check that it is supported at runtime. * Moved enable() below ARB function name definitions. * * 2001-January-31 Jason Rohrer * Fixed even more compile bugs. There's no need to do a multitexture * bind when setting texture data. * Removed extra checks for unneeded extensions, and fixed more compile bugs. * Fixed a bug in initMultitexture(). * Fixed a bug in disable(). */ #ifndef TEXTURE_GL_INCLUDED #define TEXTURE_GL_INCLUDED #include #include #include // try and include extensions if multitexture isn't // built-in to gl.h #ifndef GL_ARB_multitexture #include #endif /** * OpenGL 32-bit multi-layered texture map. * * @author Jason Rohrer */ class TextureGL { public: /** * Constructs a texture map. * * @param inNumLayers the number of multi-texture layers * in this texture. Currently supports a value in range [1:8]. */ TextureGL( int inNumLayers ); /** * The OpenGL texture is deleted when the TextureGL object is * destroyed. */ ~TextureGL(); /** * Sets the data for a layer of this texture. * * Blocks of 4 characters specify each pixel, and each * block must be ordered as RGBA. * * Note that width and height must each be powers of 2 and * not larger than 256 (for 3DFX compatability). Additionally, * for 3DFX compatability, the aspect ratio should not exceed 8:1. * * @param inLayer the multi-texture layer to set the data to. * @param inData a character array containing the color and alpha * components for this texture. All data is copied internally. * @param inWide width of the map in 4-byte blocks. * @param inHigh height of the map. */ void setTextureData( int inLayer, unsigned char *inData, int inWide, int inHigh ); /** * Gets the number of layers in this multi-texture. * * @return the number of layers in this multi-texture. */ int getNumLayers(); /** * Enables this texture and all of its layers. * * Note that this function only makes sense when * isMultitexturingSupported() returns true. * Otherwise, it is equivalent * to calling enable( 0 ). */ void enable(); /** * Enables a particular texture layer. * * @param inLayerNumber the layer to enable. */ void enable( int inLayerNumber ); /** * Disables this texture and all of its layers. */ void disable(); /** * Gets whether multitexturing is supported by the loaded * GL implementation. * * @return true if multitexturing is supported. */ static char isMultiTexturingSupported(); static GLenum sMultiTextureEnum[8]; private: static int sNextFreeTextureID; int mNumLayers; unsigned int *mTextureID; static const int MAX_NUM_LAYERS = 8; static char sMultiTexturingSupported; // a static initializer function static void staticInit(); static char sBeenInited; }; // initialize static members int TextureGL::sNextFreeTextureID = 13; char TextureGL::sBeenInited = false; char TextureGL::sMultiTexturingSupported = false; GLenum TextureGL::sMultiTextureEnum[MAX_NUM_LAYERS] = { GL_TEXTURE0_ARB, GL_TEXTURE1_ARB, GL_TEXTURE2_ARB, GL_TEXTURE3_ARB, GL_TEXTURE4_ARB, GL_TEXTURE5_ARB, GL_TEXTURE6_ARB, GL_TEXTURE7_ARB }; inline TextureGL::TextureGL( int inNumLayers ) : mNumLayers( inNumLayers ), mTextureID( new unsigned int[inNumLayers] ) { if( !sBeenInited ) { // call static initializer function TextureGL::staticInit(); } if( inNumLayers > MAX_NUM_LAYERS ) { printf( "TextureGL only supports 8 multi-texture layers.\n" ); printf( "The following number of layers is out of range: %d\n", inNumLayers ); } for( int i=0; i1) && string[i-1]=='\n')) { // New Extension Begins Here! other=&string[i]; pos=0; // Begin New Search while (string[i]!='\n') { // Search Whole Extension-String if (string[i]==search[pos]) pos++; // Next Position if ((pos>maxpos) && string[i+1]=='\n') return true; // We Have A Winner! i++; } } } return false; // Sorry, Not Found! } // isMultitextureSupported() Checks At Run-Time If Multitexturing Is Supported inline char initMultitexture(void) { char *extString = (char *)glGetString( GL_EXTENSIONS ); // Fetch Extension String int len = strlen( extString ); // allow for end of string character char *extensions = new char[ len + 1 ]; strcpy( extensions, extString ); for (int i=0; i #include "Color.h" class IconMap { public: IconMap( int w, int h); // construct a map of a certain width and height IconMap( int w, int h, int *offset ); // pass in precomputed y offsets into image map ~IconMap(); int wide; int high; int numPixels; int *yOffset; unsigned long *imageMap; // draw a solid IconMap into this IconMap void drawIconMap( IconMap *icon, int xPos, int yPos ); // draw a transparent IconMap into this IconMap void drawIconMapAlpha( IconMap *icon, int xPos, int yPos ); void copy( IconMap *icon ); // copy contents of another icon map into this one // does nothing if icon maps aren't the same size private: char yOffsetExternal; // is the yOffset ptr external? float invChannelMax; Color utilColor; }; inline IconMap::IconMap( int w, int h ) { invChannelMax = 1 / 255.0; wide = w; high = h; numPixels = wide * high; imageMap = new unsigned long[ wide * high ]; yOffset = new int[high]; for( int y=0; yimageMap; int *imageYOffset = icon->yOffset; int imageWide = icon->wide; int imageHigh = icon->high; // watch for buffer bounds int minY = yPos; if( minY < 0 ) { minY = 0; } int maxY = yPos + imageHigh; if( maxY > high ) { maxY = high; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + imageWide; if( maxX > wide ) { maxX = wide; } for( int y=minY; yimageMap; int *imageYOffset = icon->yOffset; int imageWide = icon->wide; int imageHigh = icon->high; // watch for buffer bounds int minY = yPos; if( minY < 0 ) { minY = 0; } int maxY = yPos + imageHigh; if( maxY > high ) { maxY = high; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + imageWide; if( maxX > wide ) { maxX = wide; } for( int y=minY; y> 24) * invChannelMax; float oneMinusAlpha = 1-alpha; unsigned long buffARGB = imageMap[ buffYContrib + x ]; argb = utilColor.getWeightedComposite( argb, alpha ); buffARGB = utilColor.getWeightedComposite( buffARGB, oneMinusAlpha ); unsigned long sum = utilColor.sumComposite( argb, buffARGB ); imageMap[ buffYContrib + x ] = sum; } } } inline void IconMap::copy( IconMap *icon ) { // make sure they are the same size if( numPixels != icon->numPixels ) { return; } // void * memcpy (void * dst, const void * src, size_t len); // each pixel is 4 bytes, so shift numPixels by 2 memcpy( (void *)(imageMap), (void *)(icon->imageMap), numPixels << 2 ); } #endif primrose-6+dfsg1.orig/minorGems/graphics/3d/0000755000175000017500000000000011201637526017525 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/3d/LandscapePrimitive3D.h0000644000175000017500000000776707253033271023670 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. Copied from LandscapePrimitiveGL, which this class will replace * * 2001-January-15 Jason Rohrer * Fixed a bug in the constructor. * * 2001-January-17 Jason Rohrer * Fliped how x and y in height map correspond to x and z in the terrain. * * 2001-January-19 Jason Rohrer * Changed to support multi-texturing. * * 2001-January-30 Jason Rohrer * Fixed a bug that occurs when the class defaults to no detail texture. * * 2001-March-11 Jason Rohrer * Fixed a bug in the texture map anchor points. */ #ifndef LANDSCAPE_PRIMITIVE_3D_INCLUDED #define LANDSCAPE_PRIMITIVE_3D_INCLUDED #include "Primitive3D.h" /** * Primitive 3D lanscape object. * * Made from a height map. Mesh generated spans both x and z between -1 and * 1, and can vary in height (y) from 0 to 1. * * @author Jason Rohrer */ class LandscapePrimitive3D : public Primitive3D { public: /** * Constructs a LandscapePrimitive with a multi-layer texture. * * @param inWide width of mesh in number of vertices. * Must be even and at least 2. * @param inHigh height of mesh in number of vertices. * @param inHeights array of heights for each vertex, each in * [0,1]. Must be destroyed by caller. * @param inTexture the texture to map onto the lanscape. * Texture is anchored by its corners to the corners of the * lanscape. inTexture is destroyed when primitive is destroyed. * @param inDetailTexture the second layer in the multi-texture. * The alpha channel of inDetailTexture will be used as * the blending factor to mix the detail with the global texture. * Set to NULL to use only a single layer. * @param inDetailScale the scale factor of the detailed texture. * Setting to 1.0 will anchor the detail at the corners of the * mesh (just like inTexture). Setting to 0.25 will cause * the detail texture to cycle 4 times across the surface of the * mesh. */ LandscapePrimitive3D( int inWide, int inHigh, double *inHeights, RGBAImage *inTexture, RGBAImage *inDetailTexture = NULL, double inDetailScale = 1.0 ); }; inline LandscapePrimitive3D::LandscapePrimitive3D( int inWide, int inHigh, double *inHeights, RGBAImage *inTexture, RGBAImage *inDetailTexture, double inDetailScale ) { // first, set Primitve3D members mHigh = inHigh; mWide = inWide; mNumVertices = mHigh * mWide; if( inDetailTexture == NULL ) { mNumTextures = 1; mTexture = new RGBAImage*[1]; mTexture[0] = inTexture; mAnchorX = new double*[1]; mAnchorY = new double*[1]; mAnchorX[0] = new double[mNumVertices]; mAnchorY[0] = new double[mNumVertices]; } else { mNumTextures = 2; mTexture = new RGBAImage*[2]; mTexture[0] = inTexture; mTexture[1] = inDetailTexture; mAnchorX = new double*[2]; mAnchorY = new double*[2]; mAnchorX[0] = new double[mNumVertices]; mAnchorY[0] = new double[mNumVertices]; mAnchorX[1] = new double[mNumVertices]; mAnchorY[1] = new double[mNumVertices]; } mVertices = new Vector3D*[mNumVertices]; // anchor at texture corners, and step linearly through texture double anchorYStep = 1.0 / ( mHigh - 1 ); double anchorXStep = 1.0 / ( mWide - 1 ); double detailAnchorYStep = 1.0 / ( ( mHigh - 1 ) * inDetailScale ); double detailAnchorXStep = 1.0 / ( ( mWide - 1 ) * inDetailScale ); for( int y=0; y #include "minorGems/graphics/RGBAImage.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/math/geometry/Vector3D.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/io/Serializable.h" /** * 3D primitive object. * * Comprised of a triangle mesh, texture map, and anchor points. * * @author Jason Rohrer */ class Primitive3D : public Serializable { public: /** * Constructs a Primitive. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * primitive is destroyed. * * @param inWide width of mesh in number of vertices. * Must be even and at least 2. * @param inHigh height of mesh in number of vertices. * @param inVertices vertices in row-major order. * @param inNumTextures number of multi-texture layers for * this primitive. * @param inTexture array of textures to map onto mesh. * Note that no RGBAImage in this array should have a * selection in it. * @param inAnchorX x texture anchors for each texture and * each vertex (indexed as inAnchorX[textNum][vertNum]), * in range [0,1] (outside this range, texture will wrap). * @param inAnchorY y texture anchors for each texture and * each vertex (indexed as inAnchorY[textNum][vertNum]), * in range [0,1] (outside this range, texture will wrap). */ Primitive3D( long inWide, long inHigh, Vector3D **inVertices, long inNumTextures, RGBAImage **inTexture, double **inAnchorX, double **inAnchorY ); // construct without initializing any members // for use by subclasses and for deserialization. Primitive3D(); char mMembersAllocated; ~Primitive3D(); /** * Sets whether this primitive is transparent or not. Default * is not transparent. * * @param inTransparent true if this primitive is transparent. */ void setTransparent( char inTransparent ); /** * Gets whether this primitive is transparent or not. * * @return true iff this primitive is transparent. */ char isTransparent(); /** * Sets whether this primitive's back face is visible. Default * is not visible. * * @param inIsVisible true if the back face is visible. */ void setBackVisible( char inIsVisible ); /** * Gets whether this primitive's back face is visible or not. * * @return true iff the back face is visible. */ char isBackVisible(); /** * Gets a new instance of the derived class type. * * Should be equivalent to calling the default constructor * for the derived class type. * * Should be overridden by all derived classes that * have data members beyond those provided by Primitive3D. * Note that if the extra data members require copying, * then the copy() function should be overridden instead * of simply overriding this function. * * Primitive3D::copy() will use this function to produce * a class instance before doing a copy. * * Note that this functionality SHOULD be provided by * the built-in RTTI, but it doesn't seem to be. * * @return an instance of the derived class. */ virtual Primitive3D *getNewInstance(); /** * Copies this primitive. * * @return a copy of this primitive, which must be destroyed * by the caller. */ virtual Primitive3D *copy(); /** * Gets the number of parameters associated with this object. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this object. * * @return the number of animations. */ virtual int getNumAnimations(); /* * Note that the default implementations for all the parameter * and temporal animation functions do nothing. */ /** * Sets a parameter for this primative. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this primative. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this primitive forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this primitive. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this primitive. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); long mHigh, mWide; long mNumVertices; Vector3D **mVertices; Vector3D **mNormals; long mNumTextures; // Note that no RGBAImage in this array should have a // selection in it. RGBAImage **mTexture; double **mAnchorX; double **mAnchorY; // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); protected: /** * Generates standard normals from the vertices. * * If subclass is not generating normals, this * must be called before primitive is drawn, but after * the vertices have been initialized. */ void generateNormals(); char mTransparent; char mBackVisible; }; inline Primitive3D::Primitive3D( long inWide, long inHigh, Vector3D **inVertices, long inNumTextures, RGBAImage **inTexture, double **inAnchorX, double **inAnchorY ) : mHigh( inHigh ), mWide( inWide ), mNumVertices( inHigh * inWide ), mNumTextures( inNumTextures ), mVertices( inVertices ), mTexture( inTexture ), mAnchorX( inAnchorX ), mAnchorY( inAnchorY ), mTransparent( false ), mBackVisible( false ), mMembersAllocated( true ) { generateNormals(); } inline Primitive3D::Primitive3D() : mTransparent( false ), mBackVisible( false ), mMembersAllocated( false ) { } inline Primitive3D::~Primitive3D() { if( mMembersAllocated ) { int i; for( i=0; isubtract( mVertices[ index ] ); } } // now cross and add into sum for( e=0; e<4; e++ ) { if( edges[e] != NULL && edges[ (e+1) % 4 ] != NULL ) { // not that this order of crossing works // because our cross product is right handed Vector3D *normal = edges[e]->cross( edges[ (e+1) % 4 ] ); normal->normalize(); // add this normal to our sum normalSum->add( normal ); delete normal; } } // now delete edges for( e=0; e<4; e++ ) { if( edges[e] != NULL ) { delete edges[e]; } } delete [] edges; // save summed normal as normal for this point normalSum->normalize(); mNormals[index] = normalSum; } } } inline void Primitive3D::setTransparent( char inTransparent ) { mTransparent = inTransparent; } inline char Primitive3D::isTransparent() { return mTransparent; } inline void Primitive3D::setBackVisible( char inIsVisible ) { mBackVisible = inIsVisible; } inline char Primitive3D::isBackVisible() { return mBackVisible; } inline Primitive3D *Primitive3D::getNewInstance() { return new Primitive3D(); } inline Primitive3D *Primitive3D::copy() { // get an instance of the derived class, if they've // overridden getNewInstance() Primitive3D *primCopy = getNewInstance(); primCopy->mHigh = mHigh; primCopy->mWide = mWide; primCopy->mNumVertices = mNumVertices; primCopy->mVertices = new Vector3D*[mNumVertices]; primCopy->mNormals = new Vector3D*[mNumVertices]; int i; for( i=0; imVertices[i] = new Vector3D( mVertices[i] ); primCopy->mNormals[i] = new Vector3D( mNormals[i] ); } primCopy->mNumTextures = mNumTextures; primCopy->mTexture = new RGBAImage*[mNumTextures]; primCopy->mAnchorX = new double*[mNumTextures]; primCopy->mAnchorY = new double*[mNumTextures]; for( i=0; imTexture[i] = mTexture[i]->copy(); primCopy->mAnchorX[i] = new double[mNumVertices]; primCopy->mAnchorY[i] = new double[mNumVertices]; memcpy( primCopy->mAnchorX[i], mAnchorX[i], sizeof( double ) * mNumVertices ); memcpy( primCopy->mAnchorY[i], mAnchorY[i], sizeof( double ) * mNumVertices ); } primCopy->mMembersAllocated = true; primCopy->setBackVisible( isBackVisible() ); primCopy->setTransparent( isTransparent() ); return primCopy; } inline int Primitive3D::getNumParameters() { return 0; } inline int Primitive3D::getNumAnimations() { return 0; } // the base class versions of these functions do nothing inline void Primitive3D::setParameter( int inParameterIndex, double inValue ) { } inline double Primitive3D::getParameter( int inParameterIndex ) { return 0; } inline void Primitive3D::step( double inStepSize ) { } inline void Primitive3D::startAnimation( int inAnimationIndex ) { } inline void Primitive3D::stopAnimation( int inAnimationIndex ) { } inline int Primitive3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; numBytes += inOutputStream->writeLong( mWide ); numBytes += inOutputStream->writeLong( mHigh ); int i; // output vertices and normals for( i=0; iserialize( inOutputStream ); } for( i=0; iserialize( inOutputStream ); } numBytes += inOutputStream->writeLong( mNumTextures ); // output textures for( i=0; iserialize( inOutputStream ); } // output anchor arrays for( i=0; iwriteDouble( mAnchorX[i][p] ); } } for( i=0; iwriteDouble( mAnchorY[i][p] ); } } numBytes += inOutputStream->write( (unsigned char *)&mTransparent, 1 ); numBytes += inOutputStream->write( (unsigned char *)&mBackVisible, 1 ); return numBytes; } inline int Primitive3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; int i; if( mMembersAllocated ) { // delete the old vertices, normals, and anchors for( i=0; ireadLong( &mWide ); numBytes += inInputStream->readLong( &mHigh ); mNumVertices = mHigh * mWide; mVertices = new Vector3D*[mNumVertices]; mNormals = new Vector3D*[mNumVertices]; // input vertices and normals for( i=0; ideserialize( inInputStream ); } for( i=0; ideserialize( inInputStream ); } // input number of textures numBytes += inInputStream->readLong( &mNumTextures ); mAnchorX = new double*[mNumTextures]; mAnchorY = new double*[mNumTextures]; mTexture = new RGBAImage*[mNumTextures]; // input textures for( i=0; ideserialize( inInputStream ); } // input anchor arrays for( i=0; ireadDouble( &( mAnchorX[i][p] ) ); } } for( i=0; ireadDouble( &( mAnchorY[i][p] ) ); } } numBytes += inInputStream->read( (unsigned char *)&mTransparent, 1 ); numBytes += inInputStream->read( (unsigned char *)&mBackVisible, 1 ); mMembersAllocated = true; return numBytesRead; } #endif primrose-6+dfsg1.orig/minorGems/graphics/3d/Primitive3DFactory.h0000644000175000017500000000646207261725075023405 0ustar pabspabs/* * Modification History * * 2001-March-14 Jason Rohrer * Created. * * 2001-April-1 Jason Rohrer * Added subreal entity vane class to factory. */ #ifndef PRIMITIVE_3D_FACTORY_INCLUDED #define PRIMITIVE_3D_FACTORY_INCLUDED #include "Primitive3D.h" // Run-time type identification interface (RTTI) #include // include these primitives only if we are part of subreal #ifdef SUBREAL #include "subreal/entity/EntityBodyPrimitive3D.h" #define FACTORY_ENTITY_BODY_PRIMITIVE_FLAG 1 #include "subreal/entity/EntityVanePrimitive3D.h" #define FACTORY_ENTITY_VANE_PRIMITIVE_FLAG 2 #endif // the default flag #define FACTORY_DEFAULT_PRIMITIVE_FLAG 0 /** * Class that maps Primitive3D integer subclass type flags to Primitive3D * subclass instances. * * Motivation for this class: * We want to extend Object3D to support subclass typed serialization * and deserialization without placing too much of a burden on * future Object3D subclasses. For instance, we don't want subclasses * to have to write their own de/serialization functions so that * particular Primitive3D subclasses are serialized correctly. * We can avoid this burden by writing the base Object3D serialization * code so that it uses this factory to transmit subclasses with * type informaton. * * @author Jason Rohrer */ class Primitive3DFactory { public: /** * Finds an integer subclass type flag for a primitive instance. * * @param inPrimitive the primitive to determine a flag for. Must * be destroyed by the caller. * * @return a type flag for inObject. 0 (the default Object3D * baseclass flag) will be returned if subclass determination fails. */ static int primitive3DToInt( Primitive3D *inPrimitive ); /** * Constructs a new, unitialized Primitive3D (in other words, * an Primitive3D ready for deserialization) of a subclass * type matching inTypeFlag. * * @param inTypeFlag the type flag specifying the class * of the returned primitive. * * @return an (unitialized) Primitive3D class instance with a * subclass type corresponding to inTypeFlag. If no * matching class is found, a default Primitive3D baseclass * instance is returned. Must be destroyed by the caller. */ static Primitive3D *intToPrimitive3D( int inTypeFlag ); }; inline int Primitive3DFactory::primitive3DToInt( Primitive3D *inPrimitive ) { // use RTTI to determine type of inPrimitive #ifdef SUBREAL if( typeid( *inPrimitive ) == typeid( EntityBodyPrimitive3D ) ) { return FACTORY_ENTITY_BODY_PRIMITIVE_FLAG; } else if( typeid( *inPrimitive ) == typeid( EntityVanePrimitive3D ) ) { return FACTORY_ENTITY_VANE_PRIMITIVE_FLAG; } #endif // else return the default flag return FACTORY_DEFAULT_PRIMITIVE_FLAG; } inline Primitive3D *Primitive3DFactory::intToPrimitive3D( int inTypeFlag ) { switch( inTypeFlag ) { case FACTORY_DEFAULT_PRIMITIVE_FLAG: return new Primitive3D(); break; /* these primitives are only defined if * we are part of subreal */ #ifdef SUBREAL case FACTORY_ENTITY_BODY_PRIMITIVE_FLAG: return new EntityBodyPrimitive3D(); break; case FACTORY_ENTITY_VANE_PRIMITIVE_FLAG: return new EntityVanePrimitive3D(); break; #endif default: // unknown primitive flag type return new Primitive3D(); break; } } #endif primrose-6+dfsg1.orig/minorGems/graphics/3d/Object3DFactory.h0000644000175000017500000000645207261725007022635 0ustar pabspabs/* * Modification History * * 2001-March-14 Jason Rohrer * Created. * * 2001-March-17 Jason Rohrer * Finished implementation. * * 2001-April-1 Jason Rohrer * Fixed flag name. */ #ifndef OBJECT_3D_FACTORY_INCLUDED #define OBJECT_3D_FACTORY_INCLUDED #include "Object3D.h" // Run-time type identification interface (RTTI) #include // include these objects only if we are part of subreal #ifdef SUBREAL #include "subreal/entity/EntityObject3D.h" #define FACTORY_ENTITY_OBJECT_FLAG 1 #endif // the default flag #define FACTORY_DEFAULT_OBJECT_FLAG 0 /** * Class that maps Object3D integer subclass type flags to Object3D * subclass instances. * * Motivation for this class: * We have Object3D instances that exist simultaneously on opposite * sides of the network (at both the client and server ends). Initially, * we just let the objects get sent to the server via the base class * Object3D serialization function. At that time, subclasses of Object3D * did nothing more than init an Object3D in a particular way. This * worked fine when we didn't have animations associated with various * Object3D subclasses, but doesn't work now that we have animation * code in various subclasses. During serialization (if the object * is sent as a generic Object3D), the animation code is lost on * the client end. We need a way for the client to pick the correct * subclass to construct for deserialization. We can encode the * various subtypes by integers, and then this factory class can * be used to construct a class of appropriate subtype before * deserialization. * * @author Jason Rohrer */ class Object3DFactory { public: /** * Finds an integer subclass type flag for an object instance. * * @param inObject the object to determine a flag for. Must * be destroyed by the caller. * * @return a type flag for inObject. 0 (the defautl Object3D * baseclass flag) will be returned if subclass determination fails. */ static int object3DToInt( Object3D *inObject ); /** * Constructs a new, unitialized Object3D (in other words, * an Object3D ready for deserialization) of a subclass * type matching inTypeFlag. * * @param inTypeFlag the type flag specifying the class * of the returned object. * * @return an (unitialized) Object3D class instance with a * subclass type corresponding to inTypeFlag. If no * matching class is found, a default Object3D baseclass * instance is returned. Must be destroyed by the caller. */ static Object3D *intToObject3D( int inTypeFlag ); }; inline int Object3DFactory::object3DToInt( Object3D *inObject ) { // use RTTI to determine type of inObject #ifdef SUBREAL if( typeid( *inObject ) == typeid( EntityObject3D ) ) { return FACTORY_ENTITY_OBJECT_FLAG; } #endif // else return the default flag return FACTORY_DEFAULT_OBJECT_FLAG; } inline Object3D *Object3DFactory::intToObject3D( int inTypeFlag ) { switch( inTypeFlag ) { case FACTORY_DEFAULT_OBJECT_FLAG: return new Object3D(); break; /* these objects are only defined if * we are part of subreal */ #ifdef SUBREAL case FACTORY_ENTITY_OBJECT_FLAG: return new EntityObject3D(); break; #endif default: // unknown object flag type return new Object3D(); break; } } #endif primrose-6+dfsg1.orig/minorGems/graphics/3d/Object3D.h0000644000175000017500000001700607254677305021313 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. Copied from ObjectGL. * * 2001-January-10 Jason Rohrer * Made class serializable. Added a parameterless constructor * to facilitate deserialization. * * 2001-January-15 Jason Rohrer * Fixed several bugs in the deserialize() function, as well as in the * destructor. * * 2001-January-16 Jason Rohrer * Changed to use a Transform3D instead of Vectors, Angles, and scales for * each primitive in the object. * * 2001-January-24 Jason Rohrer * Added a copy() function. * Fixed a bug in deserialize(). * Made mMembersAllocated public for copy function. * * 2001-January-26 Jason Rohrer * Fixed a bug in copy(). * * 2001-January-31 Jason Rohrer * Fixed bugs in serialize() and deserialize(). * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. * * 2001-March-11 Jason Rohrer * Added support for paramatization and temporal animations. * * 2001-March-13 Jason Rohrer * Added interface for getting the number of parameters and animations. * * 2001-March-14 Jason Rohrer * Added use of Primitive3DFactory for typed subclass primitive * de/serialization. */ #ifndef OBJECT_3D_INCLUDED #define OBJECT_3D_INCLUDED #include "Primitive3D.h" #include "minorGems/math/geometry/Transform3D.h" #include "minorGems/io/Serializable.h" #include "Primitive3DFactory.h" /** * 3D object. * * Comprised of a collection of primitives. * * @author Jason Rohrer */ class Object3D : public Serializable { public: /** * Constructs an Object. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * object is destroyed. * * @param inNumPrimitives the number of primitives in this object. * @param inPrimitives the primitives comprising this object. * @param inTransform a transform for each object. */ Object3D( long inNumPrimitives, Primitive3D **inPrimitives, Transform3D **inTransform ); Object3D(); ~Object3D(); /** * Copies this object. * * @return a copy of this object, which must be destroyed * by the caller. */ Object3D *copy(); /** * Gets the number of parameters associated with this object. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this object. * * @return the number of animations. */ virtual int getNumAnimations(); /* * Note that the default implementations for all the parameter * and temporal animation functions do nothing. */ /** * Sets a parameter for this object. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this object. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this object forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this object. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this object. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); long mNumPrimitives; Primitive3D **mPrimitives; Transform3D **mTransform; // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); char mMembersAllocated; }; inline Object3D::Object3D( long inNumPrimitives, Primitive3D **inPrimitives, Transform3D **inTransform ) : mNumPrimitives( inNumPrimitives ), mPrimitives( inPrimitives ), mTransform( inTransform ), mMembersAllocated( true ) { } inline Object3D::Object3D() : mMembersAllocated( false ) { } inline Object3D::~Object3D() { if( mMembersAllocated ) { for( int i=0; imNumPrimitives = mNumPrimitives; objCopy->mPrimitives = new Primitive3D*[ mNumPrimitives ]; objCopy->mTransform = new Transform3D*[ mNumPrimitives ]; int i; for( i=0; imPrimitives[i] = mPrimitives[i]->copy(); objCopy->mTransform[i] = new Transform3D( mTransform[i] ); } objCopy->mMembersAllocated = true; return objCopy; } inline int Object3D::getNumParameters() { return 0; } inline int Object3D::getNumAnimations() { return 0; } // the base class versions of these functions do nothing inline void Object3D::setParameter( int inParameterIndex, double inValue ) { } inline double Object3D::getParameter( int inParameterIndex ) { return 0; } inline void Object3D::step( double inStepSize ) { } inline void Object3D::startAnimation( int inAnimationIndex ) { } inline void Object3D::stopAnimation( int inAnimationIndex ) { } inline int Object3D::serialize( OutputStream *inOutputStream ) { int i; int numBytes = 0; numBytes += inOutputStream->writeLong( mNumPrimitives ); // write each primitive for( i=0; iwriteLong( typeFlag ); // write the primitive numBytes += mPrimitives[i]->serialize( inOutputStream ); } // write each primitive's transform for( i=0; iserialize( inOutputStream ); } return numBytes; } inline int Object3D::deserialize( InputStream *inInputStream ) { if( mMembersAllocated ) { // first, delete current contents of object for( int i=0; ireadLong( &mNumPrimitives ); printf( "receiving %d primitives\n", mNumPrimitives ); mPrimitives = new Primitive3D*[mNumPrimitives]; for( i=0; ireadLong( &typeFlag ); // construct a new object based on the type flag mPrimitives[i] = Primitive3DFactory::intToPrimitive3D( typeFlag ); // deserialize it numBytes += mPrimitives[i]->deserialize( inInputStream ); } mTransform = new Transform3D*[mNumPrimitives]; for( i=0; ideserialize( inInputStream ); } mMembersAllocated = true; return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/graphics/3d/LathePrimitive3D.h0000644000175000017500000000650607252736762023037 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. Copied from LathePrimitiveGL, which this class will replace. * * 2001-January-19 Jason Rohrer * Changed to support multi-texturing internally, though this primitive * type doesn't use it. * * 2001-January-21 Jason Rohrer * Fixed a bug in the constructor. * * 2001-January-31 Jason Rohrer * Got rid of an unused variable. * * 2001-March-11 Jason Rohrer * Fixed a bug in the texture map anchor points. */ #ifndef LATHE_PRIMITIVE_3D_INCLUDED #define LATHE_PRIMITIVE_3D_INCLUDED #include "Primitive3D.h" /** * Primitive 3D lathe object. * * Made of a curve rotated around an axis. * * @author Jason Rohrer */ class LathePrimitive3D : public Primitive3D { public: /** * Constructs a LathePrimitive. The lathe curve is rotated * about the y axis. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * primitive is destroyed. * * @param inNumCurvePoints number of points in curve to be lathed. * @param inCurvePoints points to be lathed. All z components * are set to 0 before lathing, so only x and y values matter. * @param inNumLatheSteps the number of quad segments around * the circumference of the lathed object. For example, * setting to 4 (with a lathe angle of 2pi) * will produce an extruded square object. * @param inNetLatheAngle total angle to sweep during lathing, * in (0,2pi]. * @param inTexture the texture to map onto the lathed object. * Texture is anchored by its corners to the ends of the lath * curve at the beginning and end of the lathe sweep */ LathePrimitive3D( int inNumCurvePoints, Vector3D **inCurvePoints, int inNumLatheSteps, double inNetLatheAngle, RGBAImage *inTexture ); }; inline LathePrimitive3D::LathePrimitive3D( int inNumCurvePoints, Vector3D **inCurvePoints, int inNumLatheSteps, double inNetLatheAngle, RGBAImage *inTexture ) { // first, set Primitve3D members mHigh = inNumCurvePoints; mWide = inNumLatheSteps + 1; mNumVertices = mHigh * mWide; mNumTextures = 1; mTexture = new RGBAImage*[1]; mTexture[0] = inTexture; double stepAngle = inNetLatheAngle / inNumLatheSteps; int i; // first, set all z values for control points to 0 for( i=0; imZ = 0; } mVertices = new Vector3D*[mNumVertices]; mAnchorX = new double*[1]; mAnchorY = new double*[1]; mAnchorX[0] = new double[mNumVertices]; mAnchorY[0] = new double[mNumVertices]; // anchor at texture corners, and step linearly through texture double anchorYStep = 1.0 / ( mHigh - 1 ); double anchorXStep = 1.0 / ( mWide - 1 ); for( int y=0; yreverseRotate( latheRotation ); delete latheRotation; } // cleanup as we go along delete inCurvePoints[y]; } delete [] inCurvePoints; generateNormals(); } #endif primrose-6+dfsg1.orig/minorGems/graphics/loadFile.cpp0000644000175000017500000000335007205611501021435 0ustar pabspabs#include #include #include "loadFile.h" // loads any file into the dest ptr. void loadFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr) { FILE *f; int numBytesRead; f = fopen( fileName, "rb"); // open the file // don't load if file failed to open if( f == NULL ) { return; } numBytesRead = fread( (void*)byteDestPtr, sizeof(char), sizeInBytes, f); fclose(f); } // loads a photoshop RAW image file, 32-bit // NOTE: // This function exists because photoshop swaps the red and blue channels when // it saves a file as raw. Thus, the file stream doesn't match the way a video // card deals with 32-bit color. // This function loads the file and then swaps the appropriate bytes void loadRawFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr) { //unsigned char tempChannel; long byteCount; FILE *f; int numBytesRead; f = fopen( fileName, "rb"); // open the file // don't load if file failed to open if( f == NULL ) { return; } numBytesRead = fread( (void*)byteDestPtr, sizeof(char), sizeInBytes, f); // now that file read, swap the red and blue channels: for( byteCount = 0; byteCount< sizeInBytes; byteCount=byteCount+4) { unsigned char alpha = byteDestPtr[byteCount+3]; byteDestPtr[byteCount+3] = byteDestPtr[byteCount+2]; byteDestPtr[byteCount+2] = byteDestPtr[byteCount+1]; byteDestPtr[byteCount+1] = byteDestPtr[byteCount]; byteDestPtr[byteCount] = alpha; /* tempChannel = byteDestPtr[byteCount]; // currently in red position byteDestPtr[byteCount] = byteDestPtr[byteCount+3]; // currently set to what's in alpha position byteDestPtr[byteCount+2] = tempChannel; */ } fclose(f); }primrose-6+dfsg1.orig/minorGems/graphics/converters/0000755000175000017500000000000011201637526021411 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/converters/bmpformat.txt0000644000175000017500000000611307244265544024153 0ustar pabspabs Size Description Header 14 bytes Windows Structure: BITMAPFILEHEADER Signature 2 bytes 'BM' FileSize 4 bytes File size in bytes reserved 4 bytes unused (=0) DataOffset 4 bytes File offset to Raster Data InfoHeader 40 bytes Windows Structure: BITMAPINFOHEADER Size 4 bytes Size of InfoHeader =40 Width 4 bytes Bitmap Width Height 4 bytes Bitmap Height Planes 2 bytes Number of Planes (=1) BitCount 2 bytes Bits per Pixel 1 = monochrome palette. NumColors = 1 4 = 4bit palletized. NumColors = 16 8 = 8bit palletized. NumColors = 256 16 = 16bit RGB. NumColors = 65536 (?) 24 = 24bit RGB. NumColors = 16M Compression 4 bytes Type of Compression 0 = BI_RGB no compression 1 = BI_RLE8 8bit RLE encoding 2 = BI_RLE4 4bit RLE encoding ImageSize 4 bytes (compressed) Size of Image It is valid to set this =0 if Compression = 0 XpixelsPerM 4 bytes horizontal resolution: Pixels/meter YpixelsPerM 4 bytes vertical resolution: Pixels/meter ColorsUsed 4 bytes Number of actually used colors ColorsImportant 4 bytes Number of important colors 0 = all ColorTable 4 * NumColors bytes present only if Info.BitsPerPixel <= 8 colors should be ordered by importance Red 1 byte Red intensity Green 1 byte Green intensity Blue 1 byte Blue intensity reserved 1 byte unused (=0) repeated NumColors times Raster Data Info.ImageSize bytes The pixel data primrose-6+dfsg1.orig/minorGems/graphics/converters/compileTestPNG0000755000175000017500000000015310530642643024173 0ustar pabspabsg++ -g -Wall -o testPNG -I../../.. testPNG.cpp PNGImageConverter.cpp ../../io/file/linux/PathLinux.cpp -lz primrose-6+dfsg1.orig/minorGems/graphics/converters/LittleEndianImageConverter.h0000644000175000017500000000521207353214427026775 0ustar pabspabs/* * Modification History * * 2001-September-22 Jason Rohrer * Created. */ #ifndef LITTLE_ENDIAN_IMAGE_CONVERTER_INCLUDED #define LITTLE_ENDIAN_IMAGE_CONVERTER_INCLUDED #include "minorGems/graphics/ImageConverter.h" /** * A base class for converters that have little endian file formats. * Basically includes little endian reading and writing functions. * * @author Jason Rohrer */ class LittleEndianImageConverter : public ImageConverter { public: // does not implement the ImageConverter interface, // which makes this class abstract. protected: /** * Writes a long value in little endian format. * * @param inLong the long value to write. * @param inStream the stream to write inLong to. */ void writeLittleEndianLong( long inLong, OutputStream *inStream ); /** * Writes a short value in little endian format. * * @param inShort the short value to write. * @param inStream the stream to write inShort to. */ void writeLittleEndianShort( short inShort, OutputStream *inStream ); /** * Reads a long value in little endian format. * * @param inStream the stream to read the long value from. * * @return the long value. */ long readLittleEndianLong( InputStream *inStream ); /** * Reads a short value in little endian format. * * @param inStream the stream to read the short value from. * * @return the short value. */ short readLittleEndianShort( InputStream *inStream ); }; inline void LittleEndianImageConverter::writeLittleEndianLong( long inLong, OutputStream *inStream ) { unsigned char buffer[4]; buffer[0] = (unsigned char)( inLong & 0xFF ); buffer[1] = (unsigned char)( ( inLong >> 8 ) & 0xFF ); buffer[2] = (unsigned char)( ( inLong >> 16 ) & 0xFF ); buffer[3] = (unsigned char)( ( inLong >> 24 ) & 0xFF ); inStream->write( buffer, 4 ); } inline long LittleEndianImageConverter::readLittleEndianLong( InputStream *inStream ) { unsigned char buffer[4]; inStream->read( buffer, 4 ); long outLong = buffer[0] | ( buffer[1] << 8 ) | ( buffer[2] << 16 ) | ( buffer[3] << 24 ); return outLong; } inline void LittleEndianImageConverter::writeLittleEndianShort( short inShort, OutputStream *inStream ) { unsigned char buffer[2]; buffer[0] = (unsigned char)( inShort & 0xFF ); buffer[1] = (unsigned char)( ( inShort >> 8 ) & 0xFF ); inStream->write( buffer, 2 ); } inline short LittleEndianImageConverter::readLittleEndianShort( InputStream *inStream ) { unsigned char buffer[2]; inStream->read( buffer, 2 ); long outShort = buffer[0] | ( buffer[1] << 8 ); return outShort; } #endif primrose-6+dfsg1.orig/minorGems/graphics/converters/testPNG.cpp0000644000175000017500000000145310530642643023444 0ustar pabspabs#include "PNGImageConverter.h" #include "minorGems/graphics/Image.h" #include "minorGems/io/file/FileOutputStream.h" int main() { int imageSize = 120; Image testImage( imageSize, imageSize, 3 ); // red fades toward bottom // green fades toward right double *red = testImage.getChannel( 0 ); double *green = testImage.getChannel( 1 ); for( int y=0; y #include "minorGems/graphics/Image.h" #include "BMPImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileOutputStream.h" #include "minorGems/io/file/FileInputStream.h" // test function for the BMPImageConverter class int main( char inNumArgs, char**inArgs ) { if( inNumArgs != 2 ) { printf( "must pass in a file name to write to\n" ); return 1; } int length = 0; while( inArgs[1][length] != '\0' ) { length++; } File *file = new File( NULL, inArgs[1], length ); // read image in FileInputStream *stream = new FileInputStream( file ); BMPImageConverter *converter = new BMPImageConverter(); Image *image = converter->deformatImage( stream ); if( image != NULL ) { // write image back out File *fileOut = new File( NULL, "testOut.bmp", 11 ); FileOutputStream *outStream = new FileOutputStream( fileOut ); converter->formatImage( image, outStream ); delete outStream; delete image; } delete stream; delete file; delete converter; /* FileOutputStream *stream = new FileOutputStream( file ); BMPImageConverter *converter = new BMPImageConverter(); Image *image = new Image( 256, 256, 3 ); double *red = image->getChannel( 0 ); double *green = image->getChannel( 1 ); for( int y=0; ygetHeight(); y++ ) { for( int x=0; xgetWidth(); x++ ) { long index = y * image->getWidth() + x; red[index] = (double)y / (double)( image->getHeight() ); green[index] = (double)x / (double)( image->getWidth() ); //red[index] = 1.0; } } converter->formatImage( image, stream ); delete stream; // delete file explicitly delete file; delete converter; delete image; */ return 0; } primrose-6+dfsg1.orig/minorGems/graphics/converters/unix/0000755000175000017500000000000011201637526022374 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/converters/unix/JPEGImageConverterUnix.cpp0000644000175000017500000004047710543537355027347 0ustar pabspabs/* * Modification History * * 2001-April-27 Jason Rohrer * Created. * * 2001-April-29 Jason Rohrer * Finished implementation. * Added an optimization to formatImage, but it did not improve * performance, so it has been commented out. */ /** * Unix-specific JPEGImageConverter implementation * * Code for compression and decompression modeled after IJG's * libjpeg example code. * * For now, it use libjpeg to write converted data out to * file, and then reads it back in. */ #include "minorGems/graphics/converters/JPEGImageConverter.h" #include "minorGems/io/file/File.h" #include #include #include // include the jpeg library as a C file. // (yuk... spent way too much time trying to figure this one out!) extern "C" { #include } /* * is used for the decompression * error recovery mechanism. */ #include void JPEGImageConverter::formatImage( Image *inImage, OutputStream *inStream ) { if( inImage->getNumChannels() != 3 ) { printf( "JPEGImageConverter only works on 3-channel images.\n" ); return; } // most of this code was copied without modification from // IJG's example.c // This struct contains the JPEG compression parameters and pointers to // working space (which is allocated as needed by the JPEG library). // It is possible to have several such structures, representing multiple // compression/decompression processes, in existence at once. We refer // to any one struct (and its associated working data) as a "JPEG object". struct jpeg_compress_struct cinfo; // This struct represents a JPEG error handler. It is declared separately // because applications often want to supply a specialized error handler // (see the second half of this file for an example). But here we just // take the easy way out and use the standard error handler, which will // print a message on stderr and call exit() if compression fails. // Note that this struct must live as long as the main JPEG parameter // struct, to avoid dangling-pointer problems. struct jpeg_error_mgr jerr; // More stuff FILE * outfile; // target file JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] int row_stride; // physical row width in image buffer // Step 1: allocate and initialize JPEG compression object // We have to set up the error handler first, in case the initialization // step fails. (Unlikely, but it could happen if you are out of memory.) // This routine fills in the contents of struct jerr, and returns jerr's // address which we place into the link field in cinfo. cinfo.err = jpeg_std_error( &jerr ); // Now we can initialize the JPEG compression object. jpeg_create_compress( &cinfo ); // Step 2: specify data destination (eg, a file) // Note: steps 2 and 3 can be done in either order. // use a temp file with a random name to make this more // thread-safe char *fileName = new char[99]; sprintf( fileName, "temp%d.dat", rand() ); // Here we use the library-supplied code to send compressed data to a // stdio stream. You can also write your own code to do something else. // VERY IMPORTANT: use "b" option to fopen() if you are on a machine that // requires it in order to write binary files. if( ( outfile = fopen( fileName, "wb" ) ) == NULL ) { printf( "can't open jpeg conversion temp file %s\n", fileName ); return; } jpeg_stdio_dest( &cinfo, outfile ); // Step 3: set parameters for compression // First we supply a description of the input image. // Four fields of the cinfo struct must be filled in: // image width and height, in pixels cinfo.image_width = inImage->getWidth(); cinfo.image_height = inImage->getHeight(); cinfo.input_components = 3; // # of color components per pixel cinfo.in_color_space = JCS_RGB; // colorspace of input image // Now use the library's routine to set default compression parameters. // (You must set at least cinfo.in_color_space before calling this, // since the defaults depend on the source color space.) jpeg_set_defaults( &cinfo ); // Now you can set any non-default parameters you wish to. // Here we just illustrate the use of // quality (quantization table) scaling: jpeg_set_quality( &cinfo, mQuality, TRUE ); // limit to baseline-JPEG values // Step 4: Start compressor // TRUE ensures that we will write a complete interchange-JPEG file. // Pass TRUE unless you are very sure of what you're doing. jpeg_start_compress( &cinfo, TRUE ); // Step 5: while (scan lines remain to be written) // jpeg_write_scanlines(...); // Here we use the library's state variable cinfo.next_scanline as the // loop counter, so that we don't have to keep track ourselves. // To keep things simple, we pass one scanline per call; you can pass // more if you wish, though. // JSAMPLEs per row in image_buffer row_stride = cinfo.image_width * 3; // channels of inImage, which we will need to pull pixel values out of double *redChannel = inImage->getChannel(0); double *greenChannel = inImage->getChannel(1); double *blueChannel = inImage->getChannel(2); // array that we will copy inImage pixels into // one scanline at a time row_pointer[0] = new JSAMPLE[ row_stride ]; //int rowNumber = 0; while( cinfo.next_scanline < cinfo.image_height ) { // jpeg_write_scanlines expects an array of pointers to scanlines. // Here the array is only one element long, but you could pass // more than one scanline at a time if that's more convenient. // make a scanline int yOffset = cinfo.next_scanline * cinfo.image_width; // for each pixel in the row for( int p=0; pgetLength(); unsigned char *fileBuffer = new unsigned char[ fileLength ]; fread( fileBuffer, 1, fileLength, inFile ); // now write the entire buffer to our output stream inStream->write( fileBuffer, fileLength ); delete [] fileBuffer; delete file; fclose( inFile ); // delete this temporary file remove( fileName ); delete [] fileName; // And we're done! } // copied this directly from IJG's example.c //extern "C" { /* * ERROR HANDLING: * * The JPEG library's standard error handler (jerror.c) is divided into * several "methods" which you can override individually. This lets you * adjust the behavior without duplicating a lot of code, which you might * have to update with each future release. * * Our example here shows how to override the "error_exit" method so that * control is returned to the library's caller when a fatal error occurs, * rather than calling exit() as the standard error_exit method does. * * We use C's setjmp/longjmp facility to return * control. This means that the * routine which calls the JPEG library must * first execute a setjmp() call to * establish the return point. We want the replacement error_exit to do a * longjmp(). But we need to make the setjmp buffer accessible to the * error_exit routine. To do this, we make a private extension of the * standard JPEG error handler object. (If we were using C++, we'd say we * were making a subclass of the regular error handler.) * * Here's the extended error handler struct: */ struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct my_error_mgr * my_error_ptr; /* * Here's the routine that will replace the standard error_exit method: */ METHODDEF(void) my_error_exit( j_common_ptr cinfo ) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ my_error_ptr myerr = (my_error_ptr)( cinfo->err ); /* Always display the message. */ /* We could postpone this until after returning, if we chose. */ (*cinfo->err->output_message)( cinfo ); /* Return control to the setjmp point */ longjmp( myerr->setjmp_buffer, 1 ); } // } Image *JPEGImageConverter::deformatImage( InputStream *inStream ) { // use a temp file with a random name to make this more // thread-safe char *fileName = new char[99]; sprintf( fileName, "temp%d.dat", rand() ); FILE *tempFile = fopen( fileName, "wb" ); if( tempFile == NULL ) { printf( "can't open jpeg conversion temp file %s\n", fileName ); return NULL; } // buffer for dumping stream to temp file unsigned char *tempBuffer = new unsigned char[1]; unsigned char previousByte = 0; // dump the JPEG stream from the input stream into tempFile // so that we can pass this file to libjpeg /* // optimization: use a buffer to prevent too many fwrite calls int bufferLength = 5000; unsigned char *fileBuffer = new unsigned char[ bufferLength ]; int currentBufferPosition = 0; while( !( tempBuffer[0] == 0xD9 && previousByte == 0xFF ) ) { previousByte = tempBuffer[0]; inStream->read( tempBuffer, 1 ); fileBuffer[currentBufferPosition] = tempBuffer[0]; if( currentBufferPosition == bufferLength - 1 ) { // at the end of the file buffer fwrite( fileBuffer, 1, bufferLength, tempFile ); currentBufferPosition = 0; } else { // keep filling the fileBuffer currentBufferPosition++; } } // now write remaining fileBuffer data to file fwrite( fileBuffer, 1, currentBufferPosition + 1, tempFile ); delete [] fileBuffer; */ // write until EOI sequence seen (0xFFD9) while( !( tempBuffer[0] == 0xD9 && previousByte == 0xFF ) ) { previousByte = tempBuffer[0]; inStream->read( tempBuffer, 1 ); fwrite( tempBuffer, 1, 1, tempFile ); } // end of jpeg stream reached. fclose( tempFile ); delete [] tempBuffer; // the remainder of this method was mostly copied from // IJG's example.c /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; /* More stuff */ FILE * infile; /* source file */ JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ /* In this example we want to open the input * file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if( ( infile = fopen( fileName, "rb" ) ) == NULL ) { printf( "can't open jpeg conversion temp file %s\n", fileName ); return NULL; } /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if( setjmp( jerr.setjmp_buffer ) ) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, * close the input file, and return. */ jpeg_destroy_decompress( &cinfo ); fclose( infile ); printf( "error in decompressing jpeg from stream.\n" ); return NULL; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress( &cinfo ); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src( &cinfo, infile ); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header( &cinfo, TRUE ); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ (void) jpeg_start_decompress( &cinfo ); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ int imageWidth = cinfo.output_width; int imageHeight = cinfo.output_height; // the return image with 3 channels Image *returnImage = new Image( imageWidth, imageHeight, 3, false ); // channels of returnImage, // which we will need to put pixel values into of double *redChannel = returnImage->getChannel(0); double *greenChannel = returnImage->getChannel(1); double *blueChannel = returnImage->getChannel(2); int currentIndex = 0; row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that * will go away when done with image */ buffer = ( *cinfo.mem->alloc_sarray ) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1 ); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ int rowNumber = 0; double inv255 = 1.0 / 255.0; while( cinfo.output_scanline < cinfo.output_height ) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ (void) jpeg_read_scanlines( &cinfo, buffer, 1 ); // write the scanline into returnImage int yOffset = rowNumber * cinfo.output_width; // for each pixel in the row // copy it into the return image channels for( int p=0; p> 24 ) & 0xFF ); buffer[1] = (unsigned char)( ( inLong >> 16 ) & 0xFF ); buffer[2] = (unsigned char)( ( inLong >> 8 ) & 0xFF ); buffer[3] = (unsigned char)( inLong & 0xFF ); inStream->write( buffer, 4 ); } inline long BigEndianImageConverter::readBigEndianLong( InputStream *inStream ) { unsigned char buffer[4]; inStream->read( buffer, 4 ); long outLong = ( buffer[0] << 24 ) | ( buffer[1] << 16 ) | ( buffer[2] << 8 ) | buffer[3]; return outLong; } inline void BigEndianImageConverter::writeBigEndianShort( short inShort, OutputStream *inStream ) { unsigned char buffer[2]; buffer[0] = (unsigned char)( ( inShort >> 8 ) & 0xFF ); buffer[1] = (unsigned char)( inShort & 0xFF ); inStream->write( buffer, 2 ); } inline short BigEndianImageConverter::readBigEndianShort( InputStream *inStream ) { unsigned char buffer[2]; inStream->read( buffer, 2 ); long outShort = ( buffer[0] << 8 ) | buffer[1]; return outShort; } #endif primrose-6+dfsg1.orig/minorGems/graphics/converters/TGAImageConverter.h0000644000175000017500000002224711144105026025026 0ustar pabspabs/* * Modification History * * 2001-September-22 Jason Rohrer * Created. * * 2001-October-13 Jason Rohrer * Added support for 4-channel images. * * 2006-November-18 Jason Rohrer * Fixed two unused variable warnings. */ #ifndef TGA_IMAGE_CONVERTER_INCLUDED #define TGA_IMAGE_CONVERTER_INCLUDED #include "LittleEndianImageConverter.h" /** * TGA (Targa) implementation of the image conversion interface. * * Note that it only supports 24- and 32-bit TGA files * (and thus only 3- and 4-channel Images). * * TGA format information taken from: * http://www.cubic.org/source/archive/fileform/graphic/tga/targa.txt * * @author Jason Rohrer */ class TGAImageConverter : public LittleEndianImageConverter { public: // implement the ImageConverter interface virtual void formatImage( Image *inImage, OutputStream *inStream ); virtual Image *deformatImage( InputStream *inStream ); }; inline void TGAImageConverter::formatImage( Image *inImage, OutputStream *inStream ) { int numChannels = inImage->getNumChannels(); // make sure the image is in the right format if( numChannels != 3 && numChannels != 4 ) { printf( "Only 3- and 4-channel images can be converted to " ); printf( "the TGA format.\n" ); return; } long width = inImage->getWidth(); long height = inImage->getHeight(); long numPixels = width * height; // a buffer for writing single bytes unsigned char *byteBuffer = new unsigned char[1]; // write the identification field size // (an empty identification field) byteBuffer[0] = 0; inStream->write( byteBuffer, 1 ); // write the color map type // (no color map) byteBuffer[0] = 0; inStream->write( byteBuffer, 1 ); // write the image type code // (type 2: unmapped RGB image) byteBuffer[0] = 2; inStream->write( byteBuffer, 1 ); // no color map spec // (set to 0, though it will be ignored) unsigned char *colorMapSpec = new unsigned char[5]; int i; for( i=0; i<5; i++ ) { colorMapSpec[i] = 0; } inStream->write( colorMapSpec, 5 ); delete [] colorMapSpec; // now for the image specification // x origin coordinate writeLittleEndianShort( 0, inStream ); // y origin coordinate writeLittleEndianShort( 0, inStream ); writeLittleEndianShort( width, inStream ); writeLittleEndianShort( height, inStream ); // number of bits in pixels if( numChannels == 3 ) { byteBuffer[0] = 24; } else { byteBuffer[0] = 32; } inStream->write( byteBuffer, 1 ); // image descriptor byte if( numChannels == 3 ) { // setting to 0 specifies: // -- no attributes per pixel (for 24-bit) // -- screen origin in lower left corner // -- non-interleaved data storage byteBuffer[0] = 0; } else { // setting to 8 specifies: // -- 8 attributes per pixel (for 32-bit) (attributes are alpha bits) // -- screen origin in lower left corner // -- non-interleaved data storage byteBuffer[0] = 8; } // set bit 5 to 1 to specify screen origin in upper left corner byteBuffer[0] = byteBuffer[0] | ( 1 << 5 ); inStream->write( byteBuffer, 1 ); // We skip the image identification field, // since we set its length to 0 above. // We also skip the color map data, // since we have none (as specified above). // now we write the pixels, in BGR(A) order unsigned char *raster = new unsigned char[ numPixels * numChannels ]; double *red = inImage->getChannel( 0 ); double *green = inImage->getChannel( 1 ); double *blue = inImage->getChannel( 2 ); long rasterIndex = 0; if( numChannels == 3 ) { for( int i=0; iwrite( raster, numPixels * 3 ); } else { // numChannels == 4 double *alpha = inImage->getChannel( 3 ); for( int i=0; iwrite( raster, numPixels * numChannels ); delete [] raster; delete [] byteBuffer; } inline Image *TGAImageConverter::deformatImage( InputStream *inStream ) { // a buffer for reading single bytes unsigned char *byteBuffer = new unsigned char[1]; // read the identification field size inStream->read( byteBuffer, 1 ); int identificationFieldSize = byteBuffer[0]; // read the color map type // (only 0, or no color map, is supported) inStream->read( byteBuffer, 1 ); if( byteBuffer[0] != 0 ) { printf( "Only TGA files without colormaps can be read.\n" ); delete [] byteBuffer; return NULL; } // read the image type code // (only type 2, unmapped RGB image, is supported) inStream->read( byteBuffer, 1 ); if( byteBuffer[0] != 2 ) { printf( "Only TGA files containing unmapped RGB images can be read.\n" ); delete [] byteBuffer; return NULL; } // ignore color map spec // (skip all 5 bytes of it) unsigned char *colorMapSpec = new unsigned char[5]; inStream->read( colorMapSpec, 5 ); delete [] colorMapSpec; // now for the image specification // don't need either of these // don't set to a variable for now to avoid unused variable warnings // x origin coordinate readLittleEndianShort( inStream ); // y origin coordinate readLittleEndianShort( inStream ); long width = readLittleEndianShort( inStream ); long height = readLittleEndianShort( inStream ); long numPixels = width * height; // number of bits in pixels // only 24 bits per pixel supported inStream->read( byteBuffer, 1 ); if( byteBuffer[0] != 24 && byteBuffer[0] != 32 ) { printf( "Only 24- and 32-bit TGA files can be read.\n" ); delete [] byteBuffer; return NULL; } int numChannels = 0; if( byteBuffer[0] == 24 ) { numChannels = 3; } else { numChannels = 4; } // image descriptor byte // setting to 0 specifies: // -- no attributes per pixel (for 24-bit) // -- screen origin in lower left corner // -- non-interleaved data storage // set bit 5 to 1 to specify screen origin in upper left corner inStream->read( byteBuffer, 1 ); char originAtTop = byteBuffer[0] & ( 1 << 5 ); if( identificationFieldSize > 0 ) { // We skip the image identification field unsigned char *identificationField = new unsigned char[ identificationFieldSize ]; inStream->read( identificationField, identificationFieldSize ); delete [] identificationField; } // We also skip the color map data, // since we have none (as specified above). // now we read the pixels, in BGR(A) order unsigned char *raster = new unsigned char[ numPixels * numChannels ]; inStream->read( raster, numPixels * numChannels ); // optimization: don't init channels to black (found with profiler) Image *image = new Image( width, height, numChannels, false ); double *red = image->getChannel( 0 ); double *green = image->getChannel( 1 ); double *blue = image->getChannel( 2 ); long rasterIndex = 0; double inv255 = 1.0 / 255.0; if( numChannels == 3 ) { if( originAtTop ) { for( int i=0; i=0; y-- ) { for( int x=0; xgetChannel( 3 ); if( originAtTop ) { for( int i=0; i=0; y-- ) { int yOffset = y * width; for( int x=0; x 100 || mQuality < 0 ) { printf( "JPEG quality must be in [0,100]\n" ); mQuality = 50; } } inline void JPEGImageConverter::setQuality( int inQuality ) { mQuality = inQuality; if( mQuality > 100 || mQuality < 0 ) { printf( "JPEG quality must be in [0,100]\n" ); mQuality = 50; } } inline int JPEGImageConverter::getQuality() { return mQuality; } #endif primrose-6+dfsg1.orig/minorGems/graphics/converters/jpegConverterTestCompile0000755000175000017500000000020307272310031026310 0ustar pabspabsg++ -I../../.. -ljpeg -o jpegConverterTest jpegConverterTest.cpp unix/JPEGImageConverterUnix.cpp ../../io/file/linux/PathLinux.cpp primrose-6+dfsg1.orig/minorGems/graphics/converters/jpegConverterTest.cpp0000644000175000017500000000366307273016172025604 0ustar pabspabs/* * Modification History * * 2001-April-27 Jason Rohrer * Created. * * 2001-April-29 Jason Rohrer * Completed initial version and used to test JPEGImageConverter * successfully. */ #include #include "minorGems/graphics/Image.h" #include "JPEGImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileOutputStream.h" #include "minorGems/io/file/FileInputStream.h" // test function for the BMPImageConverter class int main( char inNumArgs, char**inArgs ) { if( inNumArgs != 2 ) { printf( "must pass in a file name to write to\n" ); return 1; } int length = 0; while( inArgs[1][length] != '\0' ) { length++; } File *file = new File( NULL, inArgs[1], length ); // read image in FileInputStream *stream = new FileInputStream( file ); JPEGImageConverter *converter = new JPEGImageConverter( 50 ); Image *image = converter->deformatImage( stream ); if( image != NULL ) { // write image back out File *fileOut = new File( NULL, "testOut.jpg", 11 ); FileOutputStream *outStream = new FileOutputStream( fileOut ); converter->formatImage( image, outStream ); delete outStream; delete fileOut; delete image; } delete stream; delete converter; delete file; /* FileOutputStream *stream = new FileOutputStream( file ); JPEGImageConverter *converter = new JPEGImageConverteonverter( 50 ); Image *image = new Image( 256, 256, 3 ); double *red = image->getChannel( 0 ); double *green = image->getChannel( 1 ); for( int y=0; ygetHeight(); y++ ) { for( int x=0; xgetWidth(); x++ ) { long index = y * image->getWidth() + x; red[index] = (double)y / (double)( image->getHeight() ); green[index] = (double)x / (double)( image->getWidth() ); //red[index] = 1.0; } } converter->formatImage( image, stream ); delete stream; // delete file explicitly delete file; delete converter; delete image; */ return 0; } primrose-6+dfsg1.orig/minorGems/graphics/converters/PNGImageConverter.cpp0000644000175000017500000002570210531130064025370 0ustar pabspabs/* * Modification History * * 2006-November-21 Jason Rohrer * Created. */ #include "PNGImageConverter.h" #include "minorGems/util/SimpleVector.h" //#include PNGImageConverter::PNGImageConverter() { // set up the CRC table // code taken from the PNG spec: // http://www.w3.org/TR/2003/REC-PNG-20031110/#D-CRCAppendix unsigned long c; int n, k; for( n=0; n<256; n++ ) { c = (unsigned long)n; for( k=0; k<8; k++ ) { if( c & 1 ) { c = 0xedb88320L ^ (c >> 1); } else { c = c >> 1; } } mCRCTable[n] = c; } } unsigned long PNGImageConverter::updateCRC( unsigned long inCRC, unsigned char *inData, int inLength ) { // code taken from the PNG spec: // http://www.w3.org/TR/2003/REC-PNG-20031110/#D-CRCAppendix unsigned long c = inCRC; int n; for( n=0; n> 8); } return c; } #define ADLER_BASE 65521 /* largest prime smaller than 65536 */ /** * Updates an adler32 checksum. * code found here http://www.ietf.org/rfc/rfc1950.txt * * New adlers should start with inAdler set to 1. * * @param inAdler the current state of the checksum. * @param inData the data to add. Destroyed by caller. * @param inLength the length of the data in bytes. * * @return the new checksum. */ unsigned long updateAdler32( unsigned long inAdler, unsigned char *inData, int inLength ) { unsigned long s1 = inAdler & 0xffff; unsigned long s2 = (inAdler >> 16) & 0xffff; int n; for (n = 0; n < inLength; n++) { s1 = (s1 + inData[n]) % ADLER_BASE; s2 = (s2 + s1) % ADLER_BASE; } return (s2 << 16) + s1; } void PNGImageConverter::writeChunk( char inChunkType[4], unsigned char *inData, unsigned long inNumBytes, OutputStream *inStream ) { // chunk layout: // 4-byte length // 4-char type // data // 4-byte CRC (applied to type and data parts) // write the length writeBigEndianLong( inNumBytes, inStream ); inStream->write( (unsigned char *)inChunkType, 4 ); // start the crc unsigned long crc = updateCRC( mStartCRC, (unsigned char *)inChunkType, 4 ); if( inData != NULL ) { // chunk has data inStream->write( inData, inNumBytes ); crc = updateCRC( crc, inData, inNumBytes ); } // final step: invert the CRC crc = crc ^ 0xffffffffL; // now write the CRC writeBigEndianLong( crc, inStream ); } void PNGImageConverter::formatImage( Image *inImage, OutputStream *inStream ) { int numChannels = inImage->getNumChannels(); // make sure the image is in the right format if( numChannels != 3 && numChannels != 4 ) { printf( "Only 3- and 4-channel images can be converted to " ); printf( "the PNG format.\n" ); return; } long width = inImage->getWidth(); long height = inImage->getHeight(); // same for all PNG images // used to check for basic transmission errors, such as line-end flipping unsigned char pngSignature[8] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; inStream->write( pngSignature, 8 ); // data for IHDR chunk unsigned char headerData[13]; // width headerData[0] = (width >> 24) & 0xff; headerData[1] = (width >> 16) & 0xff; headerData[2] = (width >> 8) & 0xff; headerData[3] = width & 0xff; // height headerData[4] = (height >> 24) & 0xff; headerData[5] = (height >> 16) & 0xff; headerData[6] = (height >> 8) & 0xff; headerData[7] = height & 0xff; // bit depth headerData[8] = 8; // color type // 2 = truecolor (RGB) headerData[9] = 2; // compression method // method 0 (deflate) headerData[10] = 0; // filter method // method 0 supports 5 filter types headerData[11] = 0; // no interlace headerData[12] = 0; writeChunk( "IHDR", headerData, 13, inStream ); int numRawBytes = width * height * 3; // extra byte per scanline for filter type numRawBytes += height; unsigned char *rawScanlineBytes = new unsigned char[ numRawBytes ]; // ignore alpha channel double *channels[3]; int i; for( i=0; i<3; i++ ) { channels[i] = inImage->getChannel( i ); } int pixelNumber = 0; for( int y=0; y zlibBlock; // compression method 8 (deflate) // with a LZ77 window size parameter of w=7 // LZ77 window size is then 2^( w + 8 ), or in this case 32768 zlibBlock.push_back( 0x78 ); // flags // compression level 0 (2 bytes = 00b) // no preset dictionary (1 byte = 0b) // check bits for compression method (5 bits) // Should be such that if the 8-bit compression method, followed // by the 8-bit flags field, is viewed as a 16-bit number, // it is an even multiple of 31 // For our settings, check bits of 00001 works //zlibBlock.push_back( 0x01 ); // hack: mimic zlib here zlibBlock.push_back( 0xda ); // now ready for compressed data blocks int rawDataIndex = 0; // length field is 16 bits int maxUncompressedBlockLength = 65535; while( rawDataIndex < numRawBytes ) { // push another deflate block // first bit BFINAL // only 1 for final block // next two bits BTYPE // BTYPE=00 is an uncompressed block // remaining 5 bits ignored // Thus, we put 0x00 for uncompressed blocks that are not final // and 0x80 for final uncompressed block int bytesLeft = numRawBytes - rawDataIndex; int bytesInBlock; if( bytesLeft <= maxUncompressedBlockLength ) { // final // hack: when comparing output with zlib, noticed that it doesn't // set 0x80 for the final block, instead it uses 0x01 // For some reason, this was making the PNG unreadable // zlibBlock.push_back( 0x80 ); zlibBlock.push_back( 0x01 ); bytesInBlock = bytesLeft; } else { // not final zlibBlock.push_back( 0x00 ); bytesInBlock = maxUncompressedBlockLength; } // length in least-significant-byte-first order unsigned char firstLengthByte = bytesInBlock & 0xff; unsigned char secondLengthByte = (bytesInBlock >> 8) & 0xff; zlibBlock.push_back( firstLengthByte ); zlibBlock.push_back( secondLengthByte ); // those same length bytes inverted // (called "one's compliment" in the spec zlibBlock.push_back( firstLengthByte ^ 0xff); zlibBlock.push_back( secondLengthByte ^ 0xff ); // now the uncompressed data for( int b=0; b< bytesInBlock; b++ ) { zlibBlock.push_back( rawScanlineBytes[ rawDataIndex ] ); rawDataIndex++; } } // finally, adler32 of original data unsigned long adler = updateAdler32( 1L, rawScanlineBytes, numRawBytes ); zlibBlock.push_back( (adler >> 24) & 0xff ); zlibBlock.push_back( (adler >> 16) & 0xff ); zlibBlock.push_back( (adler >> 8) & 0xff ); zlibBlock.push_back( adler & 0xff ); // the zlib block is now complete /* // check against real zlib implementation z_stream zStream; zStream.next_in = rawScanlineBytes; zStream.avail_in = numRawBytes; zStream.total_in = 0; int outSize = 2 * numRawBytes + 100; unsigned char *zlibOutBuffer = new unsigned char[ outSize ]; zStream.next_out = zlibOutBuffer; zStream.avail_out = outSize; zStream.total_out = 0; zStream.data_type = Z_BINARY; zStream.zalloc = Z_NULL; zStream.zfree = Z_NULL; // init the stream // no compression int result; //result = deflateInit( &zStream, Z_DEFAULT_COMPRESSION); result = deflateInit( &zStream, Z_NO_COMPRESSION); if( result != Z_OK ) { printf( "zlib deflateInit error: %s\n", zStream.msg ); } // deflate and flush result = deflate( &zStream, Z_FINISH ); if( result != Z_STREAM_END ) { printf( "zlib deflate error (%d): %s\n", result, zStream.msg ); } printf( "Total in = %d, total out = %d\n", zStream.total_in, zStream.total_out ); printf( "Our raw bytes (%d):\n", numRawBytes ); int b; for( b=0; b zlibBlock.size() ) { minBytes = zlibBlock.size(); } for( b=0; bgetNumChannels() != 3 ) { printf( "Only 3-channel images can be converted to the BMP format.\n" ); return; } long width = inImage->getWidth(); long height = inImage->getHeight(); long numPixels = width * height; // each line should be padded with zeros to // end on a 4-byte boundary int numZeroPaddingBytes = ( 4 - ( width * 3 ) % 4 ) % 4; short bitCount = 24; long rasterSize = numPixels * 3; // zero padding bytes for each row rasterSize += numZeroPaddingBytes * height; // offset past two headers long offsetToRaster = 14 + 40; long fileSize = offsetToRaster + rasterSize; long compressionType = 0; long pixelsPerMeter = 2834; // both are 0 since we have no color map long colorsUsed = 0; long colorsImportant = 0; // write the header unsigned char *signature = new unsigned char[2]; signature[0] = 'B'; signature[1] = 'M'; inStream->write( signature, 2 ); delete [] signature; writeLittleEndianLong( fileSize, inStream ); writeLittleEndianLong( 0, inStream ); writeLittleEndianLong( offsetToRaster, inStream ); // write the info header // header size writeLittleEndianLong( 40, inStream ); writeLittleEndianLong( width, inStream ); writeLittleEndianLong( height, inStream ); // numPlanes writeLittleEndianShort( 1, inStream ); writeLittleEndianShort( bitCount, inStream ); writeLittleEndianLong( compressionType, inStream ); writeLittleEndianLong( rasterSize, inStream ); writeLittleEndianLong( pixelsPerMeter, inStream ); writeLittleEndianLong( pixelsPerMeter, inStream ); writeLittleEndianLong( colorsUsed, inStream ); writeLittleEndianLong( colorsImportant, inStream ); // no color table... // now write the raster unsigned char *raster = new unsigned char[ rasterSize ]; double *red = inImage->getChannel( 0 ); double *green = inImage->getChannel( 1 ); double *blue = inImage->getChannel( 2 ); // pixels are stored bottom-up, left to right // (row major order) long rasterIndex = 0; for( int y=height-1; y>=0; y-- ) { for( int x=0; xwrite( raster, rasterSize ); delete [] raster; } inline Image *BMPImageConverter::deformatImage( InputStream *inStream ) { // temp buffer used to skip data in the stream unsigned char *temp = new unsigned char[ 100 ]; // skip signature inStream->read( temp, 2 ); long fileSize = readLittleEndianLong( inStream ); // skip unused inStream->read( temp, 4 ); long rasterOffset = readLittleEndianLong( inStream ); long rasterSize = fileSize - rasterOffset; // skip size of header inStream->read( temp, 4 ); long width = readLittleEndianLong( inStream ); long height = readLittleEndianLong( inStream ); // skip planes inStream->read( temp, 2 ); short bitCount = readLittleEndianShort( inStream ); char failing = false; if( bitCount != 24 ) { printf( "Only 24-bit BMP file formats supported.\n" ); failing = true; } long compression = readLittleEndianLong( inStream ); if( compression != 0 ) { printf( "Only uncompressed BMP file formats supported.\n" ); failing = true; } // skip imageSize, resolution, and color usage information inStream->read( temp, 20 ); // now we're at the raster. // each line should be padded with zeros to // end on a 4-byte boundary int numZeroPaddingBytes = ( 4 - ( width * 3 ) % 4 ) % 4; unsigned char *raster = new unsigned char[ rasterSize ]; inStream->read( raster, rasterSize ); Image *returnImage; if( failing ) { return NULL; } else { returnImage = new Image( width, height, 3 ); double *red = returnImage->getChannel( 0 ); double *green = returnImage->getChannel( 1 ); double *blue = returnImage->getChannel( 2 ); // pixels are stored bottom-up, left to right // (row major order) long rasterIndex = 0; for( int y=height-1; y>=0; y-- ) { for( int x=0; x #include class Color { public : /** * Constructs a color. * * @param red, green, blue the components of the color, each in [0,1]. * @param alpha the alpha value in [0,1]. Defaults to 1. * @param inBuildComposite set to true to build the composite * upon construction, or false to skip building composite (faster). * Defaults to false. */ Color(float red, float green, float blue, float alpha=1, char inBuildComposite=false ); /** * Constructs a all-zero (except alpha set to 1) color with no * composite built. */ Color(); /** * Constructs an rgb color from HSV components. * * @param inHue, inSaturation, inValue the HSV components of the * color, each in [0,1]. * @param alpha the alpha value in [0,1]. Defaults to 1. * @param inBuildComposite set to true to build the composite * upon construction, or false to skip building composite (faster). * Defaults to true. * * @return an RGBA color equivalent to the HSV color. * Must be destroyed by caller. */ static Color *makeColorFromHSV( float inHue, float inSaturation, float inValue, float inAlpha=1, char inBuildComposite=false ); float r, g, b, a; char mCompositeBuilt; unsigned long composite; // 32-bit composite color Color *copy(); // make a copy of this color /** * Sets the RGBA values of this color. * * @param red, green, blue, alpha the values to set. * Alpha defaults to 0. */ void setValues( float red, float green, float blue, float alpha=1 ); /** * Sets the RGBA values of this color using the values from * another color. * * @param inOtherColor the color to copy values from. * Must be destroyed by caller. */ void setValues( Color *inOtherColor ); /** * Tests whether this color is equal to another color. * * @param inOtherColor the other color. * Must be destroyed by caller. * * @return true if they are equal, or false otherwise. */ char equals( Color *inOtherColor ); void print(); /** * Computes the linear weighted sum of two colors. * * @param inFirst the first color. * @param inSecond the second color. * @param inFirstWeight the weight given to the first color in the * sum. The second color is weighted (1-inFirstWeight). * * @return the sum color. Must be destroyed by caller. */ static Color *linearSum( Color *inFirst, Color *inSecond, float inFirstWeight ); // after adjusting the r, g, b, a values exterally // call this to remake the composite unsigned long unsigned long rebuildComposite(); // get largest component of R,G,B float getMax(); // alter color data by multiplying by weight void weightColor( float weight ); /** * Alters color data by multiplying by a weight color. * * @param inWeightColor the color to multiply this color by. * Must be destroyed by caller. */ void weightColor( Color *inWeightColor ); /** * Inverts this color. * * Ignores alpha channel. */ void invert(); /** * Saturates this color, ensuring that at most 2 components are * non-zero. * * Ignores alpha channel. */ void saturate(); // get component by component weighted 32-bit composite // (returns alpha unweighted) unsigned long getWeightedComposite( float weight ); // from this color unsigned long getWeightedComposite(unsigned long c1, float weight ); // from composite unsigned long sumComposite(unsigned long c1, unsigned long c2); // access this color as a three vector float &operator[](int rgbIndex); }; inline Color::Color() { r = 0; g = 0; b = 0; a = 1; mCompositeBuilt = false; composite = 0; } inline Color::Color(float red, float green, float blue, float alpha, char inBuildComposite ) { r = red; g = green; b = blue; a = alpha; if( inBuildComposite ) { rebuildComposite(); } else { composite = 0; mCompositeBuilt = false; } } inline Color *Color::makeColorFromHSV( float inHue, float inSaturation, float inValue, float inAlpha, char inBuildComposite ) { // based on pseudocode from http://www.easyrgb.com/math.php float r, g, b; if ( inSaturation == 0 ) { r = inValue; g = inValue; b = inValue; } else { float var_h = inHue * 6; float var_i = int( var_h ); // Or var_i = floor( var_h ) float var_1 = inValue * ( 1 - inSaturation ); float var_2 = inValue * ( 1 - inSaturation * ( var_h - var_i ) ); float var_3 = inValue * ( 1 - inSaturation * ( 1 - ( var_h - var_i ) ) ); if( var_i == 0 ) { r = inValue; g = var_3; b = var_1; } else if( var_i == 1 ) { r = var_2; g = inValue; b = var_1; } else if( var_i == 2 ) { r = var_1; g = inValue; b = var_3; } else if( var_i == 3 ) { r = var_1; g = var_2; b = inValue; } else if( var_i == 4 ) { r = var_3; g = var_1; b = inValue; } else { r = inValue; g = var_1; b = var_2; } } return new Color( r, g, b, inAlpha, inBuildComposite ); } inline Color *Color::copy() { Color *copyColor = new Color(r,g,b,a, mCompositeBuilt ); return copyColor; } inline void Color::setValues( float red, float green, float blue, float alpha ) { r = red; g = green; b = blue; a = alpha; if( mCompositeBuilt ) { rebuildComposite(); } } inline void Color::setValues( Color *inOtherColor ) { setValues( inOtherColor->r, inOtherColor->g, inOtherColor->b, inOtherColor->a ); } inline char Color::equals( Color *inOtherColor ) { if( r == inOtherColor->r && g == inOtherColor->g && b == inOtherColor->b && a == inOtherColor->a ) { return true; } else { return false; } } inline void Color::print() { printf( "(%f, %f, %f, %f)", r, g, b, a ); } inline Color *Color::linearSum( Color *inFirst, Color *inSecond, float inFirstWeight ) { float secondWeight = 1 - inFirstWeight; float r = inFirstWeight * inFirst->r + secondWeight * inSecond->r; float g = inFirstWeight * inFirst->g + secondWeight * inSecond->g; float b = inFirstWeight * inFirst->b + secondWeight * inSecond->b; float a = inFirstWeight * inFirst->a + secondWeight * inSecond->a; return new Color( r, g, b, a, inFirst->mCompositeBuilt || inSecond->mCompositeBuilt ); } inline unsigned long Color::rebuildComposite() { composite = ((int)(b*255)) | ((int)(g*255)) << 8 | ((int)(r*255)) << 16 | ((int)(a*255)) << 24; mCompositeBuilt = true; return composite; } inline float Color::getMax() { float max = -FLT_MAX; if( r > max ) max = r; if( g > max ) max = g; if( b > max ) max = b; return max; } inline void Color::weightColor( float weight ) { r = r * weight; g = g * weight; b = b * weight; // for now, don't touch alpha if( mCompositeBuilt ) { rebuildComposite(); } } inline void Color::invert() { r = 1 - r; g = 1 - g; b = 1 - b; } inline void Color::saturate() { if( r < g && r < b ) { r = 0; } else if( g < r && g < b ) { g = 0; } else if( b < r && b < g ) { b = 0; } else if( r != 0 ) { // they are all equal, but non-zero // default to dropping red r = 0; } //else // they are all 0 // leave as black } inline void Color::weightColor( Color *inWeightColor ) { r *= inWeightColor->r; g *= inWeightColor->g; b *= inWeightColor->b; a *= inWeightColor->a; if( mCompositeBuilt ) { rebuildComposite(); } } inline float &Color::operator[](int rgbIndex) { if( rgbIndex == 0) return r; else if( rgbIndex == 1) return g; else if( rgbIndex == 2) return b; else if( rgbIndex == 3) return a; return r; // default, return r reference } inline unsigned long Color::getWeightedComposite( float weight ) { return ((int)(b*255*weight)) | ((int)(g*255*weight)) << 8 | ((int)(r*255*weight)) << 16 | ((int)(a*255)) << 24; } inline unsigned long Color::getWeightedComposite( unsigned long c1, float weight ) { int b = c1 & 0xFF; int g = (c1 >> 8) & 0xFF; int r = (c1 >> 16) & 0xFF; int a = c1 >> 24; return ((int)(b*weight)) | (((int)(g*weight)) << 8) | (((int)(r*weight)) << 16) | (((int)(a*weight)) << 24); } inline unsigned long Color::sumComposite(unsigned long c1, unsigned long c2) { int b = (c1 & 0xFF) + (c2 & 0xFF); if( b > 255) b = 255; int g = ((c1 >> 8) & 0xFF) + ((c2 >> 8) & 0xFF); if( g > 255) g = 255; int r = ((c1 >> 16) & 0xFF) + ((c2 >> 16) & 0xFF); if( r > 255) r = 255; int a = (c1 >> 24) + (c2 >> 24); if( a > 255) a = 255; return b | (g << 8) | (r << 16) | (a << 24); } #endif primrose-6+dfsg1.orig/minorGems/graphics/ImageConverter.h0000644000175000017500000000263310711714511022301 0ustar pabspabs/* * Modification History * * 2001-February-19 Jason Rohrer * Created. * * 2001-April-28 Jason Rohrer * Updated comments to deal with a failed deformatting operation. * * 2007-October-30 Jason Rohrer * Added virtual destructor. */ #ifndef IMAGE_CONVERTER_INCLUDED #define IMAGE_CONVERTER_INCLUDED #include "Image.h" #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" /** * Interface for a class that can convert Images to and from * various image formats. * * @author Jason Rohrer */ class ImageConverter { public: /** * Sends an image out to a stream as a particular * format. * * None of the parameters are destroyed by this call. * * @param inImage the image to convert. * @param inStream the stream to write the formatted image to. */ virtual void formatImage( Image *inImage, OutputStream *inStream ) = 0; /** * Reads an image in from a stream as a particular * format. * * None of the parameters are destroyed by this call. * * @param inStream the stream to read the formatted image. * * @return the deformatted image, or NULL if the deformatting * operation fails. Must be destroyed by caller. */ virtual Image *deformatImage( InputStream *inStream ) = 0; // to ensure proper destruction of implementing classes virtual ~ImageConverter() {}; }; #endif primrose-6+dfsg1.orig/minorGems/graphics/getMouse.h0000644000175000017500000000034207205611501021151 0ustar pabspabs// Jason Rohrer // getMouse.h /** * * general interface for getting current mouse position * Implemented by a graphix framework on a particular platform * * * Created 3-21-2000 * Mods: * */ void getMouse( int *x, int *y );primrose-6+dfsg1.orig/minorGems/graphics/keyCodes.h0000644000175000017500000000104407205611501021127 0ustar pabspabs// Jason Rohrer // keyCodes.h /** * * Header for defining key codes for various platforms * * * Created 12-15-99 * Mods: * Jason Rohrer 3-23-2000 Added more key codes * */ #ifdef WINDOWS_KEY_CODES #define M_KEY 0x4D #define N_KEY 0x4E #define S_KEY 0x53 #define Q_KEY 0x51 #define L_KEY 0x4C #define R_KEY 0x52 #define T_KEY 0x54 #endif #ifdef MAC_KEY_CODES #define M_KEY 0x2E #define N_KEY 0x2D #define S_KEY 0x01 #define Q_KEY 0x0C #define L_KEY 0x25 #define R_KEY 0x0F #define T_KEY 0x11 #endifprimrose-6+dfsg1.orig/minorGems/graphics/linux/0000755000175000017500000000000011201637526020356 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/linux/SDLTest.cpp0000644000175000017500000001173007274131037022347 0ustar pabspabs //#include #include "minorGems/graphics/ScreenGraphics.h" #include "minorGems/graphics/GraphicBuffer.h" #include "minorGems/graphics/Color.h" #include "minorGems/ui/Mouse.h" #include #include #include int numIcons = 200; int currentStep = 0; int numSteps = 1000; void catch_int(int sig_num) { printf( "Quiting..." ); currentStep = numSteps; signal( SIGINT, catch_int); } int main() { int i, j; // let catch_int handle interrupt (^c) signal( SIGINT, catch_int); ScreenGraphics *graphics = new ScreenGraphics( 640, 480 ); Mouse *mouse = new Mouse(2); unsigned long *pixelBuff = new unsigned long[ 640 * 480 ]; GraphicBuffer *buffer = new GraphicBuffer( pixelBuff, 640, 480 ); IconMap **maps = new IconMap*[numIcons]; IconMap *mouseMap; IconMap *mouseMap1 = new IconMap( 10, 10 ); Color mouseColor1( 1.0, 0.0, 0.0, 1.0 ); for( int y=0; y<10; y++ ) { for( int x=0; x<10; x++ ) { mouseMap1->imageMap[ mouseMap1->yOffset[y] + x ] = mouseColor1.composite; } } IconMap *mouseMap2 = new IconMap( 10, 10 ); Color mouseColor2( 0.0, 1.0, 0.0, 1.0 ); for( int y=0; y<10; y++ ) { for( int x=0; x<10; x++ ) { mouseMap2->imageMap[ mouseMap2->yOffset[y] + x ] = mouseColor2.composite; } } IconMap *mouseMap3 = new IconMap( 10, 10 ); Color mouseColor3( 0.0, 0.0, 1.0, 1.0 ); for( int y=0; y<10; y++ ) { for( int x=0; x<10; x++ ) { mouseMap3->imageMap[ mouseMap3->yOffset[y] + x ] = mouseColor3.composite; } } mouseMap = mouseMap1; Color c( 0.0f, 0.0f, 0.0f, 1.0f ); buffer->fill( c ); float *xPos = new float[numIcons]; float *yPos = new float[numIcons]; float *xDelta = new float[numIcons]; float *yDelta = new float[numIcons]; for( i=0; iimageMap[ maps[i]->yOffset[y] + x ] = randColor.composite; } } } int mouseX = 0; int mouseY = 0; char buttonDown1 = false; char buttonDown2 = false; for( currentStep=0; currentSteperaseIconMap( mouseMap, mouseX, mouseY, c ); mouse->getLocation( &mouseX, &mouseY ); buffer->drawIconMap( mouseMap, mouseX, mouseY ); if( !buttonDown1 && mouse->isButtonDown(0) ) { buttonDown1 = true; mouseMap = mouseMap2; } else if( buttonDown1 && !mouse->isButtonDown(0) ) { buttonDown1 = false; mouseMap = mouseMap1; } else if( !buttonDown2 && mouse->isButtonDown(1) ) { buttonDown2 = true; mouseMap = mouseMap3; } else if( buttonDown2 && !mouse->isButtonDown(1) ) { buttonDown2 = false; mouseMap = mouseMap1; } for( i=0; ieraseIconMap( maps[i], (int)( xPos[i] - 5 ), (int)( yPos[i] - 5 ), c ); if( xPos[i] > 640 || xPos[i] < 0 ) { xDelta[i] = -xDelta[i]; } xPos[i] += xDelta[i]; if( yPos[i] > 480 || yPos[i] < 0 ) { yDelta[i] = -yDelta[i]; } yPos[i] += yDelta[i]; buffer->drawIconMap( maps[i], (int)( xPos[i] - 5 ), (int)( yPos[i] - 5 ) ); } graphics->swapBuffers( buffer ); } /* for( int i=0; i<100; i++ ) { if( i%2 == 0 ) { Color c( 1.0f, 0.0f, 0.0f, 1.0f ); buffer->fill( c ); } else { Color c( 0.0f, 1.0f, 0.0f, 1.0f ); buffer->fill( c ); } graphics->swapBuffers( buffer ); } */ printf( "Done.\n" ); return 0; /* if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); exit(1); } //atexit( SDL_Quit ); SDL_Surface *screen = SDL_SetVideoMode( 640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF );//| SDL_FULLSCREEN ); if ( screen == NULL ) { printf( "Couldn't set 640x480x32 video mode: %s\n", SDL_GetError() ); exit(1); } for( int i=0; i< 100; i++ ) { if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) { printf( "Couldn't lock screen: %s\n", SDL_GetError()); exit(1); } } Uint32 value; if( i%2 == 0 ) { value = 0x0; } else { value = 0xFFFFFFFF; } Uint32 *buffer = (Uint32 *)( screen->pixels ); for ( int y=0; yh; y++ ) { for ( int x=0; xw; x++ ) { int r = ( ( ( x * 255 ) / screen->w ) + i ) % 255; int g = ( ( ( y * 255 ) / screen->h ) + i ) % 255; int b = 0; int a = 255; //buffer[ y * screen->w + x ] = (a << 24) | (r << 16) | (g << 8) | b; buffer[ y * screen->w + x ] = value; } } if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } //SDL_UpdateRect( screen, 0, 0, screen->w, screen->h ); SDL_Flip( screen ); } SDL_Quit(); SDL_Delay(2000); exit(0); */ } primrose-6+dfsg1.orig/minorGems/graphics/linux/ScreenGraphicsLinux.cpp0000644000175000017500000000660310447741000025001 0ustar pabspabs/* * Modification History * * 2000-November-18 Jason Rohrer * Created. * * 2000-November-19 Jason Rohrer * Change so that it doesn't use SDL's interrupt parachute, i.e., * so it will quit on ^c. * * 2001-May-1 Jason Rohrer * Changed to use more standard SDL include location. * * 2006-April-28 Jason Rohrer * Added functions for more direct access to screen pixels. * * 2006-June-26 Jason Rohrer * Added support for dirty rectangle. * Added resize support. */ #include "minorGems/graphics/ScreenGraphics.h" #include /** * Note: Linux implementation uses windowed mode. */ ScreenGraphics::ScreenGraphics( int inWidth, int inHeight ) : mWidth( inWidth ), mHeight( inHeight ) { if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); return; } SDL_Surface *screen = SDL_SetVideoMode( mWidth, mHeight, 32, SDL_SWSURFACE ); if ( screen == NULL ) { printf( "Couldn't set %dx%dx32 video mode: %s\n", mWidth, mHeight, SDL_GetError() ); return; } mNativeObjectPointer = (void*)screen; } ScreenGraphics::~ScreenGraphics() { SDL_Quit(); } void ScreenGraphics::resize( int inNewWidth, int inNewHeight ) { mWidth = inNewWidth; mHeight = inNewHeight; SDL_Surface *screen = SDL_SetVideoMode( mWidth, mHeight, 32, SDL_SWSURFACE ); if ( screen == NULL ) { printf( "Couldn't set %dx%dx32 video mode: %s\n", mWidth, mHeight, SDL_GetError() ); return; } mNativeObjectPointer = (void*)screen; } char ScreenGraphics::isResolutionAvailable( int inWidth, int inHeight ) { if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); return false; } // ask SDL if this screen size is supported char videoModeOk = (char)SDL_VideoModeOK( inWidth, inHeight, 32, SDL_SWSURFACE ); SDL_Quit(); return videoModeOk; } void ScreenGraphics::swapBuffers( GraphicBuffer *inOutBuffer ) { if( inOutBuffer->getHeight() != mHeight || inOutBuffer->getWidth() != mWidth ) { printf( "Buffer of incorrect size passed to screen.\n" ); return; } SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; // check if we need to lock the screen if( SDL_MUSTLOCK( screen ) ) { if( SDL_LockSurface( screen ) < 0 ) { printf( "Couldn't lock screen: %s\n", SDL_GetError() ); return; } } Uint32 *buffer = (Uint32 *)( screen->pixels ); memcpy( (void*)buffer, (void*)( inOutBuffer->getBuffer() ), mWidth * mHeight * 4 ); // unlock the screen if necessary if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } SDL_Flip( screen ); } GraphicBuffer *ScreenGraphics::getScreenBuffer() { SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; Uint32 *buffer = (Uint32 *)( screen->pixels ); return new GraphicBuffer( (unsigned long *)buffer, mWidth, mHeight ); } void ScreenGraphics::flipDirtyRectangle( int inTopLeftX, int inTopLeftY, int inWidth, int inHeight ) { SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; SDL_UpdateRect( screen, inTopLeftX, inTopLeftY, inWidth, inHeight ); } void ScreenGraphics::flipScreen() { SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; SDL_Flip( screen ); } primrose-6+dfsg1.orig/minorGems/graphics/linux/graphixCommonDefs.h0000644000175000017500000000013007205611501024130 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define LINUX_KEY_CODES primrose-6+dfsg1.orig/minorGems/graphics/Image.h0000644000175000017500000003775011070202762020420 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. * * 2001-January-6 Jason Rohrer * Fixed a bug in filter( ChannelFilter * ). * Set mSelection to NULL by default. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-January-15 Jason Rohrer * Made copy() not-virtual, so it can be overridden by subclasses * while allowing pointer type to determine which function * implementation is invoked. * * 2001-January-31 Jason Rohrer * Fixed a bug in copy(). * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. * * 2001-February-4 Jason Rohrer * Rewrote the serialization code to send the image across as a byte * array with one byte per channel. This will reduce the transfer size by * a factor of 8. Keeping images in double format is convennient for image * creation, but the added quality never affects the end user anyway, so * there's no point in sending the extra data to a stream. * Removed an unused array allocation. * * 2005-February-21 Jason Rohrer * Made destructor virtual to avoid compiler warnings. * * 2006-August-25 Jason Rohrer * Made zero init of pixels optional (for speed). * * 2008-September-25 Jason Rohrer * Added a sub-image function and setting/getting color functions. */ #ifndef IMAGE_INCLUDED #define IMAGE_INCLUDED #include #include #include "ChannelFilter.h" #include "Color.h" #include "minorGems/io/Serializable.h" /** * A multi-channel, double-valued image. * * Is Serializable. Note that a serialized image doesn't have a selection. * * @author Jason Rohrer */ class Image : public Serializable { public: /** * Constructs an image. * * @param inWidth width of image in pixels. * @param inHeight height of image in pixels. * @param inNumChannels number of channels in image. * @param inStartPixelsAtZero true to initialize all pixels * to zero, or false to leave default memory values (garbage) * in place (pixels must be initialized by caller in this case). * Defaults to true. */ Image( int inWidth, int inHeight, int inNumChannels, char inStartPixelsAtZero = true ); virtual ~Image(); // gets the dimensions of this image. virtual long getWidth(); virtual long getHeight(); virtual long getNumChannels(); /** * Gets the values of a particular channel. * * Values are not copied. * * @param inChannel the channel to get. * * @return the values of the specified channel in row-major order. */ virtual double *getChannel( int inChannel ); /** * Gets the 3- or 4-channel color value at a given location in the * image. * * @param inIndex the image index. * * @return a color object. */ virtual Color getColor( int inIndex ); /** * Sets the 3- or 4-channel color value at a given location in the * image. * * @param inIndex the image index. * @param inColor the new color to set. */ virtual void setColor( int inIndex, Color inColor ); /** * Selects a region of the image. Default is a clear selection, * which means all regions of image are affected by an applied * filter. * * @param inSelection the image to use as the selection mask. * Values of 0 indicate pixels that are not selection, and 1 * indicate pixels that are selected, with selection amount * varying linearly between 0 and 1. * If inSelection is a single channel, then that channel is * used as a selection mask for all channels in this image. * If inSelection contains the same number of channels as this * image, then the corresponding channels of inSelection are * are used to mask each channel of this image. * If inSelection contains a number of channels different * from the number in this image, the first channel of inSelection * is used to mask each channel in this image. * * Note that inSelection is not copied or destroyed by this class. * Thus, modifying inSelection after calling setSelection will * modify the selection in this image. */ virtual void setSelection( Image *inSelection ); /** * Gets the selection for this image. * * @return the selection for this image. Returns NULL * if there is no selection. Must not be destroyed * by caller before calling clearSelection. */ virtual Image *getSelection(); /** * Clears the selection. Effectively selects the entire image. */ virtual void clearSelection(); /** * Applies a filter to the selected region of * a specified channel of this image. * * @param inFilter the filter to apply. * @param inChannel the channel to filter. */ virtual void filter( ChannelFilter *inFilter, int inChannel ); /** * Applies a filter to the selected region of * all channels of this image. * * @param inFilter the filter to apply. */ virtual void filter( ChannelFilter *inFilter ); /** * Copies the selected region of this image. Not virtual, * so can be overridden by subclasses while allowing pointer * type to determine which function implementation is invoked. * * @return a new image with the same number of channels * as this image, each containing the selected region * from each corresponding channel of this image. Unselected * regions are set to black. Returned image has no selection. */ Image *copy(); /** * Pastes the selected region from another image into * the selected region of this image. * * @param inImage the image to paste. Let c be the number * of channels in this image, and cp be the number * of channels in the image being pasted. * If ccp, then only the first cp channels * of this image are pasted into. */ virtual void paste( Image *inImage ); /** * Copies the data from the selected region of a channel. * * @param inChannel the channel to copy. * * @return a copy of the channel data. Must be destroyed * by the caller. */ virtual double *copyChannel( int inChannel ); /** * Pastes channel data into the selected region of a specified channel. * * @param inChannelData an array containing the channel * data to be pasted. Must be destroyed by caller. * @param inChannel the channel to paste into. */ virtual void pasteChannel( double *inChannelData, int inChannel ); /** * Gets the mask for a specified channel. * * @param inChannel the channel to get a mask for. * * @return the mask data for the specified channel. * If selection has the same number of channels as this image * then a different mask is returned for each channel. Otherwise, * the first channel from the selection is returned as the * mask for every channel. Returns NULL if there is no selection. */ virtual double *getChannelSelection( int inChannel ); /** * Extracts a smaller sub-image from this image. * * Ignores current selection. * * @param inStartX, inStartY, inWidth, inHeight * coordinates for the top left corner pixel of the sub-image * and the width and height of the sub-image. * * @return the sub-image as a new image. Must be destoryed by caller. */ Image *getSubImage( int inStartX, int inStartY, int inWidth, int inHeight ); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); protected: long mWide, mHigh, mNumPixels, mNumChannels; double **mChannels; // NULL if nothing selected. Image *mSelection; /** * Pastes masked channel data into the selected region of a * specified channel. * * @param inChannelData an array containing the channel * data to be pasted. Must be destroyed by caller. * @param inMask the selection mask to use for passed-in channel. * Set to NULL for no mask. * @param inChannel the channel to paste into. */ virtual void pasteChannel( double *inChannelData, double *inMask, int inChannel ); }; inline Image::Image( int inWidth, int inHeight, int inNumChannels, char inStartPixelsAtZero ) : mWide( inWidth ), mHigh( inHeight ), mNumPixels( inWidth * inHeight ), mNumChannels( inNumChannels ), mChannels( new double*[inNumChannels] ), mSelection( NULL ) { // initialize all channels for( int i=0; iapply( mChannels[ inChannel ], mWide, mHigh ); } else { // part of image selected // turn selection off and filter channel entirely Image *tempSelection = mSelection; mSelection = NULL; // filter a copy of the channel double *filteredChannel = copyChannel( inChannel ); inFilter->apply( filteredChannel, mWide, mHigh ); // now paste filtered channel back into selected region mSelection = tempSelection; pasteChannel( filteredChannel, inChannel ); } } inline void Image::filter( ChannelFilter *inFilter ) { for( int i=0; ipaste( this ); return copiedImage; } inline void Image::paste( Image *inImage ) { // copy paste in the min number of channels only int numChannelsToPaste = mNumChannels; if( numChannelsToPaste > inImage->getNumChannels() ) { numChannelsToPaste = inImage->getNumChannels(); } for( int i=0; igetChannel(i), inImage->getChannelSelection(i), i ); } } inline double *Image::copyChannel( int inChannel ) { // first, copy the channel double *copiedChannel = new double[mNumPixels]; memcpy( copiedChannel, mChannels[inChannel], sizeof( double ) * mNumPixels ); if( mSelection != NULL ) { // apply selection to copied channel double *selection = getChannelSelection( inChannel ); // scale copied channel with selection for( int i=0; igetNumChannels() == mNumChannels ) { // use separate selection for each channel return mSelection->getChannel( inChannel ); } else { // use first channel of selection for all channels return mSelection->getChannel( 0 ); } } } inline void Image::pasteChannel( double *inChannelData, int inChannel ) { pasteChannel( inChannelData, NULL, inChannel ); } // We've abstracted away the complexity in the other fuctions, // but it all seemed to filter down into this function, which // is very messy. inline void Image::pasteChannel( double *inChannelData, double *inMask, int inChannel ) { double *thisChannel = mChannels[inChannel]; if( mSelection != NULL ) { // scale incoming data with this selection double *selection = getChannelSelection(inChannel); if( inMask != NULL ) { // scale incoming data with both masks for( int i=0; igetChannel( c ); double *sourceChannel = mChannels[c]; int destY=0; for( int y=inStartY; ywriteLong( mWide ); numBytes += inOutputStream->writeLong( mHigh ); // then output number of channels numBytes += inOutputStream->writeLong( mNumChannels ); // now output each channel for( int i=0; iwriteDouble( mChannels[i][p] ); byteArray[p] = (unsigned char)( mChannels[i][p] * 255 ); } numBytes += inOutputStream->write( byteArray, mNumPixels ); delete [] byteArray; } return numBytes; } inline int Image::deserialize( InputStream *inInputStream ) { int i; // first delete old image channels for( i=0; ireadLong( &mWide ); numBytes += inInputStream->readLong( &mHigh ); mNumPixels = mWide * mHigh; // then input number of channels numBytes += inInputStream->readLong( &mNumChannels ); mChannels = new double*[mNumChannels]; // now input each channel for( i=0; iread( byteArray, mNumPixels ); // convert each byte to an 8-bit double pixel for( int p=0; preadDouble( &( mChannels[i][p] ) ); mChannels[i][p] = (double)( byteArray[p] ) / 255.0; } delete [] byteArray; } return numBytes; } #endif primrose-6+dfsg1.orig/minorGems/graphics/ImageColorConverter.h0000644000175000017500000003377607353715726023335 0ustar pabspabs/* * Modification History * * 2001-February-26 Jason Rohrer * Created. * Added functions for converting to and from gray byte arrays. * * 2001-September-19 Jason Rohrer * Added an RGB->HSB conversion function, which was copied * from minorGems/ai/robotics/ImageStatistics. * Added RGB<->YIQ functions. * * 2001-September-20 Jason Rohrer * Fixed a bug in the YIQ conversion. * Got rid of this bug fix, as it distorts the YIQ space, * and there is no way to prevent colors from going out of the * [0,1] range all of the time anyway. * * 2001-September-24 Jason Rohrer * Added RGB<->YCbCr functions. * Abstracted out a common coefficient multiplying function. */ #ifndef IMAGE_COLOR_CONVERTER_INCLUDED #define IMAGE_COLOR_CONVERTER_INCLUDED #include "Image.h" /** * A container class for static functions that convert * images between various color spaces. * * @author Jason Rohrer */ class ImageColorConverter { public: /** * Converts a 3-channel RGB image to a 1-channel grayscale * image using an NTSC luminosity standard. * * @param inImage the RGB image to convert. Must be destroyed * by caller. * * @return a new, grayscale version of inImage. Must be * destroyed by the caller. Returns NULL if inImage * is not a 3-channel image. */ static Image *RGBToGrayscale( Image *inImage ); /** * Converts a 1-channel grayscae image to a 3-channel RGB * image. * * @param inImage the grayscale image to convert. Must be destroyed * by caller. * * @return a new, RGB version of inImage. Must be * destroyed by the caller. Returns NULL if inImage * is not a 1-channel image. */ static Image *grayscaleToRGB( Image *inImage ); /** * Converts a 1-channel grayscae image to a 1-channel byte array. * * @param inImage the grayscale image to convert. Must be destroyed * by caller. * @param inChannelNumber the channel number to use as the * gray channel. Defaults to 0; * * @return a new byte array with one byte per image pixel, * and image [0,1] values mapped to [0,255]. */ static unsigned char *grayscaleToByteArray( Image *inImage, int inChannelNumber = 0 ); /** * Converts a byte array to a 1-channel grayscale * image. * * @param inBytes the byte array to convert. Must be destroyed * by caller. * @param inWidth the width of the image contained in the byte array. * @param inHeight the height of the image contained in the byte array. * * @return a new, grayscale image version of the byte array. Must be * destroyed by the caller. */ static Image *byteArrayToGrayscale( unsigned char *inBytes, int inWidth, int inHeight ); /** * Converts an RGB image to HSB. * * @param inRGBImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the HSB conversion of the * RGB image. Must be destroyed by caller. */ static Image *RGBToHSB( Image *inRGBImage ); /** * Converts an RGB image to YIQ. * * Note that color values in the resulting YIQ * image may lie outside of the range [0,1]. * * @param inRGBImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the YIQ conversion of the * RGB image. Must be destroyed by caller. */ static Image *RGBToYIQ( Image *inRGBImage ); /** * Converts a YIQ image to RGB. * * * Note that color values in the resulting RGB * image may lie outside of the range [0,1]. * * @param inYIQImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the RGB conversion of the * YIQ image. Must be destroyed by caller. */ static Image *YIQToRGB( Image *inYIQImage ); /** * Converts an RGB image to YCbCr. * * Note that in the YCbCr standard, Y is in the range * [0,1], while Cb and Cr are both in the range [-0.5, 0.5]. * This function returns Cb and Cr components shifted * into the range [0,1]. * * @param inRGBImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the YCbCr conversion of the * RGB image. Must be destroyed by caller. */ static Image *RGBToYCbCr( Image *inRGBImage ); /** * Converts a YCbCr image to RGB. * * * Note that in the YCbCr standard, Y is in the range * [0,1], while Cb and Cr are both in the range [-0.5, 0.5]. * This function expects input Cb and Cr components to be shifted * into the range [0,1]. * * @param inYCbCrImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the RGB conversion of the * YCbCr image. Must be destroyed by caller. */ static Image *YCbCrToRGB( Image *inYCbCrImage ); protected: /** * Converts an 3-channel image to another 3-channel * image using a matrix of conversion coefficients. * * The following formulae are used; * outChan0 = inC00 * inChan0 + inC01 * inChan1 + inC02 * inChan2 * outChan1 = inC10 * inChan0 + inC11 * inChan1 + inC12 * inChan2 * outChan2 = inC20 * inChan0 + inC21 * inChan1 + inC22 * inChan2 * * @param inImage the image to convert. * Must be destroyed by caller. * * @return a new image that is inImage converted, or NULL if * conversion failed (usually because inImage does not * contain 3 channels). * Must be destroyed by caller. */ static Image *coefficientConvert( Image *inImage, double inC00, double inC01, double inC02, double inC10, double inC11, double inC12, double inC20, double inC21, double inC22 ); }; inline Image *ImageColorConverter::RGBToGrayscale( Image *inImage ) { int w = inImage->getWidth(); int h = inImage->getHeight(); int numPixels = w * h; Image *grayImage = new Image( w, h, 1 ); double *red = inImage->getChannel( 0 ); double *green = inImage->getChannel( 1 ); double *blue = inImage->getChannel( 2 ); double *gray = grayImage->getChannel( 0 ); for( int i=0; igetWidth(); int h = inImage->getHeight(); int numPixels = w * h; Image *rgbImage = new Image( w, h, 3 ); double *red = rgbImage->getChannel( 0 ); double *green = rgbImage->getChannel( 1 ); double *blue = rgbImage->getChannel( 2 ); double *gray = inImage->getChannel( 0 ); for( int i=0; igetWidth(); int h = inImage->getHeight(); int numPixels = w * h; unsigned char *bytes = new unsigned char[ numPixels ]; double *gray = inImage->getChannel( inChannelNumber ); for( int i=0; igetChannel( 0 ); for( int i=0; igetNumChannels() != 3 ) { printf( "RGBtoHSB requires a 3-channel image as input.\n" ); return NULL; } int w = inRGBImage->getWidth(); int h = inRGBImage->getHeight(); int numPixels = w * h; Image *hsbImage = new Image( w, h, 3 ); double *redChannel = inRGBImage->getChannel( 0 ); double *greenChannel = inRGBImage->getChannel( 1 ); double *blueChannel = inRGBImage->getChannel( 2 ); double *hueChannel = hsbImage->getChannel( 0 ); double *satChannel = hsbImage->getChannel( 1 ); double *brightChannel = hsbImage->getChannel( 2 ); for( int i=0; i g) ? r : g; if (b > cmax) { cmax = b; } int cmin = (r < g) ? r : g; if (b < cmin) { cmin = b; } bright = ( (double)cmax ) / 255.0; if( cmax != 0 ) { sat = ( (double)( cmax - cmin ) ) / ( (double) cmax ); } else { sat = 0; } if( sat == 0 ) { hue = 0; } else { double redc = ( (double)( cmax - r ) ) / ( (double)( cmax - cmin ) ); double greenc = ( (double) ( cmax - g ) ) / ( (double)( cmax - cmin ) ); double bluec = ( (double)( cmax - b ) ) / ( (double)( cmax - cmin ) ); if( r == cmax ) { hue = bluec - greenc; } else if( g == cmax ) { hue = 2.0 + redc - bluec; } else { hue = 4.0 + greenc - redc; } hue = hue / 6.0; if( hue < 0 ) { hue = hue + 1.0; } } hueChannel[i] = hue; satChannel[i] = sat; brightChannel[i] = bright; } return hsbImage; } inline Image *ImageColorConverter::RGBToYIQ( Image *inRGBImage ) { if( inRGBImage->getNumChannels() != 3 ) { printf( "RGBtoYIQ requires a 3-channel image as input.\n" ); return NULL; } Image *yiqImage = coefficientConvert( inRGBImage, 0.299, 0.587, 0.114, 0.596, -0.274, -0.322, 0.212, -0.523, 0.311 ); return yiqImage; } inline Image *ImageColorConverter::YIQToRGB( Image *inYIQImage ) { if( inYIQImage->getNumChannels() != 3 ) { printf( "YIQtoRGB requires a 3-channel image as input.\n" ); return NULL; } Image *rgbImage = coefficientConvert( inYIQImage, 1.0, 0.956, 0.621, 1.0, -0.272, -0.647, 1.0, -1.105, 1.702 ); return rgbImage; } inline Image *ImageColorConverter::RGBToYCbCr( Image *inRGBImage ) { if( inRGBImage->getNumChannels() != 3 ) { printf( "RGBtoYCbCr requires a 3-channel image as input.\n" ); return NULL; } // coefficients taken from the color space faq /* RGB -> YCbCr (with Rec 601-1 specs) Y = 0.2989 * Red + 0.5866 * Green + 0.1145 * Blue Cb = -0.1687 * Red - 0.3312 * Green + 0.5000 * Blue Cr = 0.5000 * Red - 0.4183 * Green - 0.0816 * Blue YCbCr (with Rec 601-1 specs) -> RGB Red = Y + 0.0000 * Cb + 1.4022 * Cr Green = Y - 0.3456 * Cb - 0.7145 * Cr Blue = Y + 1.7710 * Cb + 0.0000 * Cr */ Image *ycbcrImage = coefficientConvert( inRGBImage, 0.2989, 0.5866, 0.1145, -0.1687, -0.3312, 0.5000, 0.5000, -0.4183, -0.0816 ); // adjust the Cb and Cr channels so they are in the range [0,1] int numPixels = ycbcrImage->getWidth() * ycbcrImage->getHeight(); double *cbChannel = ycbcrImage->getChannel( 1 ); double *crChannel = ycbcrImage->getChannel( 2 ); for( int i=0; igetNumChannels() != 3 ) { printf( "YCbCrtoRGB requires a 3-channel image as input.\n" ); return NULL; } // adjust the normalized Cb and Cr channels // so they are in the range [-0.5,0.5] int numPixels = inYCbCrImage->getWidth() * inYCbCrImage->getHeight(); double *cbChannel = inYCbCrImage->getChannel( 1 ); double *crChannel = inYCbCrImage->getChannel( 2 ); for( int i=0; i YCbCr (with Rec 601-1 specs) Y = 0.2989 * Red + 0.5866 * Green + 0.1145 * Blue Cb = -0.1687 * Red - 0.3312 * Green + 0.5000 * Blue Cr = 0.5000 * Red - 0.4183 * Green - 0.0816 * Blue YCbCr (with Rec 601-1 specs) -> RGB Red = Y + 0.0000 * Cb + 1.4022 * Cr Green = Y - 0.3456 * Cb - 0.7145 * Cr Blue = Y + 1.7710 * Cb + 0.0000 * Cr */ Image *rgbImage = coefficientConvert( inYCbCrImage, 1.0, 0.0000, 1.4022, 1.0, -0.3456, -0.7145, 1.0, 1.7710, 0.0000 ); // clip r, g, and b channels to the range [0,1], since // some YCbCr pixel values might map out of this range // (in other words, some YCbCr values map outside of rgb space) for( int c=0; c<3; c++ ) { double *channel = rgbImage->getChannel( c ); for( int p=0; p 1 ) { channel[p] = 1.0; } } } return rgbImage; } inline Image *ImageColorConverter::coefficientConvert( Image *inImage, double inC00, double inC01, double inC02, double inC10, double inC11, double inC12, double inC20, double inC21, double inC22 ) { if( inImage->getNumChannels() != 3 ) { return NULL; } int w = inImage->getWidth(); int h = inImage->getHeight(); int numPixels = w * h; Image *outImage = new Image( w, h, 3 ); double *outChannel0 = outImage->getChannel( 0 ); double *outChannel1 = outImage->getChannel( 1 ); double *outChannel2 = outImage->getChannel( 2 ); double *inChannel0 = inImage->getChannel( 0 ); double *inChannel1 = inImage->getChannel( 1 ); double *inChannel2 = inImage->getChannel( 2 ); for( int i=0; iScreenGraphics. * Adjusts screen resolution and fills screen with black. * * @param inWidth width of desired full screen. * @param inHeight height of desired full screen. */ ScreenGraphics( int inWidth, int inHeight ); /** * Desctructor restores screen to original state. */ ~ScreenGraphics(); /** * Resizes the screen. * * @param inNewWidth the new width. * @param inNewHeight the new height. */ void resize( int inNewWidth, int inNewHeight ); /** * Gets the pixel buffer used by the screen. * * @return a graphics buffer containing a pointer to the screen * pixels. Must be destroyed by caller. */ GraphicBuffer *getScreenBuffer(); /** * Flips a dirty rectangle onto the screen. * * @param inTopLeftX the X coordinate, in pixels, of the top left * point on the rectangle. * @param inTopLeftY the Y coordinate, in pixels, of the top left * point on the rectangle. * @param inWidth the width of the rectangle. * @param inHeight the height of the rectangle. */ void flipDirtyRectangle( int inTopLeftX, int inTopLeftY, int inWidth, int inHeight ); /** * Flips all the pixels stored in the location pointed to by * getScreenBuffer() onto the screen. */ void flipScreen(); /** * Swaps a buffer to the screen. * The next buffer to be filled is returned in * inOutBuffer. * * No guarentee is made about what will be in the next buffer returned. * (On systems that support on-card double buffering, it may even * be a buffer pointing directly into video memory.) * * @param inOutBuffer pointer to the buffer to swap to the screen, * and pointer where the next buffer will be stored. */ void swapBuffers( GraphicBuffer *inOutBuffer ); /** * Determines whether a particular screen setting is available. * * NOTE: Do not call after constructing a ScreenGraphics instance. * * @param inWidth width of desired full screen. * @param inHeight height of desired full screen. * * @return true iff screen setting is available. */ static char isResolutionAvailable( int inWidth, int inHeight ); private: int mWidth; int mHeight; void *mNativeObjectPointer; }; #endif primrose-6+dfsg1.orig/minorGems/graphics/mac/0000755000175000017500000000000011201637526017757 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/mac/graphixCommonDefs.h0000644000175000017500000000012507205611502023536 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define MAC_KEY_CODESprimrose-6+dfsg1.orig/minorGems/graphics/mac/graphixFramework.cpp0000644000175000017500000001727507205611502024012 0ustar pabspabs/** 32 bit DrawSprockets pluggable framework * * Jason Rohrer, 4-28-99 * * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * Jason Rohrer 12-15-99 Added support for keyboard querying * Jason Rohrer 3-21-2000 Added support for mouse querying * */ #include #include #include // for keyboard events #include #include #include "swapBuffers.h" // interface for swapping buffers #include "getKey.h" // interface for getting key states #include "getMouse.h" // interface for getting mouse state //#include "ALifeGuiRunner.h" #include "GoGUIRunner.h" #include "GraphicBuffer.h" // Constants #define BallWidth 20 #define BallHeight 20 #define BobSize 8 /* Size of text in each ball */ //MT Tutorial #define rWindow 128 // resource ID number for window // Globals Rect windRect; WindowPtr w; DSpContextReference theContext; unsigned long *double_buffer = NULL; // the double buffer unsigned long *screen_buffer = NULL; GraphicBuffer *graphicDoubleBuffer; short bufferHigh = 480; short bufferWide = 640; // prototypes void Initialize(void); void graphixPicker(void); // our mother function, picks effect order, etc. void initVideo(DSpContextReference *theContext); void MyInitAttributes(DSpContextAttributes*); void CleanUp(DSpContextReference theContext); int main() { Initialize(); // setup a window MaxApplZone(); initVideo( &theContext ); // set up and switch video graphixPicker(); CleanUp( theContext); } void graphixPicker() { // our "mother function" // selects which effect to run next // graphix plug-in format: // myGraphix( bufferPtr, bufferHigh, bufferWide, colorBits, numFrames) // function can cll "swapBuffer32" internally whenever it needs the back buffer // sent to the screen. // jcrTorus( double_buffer, 480, 640, 32, 100); // jcrVoxels( double_buffer, 480, 640, 32, 230); // jcrTorus( double_buffer, 480, 640, 32, 50); //jcrBloom( double_buffer, 480, 640, 32, 100); // GraphicBuffer passed in contains all needed info about screen // pass in number of frames to run for //ALifeGuiRunner( *graphicDoubleBuffer, 1000 ); GoGUIRunner( *graphicDoubleBuffer, 0 ); } // Initialize the draw sprockets // set up the video, fade out display, and switch video modes void initVideo(DSpContextReference *theContext) { CGrafPtr backBuffer; PixMapHandle bufferMap; DSpContextAttributes theDesiredAttributes; OSStatus theError; MyInitAttributes(&theDesiredAttributes); theDesiredAttributes.displayWidth = 640; theDesiredAttributes.displayHeight = 480; theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; theDesiredAttributes.backBufferDepthMask = kDSpDepthMask_32; theDesiredAttributes.displayDepthMask = kDSpDepthMask_32; theDesiredAttributes.backBufferBestDepth = 32; theDesiredAttributes.displayBestDepth = 32; theError = DSpFindBestContext(&theDesiredAttributes, theContext); // add page flipping by video card to request theDesiredAttributes.contextOptions |= kDSpContextOption_PageFlip; //theDesiredAttributes.contextOptions |= kDSpContextOption_DontSyncVBL; // Reserver a display theError = DSpContext_Reserve(*theContext, &theDesiredAttributes); // fade out theError = DSpContext_FadeGammaOut(NULL, NULL); theError = DSpContext_SetState(*theContext, kDSpContextState_Active); ShowCursor(); HideCursor(); // setup global pointers to screen and back buffer theError = DSpContext_GetBackBuffer(*theContext, kDSpBufferKind_Normal, &backBuffer); bufferMap = (PixMapHandle)GetGWorldPixMap(backBuffer); double_buffer = (unsigned long*)(**bufferMap).baseAddr; // create GraphicBuffer object graphicDoubleBuffer = new GraphicBuffer( double_buffer, 640, 480 ); theError = DSpContext_GetFrontBuffer(*theContext, &backBuffer); bufferMap = (PixMapHandle)GetGWorldPixMap(backBuffer); screen_buffer = (unsigned long*)(**bufferMap).baseAddr; theError = DSpContext_FadeGammaIn(NULL, NULL); } // initialize a set of Display attributes to zero void MyInitAttributes (DSpContextAttributes *inAttributes) { if (NULL == inAttributes) DebugStr("\pStimpy! You Idiot!"); inAttributes->frequency = 0; inAttributes->displayWidth = 0; inAttributes->displayHeight = 0; inAttributes->reserved1 = 0; inAttributes->reserved2 = 0; inAttributes->colorNeeds = 0; inAttributes->colorTable = NULL; inAttributes->contextOptions = 0; inAttributes->backBufferDepthMask = 0; inAttributes->displayDepthMask = 0; inAttributes->backBufferBestDepth = 0; inAttributes->displayBestDepth = 0; inAttributes->pageCount = 0; inAttributes->gameMustConfirmSwitch = false; inAttributes->reserved3[0] = 0; inAttributes->reserved3[1] = 0; inAttributes->reserved3[2] = 0; inAttributes->reserved3[3] = 0; } void CleanUp(DSpContextReference theContext) { OSStatus theError; theError = DSpContext_FadeGammaOut(NULL, NULL); /* put the context into the inactive state */ theError = DSpContext_SetState(theContext, kDSpContextState_Inactive); /* fade back in */ theError = DSpContext_FadeGammaIn(NULL, NULL); /* release the context */ theError = DSpContext_Release(theContext); ShowCursor(); } // swap bufferB to the screen (32 bit version) void swapBuffers32( GraphicBuffer &bufferB ) { OSStatus theError; // swap buffers theError = DSpContext_SwapBuffers(theContext, NULL, 0); // get pointer to new back buffer and return it CGrafPtr backBuffer; PixMapHandle bufferMap; theError = DSpContext_GetBackBuffer(theContext, kDSpBufferKind_Normal, &backBuffer); bufferMap = (PixMapHandle)GetGWorldPixMap(backBuffer); // replace the buffer in bufferB with the new double buffer bufferB.setBuffer( (unsigned long*)(**bufferMap).baseAddr ); // memcpy(screen_buffer, bufferPtrB, 4*bufferWide*bufferHigh); } // end of swapBuffers // returns true if key represented by given key code is down char getKeyDown( int vKeyCode ) { unsigned char keyArray [16]; GetKeys( (long *)keyArray ); return ((keyArray[vKeyCode>>3] >> (vKeyCode & 7)) & 1); } // returns true if key is up char getKeyUp( int vKeyCode ) { unsigned char keyArray [16]; GetKeys( (long *)keyArray ); return !((keyArray[vKeyCode>>3] >> (vKeyCode & 7)) & 1); } void getMouse( int *x, int *y ) { Point mousePoint; DSpGetMouse( &mousePoint ); *x = mousePoint.h; *y = mousePoint.v; } void Initialize(void) { WindowPtr mainPtr; OSErr error; SysEnvRec theWorld; // // Test the computer to be sure we can do color. // If not we would crash, which would be bad. // If we cant run, just beep and exit. // error = SysEnvirons(1, &theWorld); if (theWorld.hasColorQD == false) { // SysBeep(50); ExitToShell(); // If no color QD, we must leave. } // Initialize all the needed managers. InitGraf(&qd.thePort); // InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); // // To make the Random sequences truly random, we need to make the seed start // at a different number. An easy way to do this is to put the current time // and date into the seed. Since it is always incrementing the starting seed // will always be different. Dont for each call of Random, or the sequence // will no longer be random. Only needed once, here in the init. // GetDateTime((unsigned long*) &qd.randSeed); // // Make a new window for drawing in, and it must be a color window. // The window is full screen size, made smaller to make it more visible. // mainPtr = GetNewCWindow(rWindow, nil, (WindowPtr) -1); // MW Tutorial windRect = mainPtr->portRect; SetPort(mainPtr); // set window to current graf port TextSize(BobSize); // smaller font for drawing. } primrose-6+dfsg1.orig/minorGems/graphics/win32/0000755000175000017500000000000011201637527020162 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/win32/graphixCommonDefs.h0000644000175000017500000000013107205611501023734 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define WINDOWS_KEY_CODESprimrose-6+dfsg1.orig/minorGems/graphics/win32/graphixFramework.cpp0000644000175000017500000002651507205611501024210 0ustar pabspabs// 32 bit DDraw pluggable framework // Jason Rohrer, 4-28-99 /** * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * Jason Rohrer 3-21-2000 Added support for mouse querying */ // based on the work of: /* * water ripples effect * -------------------- * anthony greene :: emit * april 1999 */ #define WIN32_LEAN_AND_MEAN // make sure certain headers are included correctly /* includes */ #include // include the standard windows stuff //#include // include the 32 bit stuff //#include // include the multi media stuff // need winmm.lib also #include // include direct draw components #include #include "swapBuffers.h" // interface for swapping buffers #include "getKey.h" // interface for handling keyboard input #include "getMouse.h" // interface for handling mouse input #include "GraphicBuffer.h" //#include "ALifeGuiRunner.h" #include "GoGUIRunner.h" /* defines */ #define WINDOW_CLASS_NAME "WINDOW_CLASS" // this is the name of the window class #define SCREEN_WIDTH 640 // the width of the viewing surface #define SCREEN_HEIGHT 480 // the height of the viewing surface #define SCREEN_BPP 32 // the bits per pixel #define MAX_COLORS 256 // the maximum number of colors /* types */ typedef unsigned char BYTE; typedef unsigned char UCHAR; typedef unsigned short WORD; /* macros */ // these query the keyboard in real-time #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) /* prototypes */ int DD_Init(HWND hwnd); int DD_Shutdown(void); void graphixPicker(void); // our mother function, picks effect order, etc. /* directdraw globals */ LPDIRECTDRAW lpdd = NULL; // dd object LPDIRECTDRAWSURFACE lpddsprimary = NULL; // dd primary surface LPDIRECTDRAWSURFACE lpddsback = NULL; // dd back surface LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette PALETTEENTRY color_palette[256]; // holds the shadow palette entries DDSURFACEDESC ddsd; // a direct draw surface description struct DDSCAPS ddscaps; // a direct draw surface capabilities struct HRESULT ddrval; // result back from dd calls HWND main_window_handle = NULL; // used to store the window handle unsigned long *double_buffer = NULL; // the double buffer unsigned long *screen_buffer = NULL; GraphicBuffer *graphicDoubleBuffer; /* globals */ int Height[2][640*480]; int old; int nu; int running = 0; int cycle; /* direct x functions */ int DD_Init(HWND hwnd) { // this function is responsible for initializing direct draw, // it creates a primary surface int index; // looping index // now that the windows portion is complete, start up direct draw if (DirectDrawCreate(NULL,&lpdd,NULL)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // now set the coop level to exclusive and set for full screen and mode x if (lpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // now set the display mode if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // Create the primary surface memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // end if // allocate memory for the double buffer if ((double_buffer = (unsigned long *)malloc(SCREEN_WIDTH*SCREEN_HEIGHT*4))==NULL) return(0); // create GraphicBuffer object graphicDoubleBuffer = new GraphicBuffer( double_buffer, 640, 480 ); // create the palette and attach it to the primary surface // clear all the palette entries to RGB 0,0,0 memset(color_palette,0,256*sizeof(PALETTEENTRY)); // set all of the flags to the correct value int c=0; for (index=0; index<256; index++) { // create the GRAY/RED/GREEN/BLUE palette, 64 shades of each if (index < 64) { color_palette[index].peRed = index; color_palette[index].peGreen = 0; color_palette[index].peBlue = 0; } else if (index < 128) { color_palette[index].peRed = index; color_palette[index].peGreen = 0; color_palette[index].peBlue = 0; } else if (index < 192) { color_palette[index].peRed = index; color_palette[index].peGreen = c; color_palette[index].peBlue = c; c++; } else if (index < 256) { color_palette[index].peRed = index; color_palette[index].peGreen = c; color_palette[index].peBlue = c; c++; } // set the no collapse flag color_palette[index].peFlags = PC_NOCOLLAPSE; } // now create the palette object, note that it is a member of the dd object itself if (lpdd->CreatePalette((DDPCAPS_8BIT | DDPCAPS_INITIALIZE),color_palette,&lpddpal,NULL)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // now attach the palette to the primary surface lpddsprimary->SetPalette(lpddpal); // return success if we got this far return(1); } int DD_Shutdown(void) { // this function tests for dd components that have been created // and releases them back to the operating system // test if the dd object exists if (lpdd) { // test if there is a primary surface if(lpddsprimary) { // release the memory and set pointer to NULL lpddsprimary->Release(); lpddsprimary = NULL; } // now release the dd object itself lpdd->Release(); lpdd = NULL; // free double buffer if (double_buffer!=NULL) free(double_buffer); // return success return(1); } else return(0); } /* windows callback fucntion */ LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // this is the main message handler of the system HDC hdc; // handle to graphics context PAINTSTRUCT ps; // used to hold the paint info // what is the message.. switch(msg) { case WM_CREATE: { // do windows inits here return(0); } break; case WM_PAINT: { // this message occurs when your window needs repainting hdc = BeginPaint(hwnd,&ps); EndPaint((struct HWND__ *)hdc,&ps); return(0); } break; case WM_DESTROY: { // this message is sent when your window is destroyed PostQuitMessage(0); return(0); } break; case WM_MOUSEMOVE: { // extract x,y /* int mouse_x = (int)LOWORD(lparam); int mouse_y = (int)HIWORD(lparam); Height[old][mouse_y*640+mouse_x] = 300; */ return(0); } break; default:break; } // let windows process any messages that we didn't take care of return (DefWindowProc(hwnd, msg, wparam, lparam)); } int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { WNDCLASSEX winclass; // this holds the windows class info HWND hwnd; // this holds the handle of our new window MSG msg; // this holds a generic message // first fill in the window class stucture winclass.cbSize = sizeof(WNDCLASSEX); winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winclass.lpfnWndProc = WindowProc; winclass.cbClsExtra = 0; winclass.cbWndExtra = 0; winclass.hInstance = hinstance; winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); winclass.hCursor = LoadCursor(NULL, IDC_ARROW); winclass.hbrBackground = (struct HBRUSH__ *)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName = NULL; winclass.lpszClassName = WINDOW_CLASS_NAME; // register the window class if (!RegisterClassEx(&winclass)) return(0); // create the window if (!(hwnd = CreateWindowEx(WS_EX_TOPMOST, WINDOW_CLASS_NAME, // class "water", // title WS_VISIBLE | WS_POPUP, 0,0, // x,y GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, // parent NULL, // menu hinstance, // instance NULL))) // creation parms return(0); // hide the mouse cursor ShowCursor(0); // save the window handle main_window_handle = hwnd; // initialize direct draw if (!DD_Init(hwnd)) { DestroyWindow(hwnd); return(0); } // peek at the message once just to make them happy PeekMessage(&msg,NULL,0,0,PM_REMOVE); // do it once, then leave graphixPicker(); // picks which effects to run. // afterwards, end!!! // shut down direct draw DD_Shutdown(); // return to Windows return(msg.wParam); } void graphixPicker() { // our "mother function" // selects which effect to run next // graphix plug-in format: // myGraphix( bufferPtr, bufferHigh, bufferWide, colorBits, numFrames) // function can cll "swapBuffer32" internally whenever it needs the back buffer // sent to the screen. // jcrTorus( double_buffer, 480, 640, 32, 100); // jcrVoxels( double_buffer, 480, 640, 32, 230); // jcrTorus( double_buffer, 480, 640, 32, 50); // jcrBloom( double_buffer, 480, 640, 32, 100); //ALifeGuiRunner( *graphicDoubleBuffer, 200 ); GoGUIRunner( *graphicDoubleBuffer, 0 ); } char getKeyDown( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? true : false); } char getKeyUp( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? false : true); } void getMouse( int *x, int *y ) { POINT p; GetCursorPos( &p ); *x = p.x; *y = p.y; } /// CODE FOR SWAPPING BUFFERES BELOW THIS POINT....... // swap bufferB to the screen (32 bit version) void swapBuffers32( GraphicBuffer &bufferB ) { unsigned long *primary_buffer = NULL, // used to draw *dest_ptr = NULL, // used in line by line copy *src_ptr = NULL; // " " short bufferHigh = 480; short bufferWide = 640; // copy the double buffer into the primary buffer memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // lock the primary surface lpddsprimary->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce primary_buffer = (unsigned long *)ddsd.lpSurface; // test if memory is linear if (ddsd.lPitch == 640*4) { // copy memory from double buffer to primary buffer memcpy(primary_buffer, double_buffer, 640*480*4); } else { // non-linear // make copy of source and destination addresses dest_ptr = primary_buffer; src_ptr = double_buffer; // memory is non-linear, copy line by line for (int y=0; yUnlock(primary_buffer); } // end of swapBuffers primrose-6+dfsg1.orig/minorGems/graphics/loadfile.h0000644000175000017500000000025307205611501021141 0ustar pabspabsvoid loadFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr); void loadRawFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr);primrose-6+dfsg1.orig/minorGems/graphics/test/0000755000175000017500000000000011201637527020177 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/graphics/test/tgaConverter.cpp0000644000175000017500000001002007353716210023337 0ustar pabspabs/* * Modification History * * 2001-September-24 Jason Rohrer * Created. */ #include "minorGems/graphics/Image.h" #include "minorGems/graphics/ImageColorConverter.h" #include "minorGems/graphics/converters/TGAImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" #include #include #include void usage( char *inAppName ); Image *loadTGAImage( char *inFileName ); void writeTGAImage( char *inFileName, Image *inImage ); // normalizes an image into the pixel range [0,1] if some // pixels are out of range void normalizeImage( Image *inImage ); // a test program that converts a tga image between // parameterizable color formats int main( char inNumArgs, char **inArgs ) { if( inNumArgs != 5 ) { usage( inArgs[0] ); } Image *inImage = loadTGAImage( inArgs[1] ); Image *outImage; // convert inImage to outImage based on the color space strings if( !strcmp( inArgs[3], "rgb" ) ) { if( !strcmp( inArgs[4], "yiq" ) ) { outImage = ImageColorConverter::RGBToYIQ( inImage ); } if( !strcmp( inArgs[4], "ycbcr" ) ) { outImage = ImageColorConverter::RGBToYCbCr( inImage ); } } if( !strcmp( inArgs[3], "yiq" ) ) { if( !strcmp( inArgs[4], "rgb" ) ) { outImage = ImageColorConverter::YIQToRGB( inImage ); } if( !strcmp( inArgs[4], "ycbcr" ) ) { Image *tempImage = ImageColorConverter::YIQToRGB( inImage ); outImage = ImageColorConverter::RGBToYCbCr( tempImage ); delete tempImage; } } if( !strcmp( inArgs[3], "ycbcr" ) ) { if( !strcmp( inArgs[4], "rgb" ) ) { outImage = ImageColorConverter::YCbCrToRGB( inImage ); } if( !strcmp( inArgs[4], "yiq" ) ) { Image *tempImage = ImageColorConverter::YCbCrToRGB( inImage ); outImage = ImageColorConverter::RGBToYIQ( tempImage ); delete tempImage; } } writeTGAImage( inArgs[2], outImage ); delete inImage; delete outImage; return 0; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( "\t%s in_image_tga out_image_tga in_format out_format\n", inAppName ); printf( "Example:\n" ); printf( "\t%s testRGB.tga testYIQ.bmp rgb yiq\n", inAppName ); printf( "The following color formats are supported:\n" ); printf( "\trgb, yiq, ycbcr\n" ); exit( 1 ); } void normalizeImage( Image *inImage ) { // now normalize the image so that pixels are in the range [0,1] int numPixels = inImage->getWidth() * inImage->getHeight(); int numChannels = inImage->getNumChannels(); double minValue = 1000.0; double maxValue = -1000.0; int c; // search for min and max values for( c=0; cgetChannel( c ); for( int p=0; p maxValue ) { maxValue = channel[p]; } } } double diff = maxValue - minValue; if( minValue >= 0 && diff + minValue <= 1 ) { // no need to normalize, as values are already // in range return; } double scale = 1.0 / diff; // now normalize all pixels for( c=0; cgetChannel( c ); for( int p=0; pdeformatImage( imageStream ); delete imageFile; delete imageStream; delete converter; return returnImage; } void writeTGAImage( char *inFileName, Image *inImage ) { File *imageFile = new File( NULL, inFileName, strlen( inFileName ) ); FileOutputStream *imageStream = new FileOutputStream( imageFile ); TGAImageConverter *converter = new TGAImageConverter(); converter->formatImage( inImage, imageStream ); delete imageFile; delete imageStream; delete converter; } primrose-6+dfsg1.orig/minorGems/graphics/test/yiq2rgb.cpp0000644000175000017500000000622207353474230022267 0ustar pabspabs/* * Modification History * * 2001-September-20 Jason Rohrer * Created. * Changed so that images are normalized to [0,1] before * being output. */ #include "minorGems/graphics/Image.h" #include "minorGems/graphics/ImageColorConverter.h" #include "minorGems/graphics/converters/BMPImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" #include #include void usage( char *inAppName ); Image *loadBMPImage( char *inFileName ); void writeBMPImage( char *inFileName, Image *inImage ); // normalizes an image into the pixel range [0,1] if some // pixels are out of range void normalizeImage( Image *inImage ); // a test program that converts an rgb BMP to a yiq BMP int main( char inNumArgs, char **inArgs ) { if( inNumArgs != 3 ) { usage( inArgs[0] ); } Image *yiqImage = loadBMPImage( inArgs[1] ); if( yiqImage == NULL ) { printf( "Reading image from file %s failed\n", inArgs[1] ); usage( inArgs[0] ); } Image *rgbImage = ImageColorConverter::YIQToRGB( yiqImage ); normalizeImage( rgbImage ); writeBMPImage( inArgs[2], rgbImage ); delete rgbImage; delete yiqImage; return 0; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( "\t%s yiq_image_bmp rgb_image_bmp\n", inAppName ); printf( "Example:\n" ); printf( "\t%s testYIQ.bmp testRGB.bmp\n", inAppName ); exit( 1 ); } void normalizeImage( Image *inImage ) { // now normalize the image so that pixels are in the range [0,1] int numPixels = inImage->getWidth() * inImage->getHeight(); int numChannels = inImage->getNumChannels(); double minValue = 1000.0; double maxValue = -1000.0; int c; // search for min and max values for( c=0; cgetChannel( c ); for( int p=0; p maxValue ) { maxValue = channel[p]; } } } double diff = maxValue - minValue; if( minValue >= 0 && diff + minValue <= 1 ) { // no need to normalize, as values are already // in range return; } double scale = 1.0 / diff; // now normalize all pixels for( c=0; cgetChannel( c ); for( int p=0; pdeformatImage( imageStream ); delete imageFile; delete imageStream; delete converter; return returnImage; } void writeBMPImage( char *inFileName, Image *inImage ) { File *imageFile = new File( NULL, inFileName, strlen( inFileName ) ); FileOutputStream *imageStream = new FileOutputStream( imageFile ); BMPImageConverter *converter = new BMPImageConverter(); converter->formatImage( inImage, imageStream ); delete imageFile; delete imageStream; delete converter; } primrose-6+dfsg1.orig/minorGems/graphics/test/rgb2yiq.cpp0000644000175000017500000000615707353474230022276 0ustar pabspabs/* * Modification History * * 2001-September-19 Jason Rohrer * Created. * * 2001-September-20 Jason Rohrer * Finished initial implementation. * Changed so that images are normalized to [0,1] before * being output. */ #include "minorGems/graphics/Image.h" #include "minorGems/graphics/ImageColorConverter.h" #include "minorGems/graphics/converters/BMPImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" #include #include void usage( char *inAppName ); Image *loadBMPImage( char *inFileName ); void writeBMPImage( char *inFileName, Image *inImage ); // normalizes an image into the pixel range [0,1] if some // pixels are out of range void normalizeImage( Image *inImage ); // a test program that converts an rgb BMP to a yiq BMP int main( char inNumArgs, char **inArgs ) { if( inNumArgs != 3 ) { usage( inArgs[0] ); } Image *rgbImage = loadBMPImage( inArgs[1] ); Image *yiqImage = ImageColorConverter::RGBToYIQ( rgbImage ); normalizeImage( yiqImage ); writeBMPImage( inArgs[2], yiqImage ); delete rgbImage; delete yiqImage; return 0; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( "\t%s rgb_image_bmp yiq_image_bmp\n", inAppName ); printf( "Example:\n" ); printf( "\t%s testRGB.bmp testYIQ.bmp\n", inAppName ); exit( 1 ); } void normalizeImage( Image *inImage ) { // now normalize the image so that pixels are in the range [0,1] int numPixels = inImage->getWidth() * inImage->getHeight(); int numChannels = inImage->getNumChannels(); double minValue = 1000.0; double maxValue = -1000.0; int c; // search for min and max values for( c=0; cgetChannel( c ); for( int p=0; p maxValue ) { maxValue = channel[p]; } } } double diff = maxValue - minValue; if( minValue >= 0 && diff + minValue <= 1 ) { // no need to normalize, as values are already // in range return; } double scale = 1.0 / diff; // now normalize all pixels for( c=0; cgetChannel( c ); for( int p=0; pdeformatImage( imageStream ); delete imageFile; delete imageStream; delete converter; return returnImage; } void writeBMPImage( char *inFileName, Image *inImage ) { File *imageFile = new File( NULL, inFileName, strlen( inFileName ) ); FileOutputStream *imageStream = new FileOutputStream( imageFile ); BMPImageConverter *converter = new BMPImageConverter(); converter->formatImage( inImage, imageStream ); delete imageFile; delete imageStream; delete converter; } primrose-6+dfsg1.orig/minorGems/graphics/test/tgaConverterCompile0000755000175000017500000000014107353716210024075 0ustar pabspabsg++ -g -o tgaConverter -I../../.. tgaConverter.cpp ../../../minorGems/io/file/linux/PathLinux.cppprimrose-6+dfsg1.orig/minorGems/graphics/test/rgb2yiqCompile0000755000175000017500000000012407352467255023025 0ustar pabspabsg++ -o rgb2yiq -I../../.. rgb2yiq.cpp ../../../minorGems/io/file/linux/PathLinux.cppprimrose-6+dfsg1.orig/minorGems/graphics/test/yiq2rgbCompile0000755000175000017500000000012707352505010023006 0ustar pabspabsg++ -g -o yiq2rgb -I../../.. yiq2rgb.cpp ../../../minorGems/io/file/linux/PathLinux.cppprimrose-6+dfsg1.orig/minorGems/numtest.cpp0000644000175000017500000000135507237350067017634 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * * 2001-February-4 Jason Rohrer * Fixed a bug that made this test not compatible with TypeIO. * Fixed comment. */ #include // function for testing how doubles are stored /* * The output from a big-endian linux is as follows: * * size of double = 8 * byte 0 = 63 * byte 1 = 255 * byte 2 = 189 * byte 3 = 137 * byte 4 = 176 * byte 5 = 126 * byte 6 = 158 * byte 7 = 168 * */ int main() { printf( "size of double = %d\n", sizeof( double ) ); double x = 1.983773889; unsigned char *doubleBuffer = (unsigned char*)( &x ); for( int i=0; i<8; i++ ) { printf( "byte %d = %d\n", i, doubleBuffer[i] ); } return 0; } primrose-6+dfsg1.orig/minorGems/system/0000755000175000017500000000000011201637537016745 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/system/semaphoreTest.cpp0000644000175000017500000000366407234645702022311 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Made printing in threads thread-safe. */ #include "BinarySemaphore.h" #include "Semaphore.h" #include "Thread.h" #include "ThreadSafePrinter.h" #include /** * Thread that waits on a semaphore. * * @author Jason Rohrer */ class WaitingThread : public Thread { public: WaitingThread( int inID, Semaphore *inSemaphore ); // override the run method from PThread void run(); private: Semaphore *mSemaphore; int mID; }; inline WaitingThread::WaitingThread( int inID, Semaphore *inSemaphore ) : mID( inID ), mSemaphore( inSemaphore ) { } inline void WaitingThread::run() { for( int i=0; i<10; i++ ) { ThreadSafePrinter::printf( "%d waiting for signal %d...\n", mID, i ); mSemaphore->wait(); ThreadSafePrinter::printf( "%d received signal %d.\n", mID, i ); } } /** * Thread that signals on a semaphore. * * @author Jason Rohrer */ class SignalingThread : public Thread { public: SignalingThread( Semaphore *inSemaphore ); // override the run method from PThread void run(); private: Semaphore *mSemaphore; }; inline SignalingThread::SignalingThread( Semaphore *inSemaphore ) : mSemaphore( inSemaphore ) { } inline void SignalingThread::run() { for( int i=0; i<5; i++ ) { sleep( 5000 ); ThreadSafePrinter::printf( "Signaling 20 times\n" ); for( int j=0; j<20; j++ ) { mSemaphore->signal(); } } } int main() { int i; Semaphore *semph = new Semaphore(); SignalingThread *threadS = new SignalingThread( semph ); WaitingThread **threadW = new WaitingThread*[10]; for( i=0; i<10; i++ ) { threadW[i] = new WaitingThread( i, semph ); threadW[i]->start(); } threadS->start(); for( i=0; i<10; i++ ) { threadW[i]->join(); delete threadW[i]; } threadS->join(); delete semph; delete threadS; delete [] threadW; return 0; } primrose-6+dfsg1.orig/minorGems/system/unix/0000755000175000017500000000000011201637537017730 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/system/unix/LauncherUnix.cpp0000644000175000017500000000077307607633527023062 0ustar pabspabs/* * Modification History * * 2003-January-10 Jason Rohrer * Created. */ #include "minorGems/system/Launcher.h" #include #include void Launcher::launchCommand( char *inCommandName, char **inArguments ) { int forkValue = fork(); if( forkValue == 0 ) { // we're in child process, so exec command execvp( inCommandName, inArguments ); // we'll never return from this call } } primrose-6+dfsg1.orig/minorGems/system/unix/TimeUnix.cpp0000644000175000017500000000123407447774050022207 0ustar pabspabs/* * Modification History * * 2001-October-29 Jason Rohrer * Created. * * 2002-March-13 Jason Rohrer * Added include of time.h so that FreeBSD compile will work. * Changed to use newer gettimeofday that should work on all unix platforms. * Fixed a conversion bug. */ #include "minorGems/system/Time.h" #include #include #include #include void Time::getCurrentTime( unsigned long *outSeconds, unsigned long *outMilliseconds ) { struct timeval currentTime; gettimeofday( ¤tTime, NULL ); *outMilliseconds = currentTime.tv_usec / 1000; *outSeconds = currentTime.tv_sec; } primrose-6+dfsg1.orig/minorGems/system/endian.h0000644000175000017500000000317111165410607020352 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * * 2004-January-12 Jason Rohrer * Added support for metrowerks win32 compiler. * * 2009-April-3 Jason Rohrer * OpenBSD support. */ #include "minorGems/common.h" /** * Include this file to define __BYTE_ORDER * * After this has been included, __BYTE_ORDER will be either * __LITTLE_ENDIAN or * __BIG_ENDIAN */ #ifdef __FreeBSD__ #include #elif defined(__NetBSD__) #include #elif defined(__OpenBSD__) #include #include // default BSD case #elif defined(BSD) #include #elif defined(SOLARIS) // Code for Solaris defs adapted from: // MD5 message-digest algorithm. // by Colin Plumb in 1993, no copyright is claimed. //each solaris is different -- this won't work on 2.6 or 2.7 # include #define __LITTLE_ENDIAN 1234 #define __BIG_ENDIAN 4321 #ifdef _LITTLE_ENDIAN #define __BYTE_ORDER __LITTLE_ENDIAN #else // default to big endian #define __BYTE_ORDER __BIG_ENDIAN #endif // end solaris case #elif defined(WIN_32) || \ ( defined(__MWERKS__) && defined(__INTEL__) ) // windows case #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __LITTLE_ENDIAN // end windows case #else // linux case #include // end linux case #endif // end of all system-specific cases // BSD calls it BYTE_ORDER, linux calls it __BYTE_ORDER #ifndef __BYTE_ORDER #define __BYTE_ORDER BYTE_ORDER #endif #ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #ifndef __BIG_ENDIAN #define __BIG_ENDIAN BIG_ENDIAN #endif primrose-6+dfsg1.orig/minorGems/system/BinarySemaphore.h0000644000175000017500000000331307722702203022202 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Fixed a bug in the precompiler directives. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. */ #include "minorGems/common.h" #ifndef BINARY_SEMAPHORE_CLASS_INCLUDED #define BINARY_SEMAPHORE_CLASS_INCLUDED #include "MutexLock.h" /** * Binary semaphore class. Semaphore starts out with a value of 0. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class BinarySemaphore { public: /** * Constructs a binary semaphore. */ BinarySemaphore(); ~BinarySemaphore(); /** * Blocks on this semaphore until signal() is called by another thread. * Note that if signal() has already been called before wait() is * called, then this call will return immediately, though the semaphore * is reset to 0 by this call. * * @param inTimeoutInMilliseconds the maximum time to wait in * milliseconds, or -1 to wait forever. Defaults to -1. * * @return 1 if the semaphore was signaled, or 0 if it timed out. */ int wait( int inTimeoutInMilliseconds = -1 ); /** * Signals the semaphore, allowing a waiting thread to return from * its call to wait(). (The semaphore is set to 1 by this call if * no thread is waiting on the semaphore currently.) */ void signal(); private: // starts at 0 int mSemaphoreValue; /** * Used by platform-specific implementations. */ void *mNativeObjectPointerA; void *mNativeObjectPointerB; }; #endif primrose-6+dfsg1.orig/minorGems/system/Launcher.h0000644000175000017500000000163007607633465020672 0ustar pabspabs/* * Modification History * * 2003-January-10 Jason Rohrer * Created. */ #include "minorGems/common.h" #ifndef LAUNCHER_INCLUDED #define LAUNCHER_INCLUDED /** * Interface for launching processes. * * @author Jason Rohrer */ class Launcher { public: /** * Launches a command in a new process. * * @param inCommandName the name of the command to launch. * Must be destroyed by caller if non-const. * @param inArguments an array of argument strings for the command. * This array must be terminated by a NULL pointer. * Note that by convention, the first argument should be the * command name. * Must be destroyed by caller. */ static void launchCommand( char *inCommandName, char **inArguments ); }; #endif primrose-6+dfsg1.orig/minorGems/system/Time.h0000644000175000017500000000444310202731646020015 0ustar pabspabs/* * Modification History * * 2001-October-29 Jason Rohrer * Created. * * 2004-October-14 Jason Rohrer * Fixed sign bug. * * 2005-February-10 Jason Rohrer * Added function to get time in floating point format. */ #include "minorGems/common.h" #ifndef TIME_INCLUDED #define TIME_INCLUDED /** * Interface for platform-independent, high-resolution time access. * * @author Jason Rohrer */ class Time { public: /** * Gets the current time in seconds and milliseconds. * * No guarentee about when absolute 0 of this time * scale is for particular systems. * * @param outSeconds pointer to where the time in seconds * will be returned. * @param outMilliseconds pointer to where the extra * milliseconds will be returned. Value returned is in [0,999]. */ static void getCurrentTime( unsigned long *outSeconds, unsigned long *outMilliseconds ); /** * Gets the current time in fractional (double) seconds. * * @return the current time in seconds. */ static double getCurrentTime(); /** * Gets the number of milliseconds that have passed * since a time in seconds and milliseconds. * * @param inSeconds the start time, in seconds. * @param inMilliseconds the start time's additional milliseconds. * * @return the number of milliseconds that have passed * since inSeconds:inMilliseconds. May overflow if * more than 49 days have passed (assuming 32-bit longs). */ static unsigned long getMillisecondsSince( unsigned long inSeconds, unsigned long inMilliseconds ); }; inline double Time::getCurrentTime() { unsigned long currentTimeS; unsigned long currentTimeMS; getCurrentTime( ¤tTimeS, ¤tTimeMS ); return currentTimeS + currentTimeMS / 1000.0; } inline unsigned long Time::getMillisecondsSince( unsigned long inSeconds, unsigned long inMilliseconds ) { unsigned long currentTimeS; unsigned long currentTimeMS; getCurrentTime( ¤tTimeS, ¤tTimeMS ); unsigned long deltaS = ( currentTimeS - inSeconds ); long deltaMS = ( (long)currentTimeMS - (long)inMilliseconds ); // carry, if needed if( deltaMS < 0 ) { deltaS--; deltaMS += 1000; } return 1000 * deltaS + deltaMS; } #endif primrose-6+dfsg1.orig/minorGems/system/Semaphore.h0000644000175000017500000001023307777611355021055 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2001-January-11 Jason Rohrer * Added a willBlock() function. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. * * 2002-February-11 Jason Rohrer * Fixed a mistake in the signal() comment. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. * * 2003-December-28 Jason Rohrer * Fixed a bug in semaphore value when we timeout on wait. * * 2004-January-9 Jason Rohrer * Fixed a preprocessor error. */ #include "minorGems/common.h" #ifndef SEMAPHORE_CLASS_INCLUDED #define SEMAPHORE_CLASS_INCLUDED #include "MutexLock.h" #include "BinarySemaphore.h" /** * General semaphore with an unbounded value. * * This class uses BinarySemaphores to implement general semaphores, * so it relies on platform-specific BinarySemaphore implementations, * but this class itself is platform-independent. * * @author Jason Rohrer */ class Semaphore { public: /** * Constructs a semaphore. * * @param inStartingValue the starting value for this semaphore. * Defaults to 0 if unspecified. */ Semaphore( int inStartingValue = 0 ); ~Semaphore(); /** * If this semaphore's current value is 0, then this call blocks * on this semaphore until signal() is called by another thread. * If this semaphore's value is >0, then it is decremented by this * call. * * @param inTimeoutInMilliseconds the maximum time to wait in * milliseconds, or -1 to wait forever. Defaults to -1. * * @return 1 if the semaphore was signaled, or 0 if it timed out. */ int wait( int inTimeoutInMilliseconds = -1 ); /** * If a thread is waiting on this semaphore, then the thread * becomes unblocked. * If no thread is waiting, then the semaphore is incremented. */ void signal(); /** * Returns true if a call to wait would have blocked. */ char willBlock(); private: // starts at 0 int mSemaphoreValue; // mutex semaphore starts at 1 BinarySemaphore *mMutexSemaphore; // blocking semaphore starts at 0 BinarySemaphore *mBlockingSemaphore; }; inline Semaphore::Semaphore( int inStartingValue ) : mSemaphoreValue( inStartingValue ), mMutexSemaphore( new BinarySemaphore() ), mBlockingSemaphore( new BinarySemaphore() ) { // increment the mutex semaphore to 1 mMutexSemaphore->signal(); } inline Semaphore::~Semaphore() { delete mMutexSemaphore; delete mBlockingSemaphore; } inline int Semaphore::wait( int inTimeoutInMilliseconds ) { int returnValue; // this implementation copied from _Operating System Concepts_, p. 172 // lock the mutex mMutexSemaphore->wait(); // decrement the semaphore mSemaphoreValue--; if( mSemaphoreValue < 0 ) { // we should block // release the mutex mMutexSemaphore->signal(); // block returnValue = mBlockingSemaphore->wait( inTimeoutInMilliseconds ); if( returnValue != 1 ) { // timed out // increment the semaphore, since we never got signaled // lock the mutex mMutexSemaphore->wait(); mSemaphoreValue++; // we will unlock the mutex below } } else { returnValue = 1; } // release the mutex // ( if we were signaled, then the signaller left the mutex locked ) // ( if we timed out, then we re-locked the mutex above ) mMutexSemaphore->signal(); return returnValue; } inline char Semaphore::willBlock() { char returnValue = false; // lock the mutex mMutexSemaphore->wait(); // check if we will block if( mSemaphoreValue <= 0 ) { returnValue = true; } // release the mutex mMutexSemaphore->signal(); return returnValue; } inline void Semaphore::signal() { // lock the mutex mMutexSemaphore->wait(); // increment the semaphore mSemaphoreValue++; if( mSemaphoreValue <= 0 ) { // we need to wake up a waiting thread mBlockingSemaphore->signal(); // let the waiting thread unlock the mutex } else { // no threads are waiting, so we need to unlock the mutex mMutexSemaphore->signal(); } } #endif primrose-6+dfsg1.orig/minorGems/system/MutexLock.h0000644000175000017500000000207307554113530021031 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-October-18 Jason Rohrer * Moved common include out of header and into platform-specific cpp files, * since MemoryTrack uses a mutex lock. */ #ifndef MUTEX_LOCK_CLASS_INCLUDED #define MUTEX_LOCK_CLASS_INCLUDED #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Mutex lock class. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class MutexLock { public: /** * Constructs a mutex lock; */ MutexLock(); ~MutexLock(); /** * Locks the mutex. Blocks until mutex available if it's * already locked by another thread. */ void lock(); /** * Unlocks the mutex. */ void unlock(); private: /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; }; #endif primrose-6+dfsg1.orig/minorGems/system/FinishedSignalThread.cpp0000644000175000017500000000203410033036772023463 0ustar pabspabs/* * Modification History * * 2002-March-9 Jason Rohrer * Created. * * 2002-March-11 Jason Rohrer * Changed so that destructor joins thread. * * 2002-April-4 Jason Rohrer * Changed name of lock to avoid confusion with subclass-provided locks. * * 2002-August-5 Jason Rohrer * Fixed member initialization order to match declaration order. * * 2004-April-1 Jason Rohrer * Moved from konspire2b into minorGems. * Changed so that destructor does not join the thread. */ #include "FinishedSignalThread.h" #include FinishedSignalThread::FinishedSignalThread() : mFinishedLock( new MutexLock() ), mFinished( false ) { } FinishedSignalThread::~FinishedSignalThread() { delete mFinishedLock; } char FinishedSignalThread::isFinished() { mFinishedLock->lock(); char finished = mFinished; mFinishedLock->unlock(); return finished; } void FinishedSignalThread::setFinished() { mFinishedLock->lock(); mFinished = true; mFinishedLock->unlock(); } primrose-6+dfsg1.orig/minorGems/system/FinishedSignalThreadManager.cpp0000644000175000017500000000461510170260026024756 0ustar pabspabs/* * Modification History * * 2004-November-9 Jason Rohrer * Created. * Modified from MUTE's ChannelReceivingThreadManager. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to allow sleep to be interrupted. */ #include "minorGems/system/FinishedSignalThreadManager.h" FinishedSignalThreadManager::FinishedSignalThreadManager() : mLock( new MutexLock() ), mThreadVector( new SimpleVector() ), mStopSignal( false ), mSleepSemaphore( new BinarySemaphore() ) { this->start(); } FinishedSignalThreadManager::~FinishedSignalThreadManager() { mLock->lock(); mStopSignal = true; mLock->unlock(); // signal the sleeping semaphore to wake up the thread mSleepSemaphore->signal(); this->join(); mLock->lock(); // destroy all remaining threads int numThreads = mThreadVector->size(); for( int i=0; igetElement( i ) ); } delete mThreadVector; mLock->unlock(); delete mLock; delete mSleepSemaphore; } void FinishedSignalThreadManager::addThread( FinishedSignalThread *inThread ) { mLock->lock(); mThreadVector->push_back( inThread ); mLock->unlock(); } void FinishedSignalThreadManager::run() { char stopped; mLock->lock(); stopped = mStopSignal; mLock->unlock(); while( !stopped ) { // wait for 10 seconds int wasSignaled = mSleepSemaphore->wait( 10000 ); if( wasSignaled == 1 ) { // signaled... we should stop return; } char foundFinished = true; while( foundFinished ) { foundFinished = false; mLock->lock(); int numThreads = mThreadVector->size(); for( int i=0; igetElement( i ) ); if( currentThread->isFinished() ) { delete currentThread; mThreadVector->deleteElement( i ); foundFinished = true; } } mLock->unlock(); } mLock->lock(); stopped = mStopSignal; mLock->unlock(); } } primrose-6+dfsg1.orig/minorGems/system/TestThread.h0000644000175000017500000000252107565075331021173 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Switched to a ThreadSafePrinter in attempt to get it to work on Win32. * Changed print call to printf. * * 2002-November-14 Jason Rohrer * Added missing destructor. */ #include "minorGems/common.h" #ifndef TEST_THREAD_CLASS_INCLUDED #define TEST_THREAD_CLASS_INCLUDED #include "Thread.h" #include "ThreadSafePrinter.h" #include /** * Test subclass of Thread class. Useful for testing if platform-specific * thread implmentations are working. * * @author Jason Rohrer */ class TestThread : public Thread { public: /** * Constructs a test thread and tells it how high to count to. * * @param inID id number thread will print along with count. * @param inNumToCount thread will count from 0 to this number. */ TestThread( int inID, int inNumToCount ); ~TestThread(); // override the run method from PThread void run(); private: int mID; int mNumToCount; }; inline TestThread::TestThread( int inID, int inNumToCount ) : mID( inID ), mNumToCount( inNumToCount ) { } inline TestThread::~TestThread() { } inline void TestThread::run() { for( int i=0; i<=mNumToCount; i++ ) { ThreadSafePrinter::printf( "Thread %d counting %d.\n", mID, i ); } } #endif primrose-6+dfsg1.orig/minorGems/system/StopSignalThread.cpp0000644000175000017500000000231510170267060022657 0ustar pabspabs/* * Modification History * * 2002-April-4 Jason Rohrer * Created. * Changed to reflect the fact that the base class * destructor is called *after* the derived class destructor. * * 2002-August-5 Jason Rohrer * Fixed member initialization order to match declaration order. * * 2003-September-5 Jason Rohrer * Moved into minorGems. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to make sleep interruptable by stop. */ #include "StopSignalThread.h" StopSignalThread::StopSignalThread() : mStopLock( new MutexLock() ), mStopped( false ), mSleepSemaphore( new BinarySemaphore() ) { } StopSignalThread::~StopSignalThread() { delete mStopLock; delete mSleepSemaphore; } void StopSignalThread::sleep( unsigned long inTimeInMilliseconds ) { mSleepSemaphore->wait( inTimeInMilliseconds ); } char StopSignalThread::isStopped() { mStopLock->lock(); char stoped = mStopped; mStopLock->unlock(); return stoped; } void StopSignalThread::stop() { mStopLock->lock(); mStopped = true; mStopLock->unlock(); // signal the semaphore to wake up the thread, if it is sleeping mSleepSemaphore->signal(); } primrose-6+dfsg1.orig/minorGems/system/linux/0000755000175000017500000000000011201637537020104 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/system/linux/ThreadLinux.cpp0000644000175000017500000001335410174541132023036 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2001-January-11 Jason Rohrer * Added missing sleep() implementation. * * 2002-March-27 Jason Rohrer * Added support for gprof-friendly thread wrappers. * Fixed a compile bug when gprof threads disabled. * * 2002-August-5 Jason Rohrer * Removed an unused variable. * * 2003-February-3 Jason Rohrer * Fixed sleep to be thread safe (signals were interrupting thread sleeps). * * 2004-March-31 Jason Rohrer * Added support for detatched mode. * * 2005-January-22 Jason Rohrer * Added a static sleep function. */ #include #include #include #include #include /** * Linux-specific implementation of the Thread class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * g++ -lpthread * If thread profiling is desired for gprof on linux, compile * with -DUSE_GPROF_THREADS (otherwise, only main thread is profiled). */ #ifdef USE_GPROF_THREADS // prototype int gprof_pthread_create( pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg ); #endif // prototype /** * A wrapper for the run method, since pthreads won't take * a class's member function. Takes a pointer to the Thread to run, * cast as a void*; */ void *linuxThreadFunction( void * ); Thread::Thread() { // allocate a pthread structure on the heap mNativeObjectPointer = (void *)( new pthread_t[1] ); } Thread::~Thread() { // de-allocate the pthread structure from the heap pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer; delete [] threadPointer; } void Thread::start( char inDetach ) { mIsDetached = inDetach; // get a pointer to the pthread pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer; // create the pthread, which also sets it running #ifdef USE_GPROF_THREADS gprof_pthread_create( &( threadPointer[0] ), NULL, linuxThreadFunction, (void*)this ); #else pthread_create( &( threadPointer[0] ), NULL, linuxThreadFunction, (void*)this ); #endif if( mIsDetached ) { pthread_detach( threadPointer[0] ); } } void Thread::join() { void *joinStat; pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer; pthread_join( threadPointer[0], &joinStat ); } void Thread::staticSleep( unsigned long inTimeInMilliseconds ) { unsigned long seconds = inTimeInMilliseconds / 1000; unsigned long milliseconds = inTimeInMilliseconds % 1000; struct timespec remainingSleepTimeStruct; remainingSleepTimeStruct.tv_sec = seconds; remainingSleepTimeStruct.tv_nsec = milliseconds * 1000000; struct timespec timeToSleepStruct; // sleep repeatedly, ignoring signals, untill we use up all of the time int sleepReturn = -1; while( sleepReturn == -1 ) { timeToSleepStruct.tv_sec = remainingSleepTimeStruct.tv_sec; timeToSleepStruct.tv_nsec = remainingSleepTimeStruct.tv_nsec; sleepReturn = nanosleep( &timeToSleepStruct, &remainingSleepTimeStruct ); } } // takes a pointer to a Thread object as the data value void *linuxThreadFunction( void *inPtrToThread ) { Thread *threadToRun = (Thread *)inPtrToThread; threadToRun->run(); if( threadToRun->isDetatched() ) { // thread detached, so we must destroy it delete threadToRun; } return inPtrToThread; } #ifdef USE_GPROF_THREADS // found at http://sam.zoy.org/doc/programming/gprof.html #include /* * pthread_create wrapper for gprof compatibility * * needed headers: * */ typedef struct wrapper_s { void * (*start_routine)(void *); void * arg; pthread_mutex_t lock; pthread_cond_t wait; struct itimerval itimer; } wrapper_t; static void * wrapper_routine(void *); /** * Same prototype as pthread_create; use some #define magic to * transparently replace it in other files */ int gprof_pthread_create( pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg ) { wrapper_t wrapper_data; int i_return; /* Initialize the wrapper structure */ wrapper_data.start_routine = start_routine; wrapper_data.arg = arg; getitimer(ITIMER_PROF, &wrapper_data.itimer); pthread_cond_init(&wrapper_data.wait, NULL); pthread_mutex_init(&wrapper_data.lock, NULL); pthread_mutex_lock(&wrapper_data.lock); /* The real pthread_create call */ i_return = pthread_create(thread, attr, &wrapper_routine, &wrapper_data); /* If the thread was successfully spawned, wait for the data * to be released */ if( i_return == 0 ) { pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock); } pthread_mutex_unlock(&wrapper_data.lock); pthread_mutex_destroy(&wrapper_data.lock); pthread_cond_destroy(&wrapper_data.wait); return i_return; } /** * The wrapper function in charge for setting the itimer value */ static void * wrapper_routine( void * data ) { /* Put user data in thread-local variables */ void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine; void * arg = ((wrapper_t*)data)->arg; /* Set the profile timer value */ setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL); /* Tell the calling thread that we don't need its data anymore */ pthread_mutex_lock(&((wrapper_t*)data)->lock); pthread_cond_signal(&((wrapper_t*)data)->wait); pthread_mutex_unlock(&((wrapper_t*)data)->lock); /* Call the real function */ return start_routine(arg); } #endif primrose-6+dfsg1.orig/minorGems/system/linux/MutexLockLinux.cpp0000644000175000017500000000311307554122211023533 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Moved common include out of header and into platform-specific cpp files, * since MemoryTrack uses a mutex lock. * Changed to use malloc instead of new internally to work with debugMemory. * Made use of mNativeObjectPointer a bit cleaner. */ #include "minorGems/common.h" #include #include #include /** * Linux-specific implementation of the MutexLock class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * g++ -lpthread */ MutexLock::MutexLock() { // allocate a mutex structure on the heap mNativeObjectPointer = malloc( sizeof( pthread_mutex_t ) ); // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; // init the mutex pthread_mutex_init( mutexPointer, NULL ); } MutexLock::~MutexLock() { // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; // destroy the mutex pthread_mutex_destroy( mutexPointer ); // de-allocate the mutex structure from the heap free( mNativeObjectPointer ); } void MutexLock::lock() { // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; pthread_mutex_lock( mutexPointer ); } void MutexLock::unlock() { // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; pthread_mutex_unlock( mutexPointer ); } primrose-6+dfsg1.orig/minorGems/system/linux/BinarySemaphoreLinux.cpp0000644000175000017500000001103210401110426024675 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. * * 2006-February-28 Jason Rohrer * Fixed bug in sub-second timeout computation. */ #include "minorGems/system/BinarySemaphore.h" #include "minorGems/system/Time.h" #include /** * Linux-specific implementation of the BinarySemaphore class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * g++ -lpthread */ /** * Native object pointer A is the condition variable. * Pointer B is the mutex that must go along with it. */ BinarySemaphore::BinarySemaphore() : mSemaphoreValue( 0 ) { // allocate a condition variable structure on the heap mNativeObjectPointerA = (void *)( new pthread_cond_t[1] ); // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // init the cond pthread_cond_init( &( condPointer[0] ), NULL ); // allocate a mutex structure on the heap mNativeObjectPointerB = (void *)( new pthread_mutex_t[1] ); // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // init the mutex pthread_mutex_init( &( mutexPointer[0] ), NULL ); } BinarySemaphore::~BinarySemaphore() { // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // destroy the cond pthread_cond_destroy( &( condPointer[0] ) ); // de-allocate the cond structure from the heap delete [] condPointer; // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // destroy the mutex pthread_mutex_destroy( &( mutexPointer[0] ) ); // de-allocate the mutex structure from the heap delete [] mutexPointer; } int BinarySemaphore::wait( int inTimeoutInMilliseconds ) { int returnValue = 1; // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // lock the mutex pthread_mutex_lock( &( mutexPointer[0] ) ); if( mSemaphoreValue == 0 ) { // wait on condition variable, which automatically unlocks // the passed-in mutex if( inTimeoutInMilliseconds == -1 ) { // no timeout pthread_cond_wait( &( condPointer[0] ), &( mutexPointer[0] ) ); } else { // use timeout version unsigned long nsecPerSecond = 1000000000; unsigned long nsecPerMillisecond = 1000000; unsigned long currentSec; unsigned long currentMS; Time::getCurrentTime( ¤tSec, ¤tMS ); unsigned long currentNS = currentMS * nsecPerMillisecond; long timeoutSec = inTimeoutInMilliseconds / 1000; long extraMS = inTimeoutInMilliseconds % 1000; long extraNS = extraMS * nsecPerMillisecond; unsigned long absTimeoutSec = currentSec + timeoutSec; unsigned long absTimeoutNsec = currentNS + extraNS; // check for nsec overflow if( absTimeoutNsec > nsecPerSecond ) { absTimeoutSec += 1; absTimeoutNsec -= nsecPerSecond; } struct timespec abstime; abstime.tv_sec = absTimeoutSec; abstime.tv_nsec = absTimeoutNsec; int result = pthread_cond_timedwait( &( condPointer[0] ), &( mutexPointer[0] ), &abstime ); if( result != 0 ) { // timed out returnValue = 0; } } // mutex is apparently re-locked when we return from cond_wait } // decrement the semaphore value mSemaphoreValue = 0; // unlock the mutex again pthread_mutex_unlock( &( mutexPointer[0] ) ); return returnValue; } void BinarySemaphore::signal() { // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // lock the mutex pthread_mutex_lock( &( mutexPointer[0] ) ); // increment the semaphore value mSemaphoreValue = 1; pthread_cond_signal( &( condPointer[0] ) ); // unlock the mutex pthread_mutex_unlock( &( mutexPointer[0] ) ); } primrose-6+dfsg1.orig/minorGems/system/FinishedSignalThread.h0000644000175000017500000000326510147345462023144 0ustar pabspabs/* * Modification History * * 2002-March-9 Jason Rohrer * Created. * * 2002-March-10 Jason Rohrer * Made destructor public. * * 2002-March-11 Jason Rohrer * Changed so that destructor joins thread. * * 2002-April-4 Jason Rohrer * Changed name of lock to avoid confusion with subclass-provided locks. * * 2004-April-1 Jason Rohrer * Moved from konspire2b into minorGems. * Changed so that destructor does not join the thread. * * 2004-November-19 Jason Rohrer * Changed to virtual inheritance from Thread class. */ #ifndef FINISHED_SIGNAL_THREAD_INCLUDED #define FINISHED_SIGNAL_THREAD_INCLUDED #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" /** * Abstract subclass if thread that has a * synchronized finished signal. * * @author Jason Rohrer */ class FinishedSignalThread : public virtual Thread { public: /** * Only destroys this thread. * Does not join. */ virtual ~FinishedSignalThread(); /** * Gets whether this thread is finished and * ready to be destroyed. * * @return true iff this thread is finished. */ char isFinished(); protected: FinishedSignalThread(); /** * Sets that this thread is finished and * ready to be destroyed. * * For this class to work properly, the subclass * MUST call this function at the end of its run method. */ void setFinished(); private: MutexLock *mFinishedLock; char mFinished; }; #endif primrose-6+dfsg1.orig/minorGems/system/FinishedSignalThreadManager.h0000644000175000017500000000273610170257606024437 0ustar pabspabs/* * Modification History * * 2004-November-9 Jason Rohrer * Created. * Modified from MUTE's ChannelReceivingThreadManager. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to allow sleep to be interrupted. */ #ifndef FINISHED_SIGNAL_THREAD_MANAGER_INCLUDED #define FINISHED_SIGNAL_THREAD_MANAGER_INCLUDED #include "minorGems/system/FinishedSignalThread.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/system/BinarySemaphore.h" /** * A thread that manages the destruction of FinishedSignalThreads. * * @author Jason Rohrer. */ class FinishedSignalThreadManager : public Thread { public: /** * Constructs and starts this manager. */ FinishedSignalThreadManager(); /** * Stops and destroys this manager. */ ~FinishedSignalThreadManager(); /** * Adds a thread to this manager. * * @param inThread the thread to add. * Will be destroyed by this class. */ void addThread( FinishedSignalThread *inThread ); // implements the Thread interface void run(); protected: MutexLock *mLock; SimpleVector *mThreadVector; char mStopSignal; BinarySemaphore *mSleepSemaphore; }; #endif primrose-6+dfsg1.orig/minorGems/system/ThreadSafePrinter.h0000644000175000017500000000262710032526077022474 0ustar pabspabs/* * Modification History * * 2000-October-14 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Converted to use MutexLock and added to minorGems source tree. * Changed tprintf to be static (the mutexes don't work otherwise). * Now we're closing the argument list. * Fixed so that it works with any number of arguments. * Changed name of print function to printf. * * 2004-March-31 Jason Rohrer * Fixed static memory leak. */ #include "minorGems/common.h" #ifndef THREAD_SAFE_PRINTER_INCLUDED #define THREAD_SAFE_PRINTER_INCLUDED #include "MutexLock.h" #include // for variable argument lists #include /** * Thread safe printf function. Note that printf is actually thread safe * anyway, so this is just to demonstrate and test locks. It seems as * though printf _isn't_ thread safe on certain platforms, so this class * may be useful. * * @author Jason Rohrer */ class ThreadSafePrinter { public: static int printf( const char* inFormatString, ... ); private: static MutexLock sLock; }; // initialize static members MutexLock ThreadSafePrinter::sLock; inline int ThreadSafePrinter::printf( const char*inFormatString, ... ) { va_list argList; va_start( argList, inFormatString ); sLock.lock(); int returnVal = vprintf( inFormatString, argList ); fflush( stdout ); sLock.unlock(); va_end( argList ); return returnVal; } #endif primrose-6+dfsg1.orig/minorGems/system/Thread.h0000644000175000017500000000560710174541121020324 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Made sleep() static so it can be called by non-Thread classes. * * 2001-May-12 Jason Rohrer * Added comments about joining before destroying. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-August-5 Jason Rohrer * Made destructor virtual. * * 2004-March-31 Jason Rohrer * Added support for detatched mode. * * 2005-January-9 Jason Rohrer * Made sleep function virtual to allow overrides. * * 2005-January-22 Jason Rohrer * Added a static sleep function. */ #include "minorGems/common.h" #ifndef THREAD_CLASS_INCLUDED #define THREAD_CLASS_INCLUDED #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Base class to be subclassed by all threads. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class Thread { public: Thread(); virtual ~Thread(); /** * Starts this Thread. * * Note that after starting a non-detached thread, it _must_ be * joined before being destroyed to avoid memory leaks. * * Threads running in detatched mode handle their own destruction * as they terminate and do not need to be joined at all. * * @param inDetach true if this thread should run in detatched mode, * or false to run in non-detached mode. Defaults to false. */ void start( char inDetach = false ); /** * To be overriden by subclasses. * This method will be run by the Thread after start() has been called. */ virtual void run() = 0; /** * Blocks until this thread finishes executing its run() method. * * Must be called before destroying this thread, if this thread * has been started. */ void join(); /** * Puts the current thread to sleep for a specified amount of time. * * Note that given a thread instance threadA, calling threadA.sleep() * will put the calling thread to sleep. * * @param inTimeInMilliseconds the number of milliseconds to sleep. */ virtual void sleep( unsigned long inTimeInMilliseconds ) { staticSleep( inTimeInMilliseconds ); } /** * Same as sleep, but can be called without constructing a thread. */ static void staticSleep( unsigned long inTimeInMilliseconds ); /** * Gets whether this thread is detached. * * @return true if this thread is detached. */ char isDetatched() { return mIsDetached; } private: /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; char mIsDetached; }; #endif primrose-6+dfsg1.orig/minorGems/system/TestThread.cpp0000644000175000017500000000231710032526430021511 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2002-November-14 Jason Rohrer * Added more verbose printouts. * * 2004-March-31 Jason Rohrer * Added test of detached threads. */ #include "TestThread.h" int numToCount = 1000; /** * Main method that spawns two TestThreads. * * @author Jason Rohrer */ int main() { TestThread *thread1 = new TestThread( 1, numToCount ); TestThread *thread2 = new TestThread( 2, numToCount ); TestThread *thread3 = new TestThread( 3, numToCount ); ThreadSafePrinter::printf( "Starting thread 1\n" ); thread1->start(); ThreadSafePrinter::printf( "Starting thread 2\n" ); thread2->start(); ThreadSafePrinter::printf( "Starting thread 3 in detached mode\n" ); thread3->start( true ); Thread::sleep( 5000 ); ThreadSafePrinter::printf( "Joining thread 1\n" ); thread1->join(); ThreadSafePrinter::printf( "Joining thread 2\n" ); thread2->join(); ThreadSafePrinter::printf( "Destroying thread 1\n" ); delete thread1; ThreadSafePrinter::printf( "Destroying thread 2\n" ); delete thread2; ThreadSafePrinter::printf( "Thread 3 should handle its own destruction.\n" ); return 0; } primrose-6+dfsg1.orig/minorGems/system/StopSignalThread.h0000644000175000017500000000361610170267060022331 0ustar pabspabs/* * Modification History * * 2002-April-4 Jason Rohrer * Created. * Changed to reflect the fact that the base class * destructor is called *after* the derived class destructor. * * 2003-September-5 Jason Rohrer * Moved into minorGems. * * 2004-November-19 Jason Rohrer * Changed to virtual inheritance from Thread class. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to make sleep interruptable by stop. */ #ifndef STOP_SIGNAL_THREAD_INCLUDED #define STOP_SIGNAL_THREAD_INCLUDED #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/system/BinarySemaphore.h" /** * Abstract subclass of thread that has a stop signal. * * Note that subclasses MUST check the isStopped() function * periodically in their run() function for this class to work * properly. * * @author Jason Rohrer */ class StopSignalThread : public virtual Thread { public: /** * Only destroys this thread. * Does not stop or join. */ virtual ~StopSignalThread(); protected: StopSignalThread(); // overrides Thread::sleep to make it interruptable by our stop call virtual void sleep( unsigned long inTimeInMilliseconds ); /** * Signals this thread to stop, interrupting it if it is sleeping. * * Thread safe. * * Thread must be joined after this call returns. */ void stop(); /** * Gets whether this thread has been signaled to stop. * * Thread safe. * * @return true if this thread should stop. */ char isStopped(); private: MutexLock *mStopLock; char mStopped; BinarySemaphore *mSleepSemaphore; }; #endif primrose-6+dfsg1.orig/minorGems/system/win32/0000755000175000017500000000000011201637537017707 5ustar pabspabsprimrose-6+dfsg1.orig/minorGems/system/win32/ThreadWin32.cpp0000644000175000017500000000456010174541132022443 0ustar pabspabs/* * Modification History * * 2001-January-27 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2004-March-31 Jason Rohrer * Added missing call to CloseHandle in destructor. * Added support for detatched mode. * * 2004-April-1 Jason Rohrer * Fixed a bug in CloseHandle call pointed out by Mycroftxxx. * * 2005-January-22 Jason Rohrer * Added a static sleep function. */ #include "minorGems/system/Thread.h" #include /** * Win32-specific implementation of the Thread class member functions. * */ // prototype /** * A wrapper for the run method, since windows thread (perhaps) won't take * a class's member function. Takes a pointer to the Thread to run, * cast as a void*; */ DWORD WINAPI win32ThreadFunction( void * ); Thread::Thread() { // allocate a handle on the heap mNativeObjectPointer = (void *)( new HANDLE[1] ); } Thread::~Thread() { // get a pointer to the allocated handle HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer; // close the handle to ensure that the thread resources are freed CloseHandle( threadPointer[0] ); // de-allocate the thread handle from the heap delete [] threadPointer; } void Thread::start( char inDetach ) { mIsDetached = inDetach; // get a pointer to the allocated handle HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer; DWORD threadID; threadPointer[0] = CreateThread( (LPSECURITY_ATTRIBUTES)NULL, // no attributes (DWORD)0, // default stack size win32ThreadFunction, // function (LPVOID)this, // function arg (DWORD)0, // no creation flags (start thread immediately) &threadID ); } void Thread::join() { HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer; WaitForSingleObject( threadPointer[0], INFINITE ); } void Thread::staticSleep( unsigned long inTimeInMilliseconds ) { Sleep( inTimeInMilliseconds ); } // takes a pointer to a Thread object as the data value DWORD WINAPI win32ThreadFunction( void *inPtrToThread ) { Thread *threadToRun = (Thread *)inPtrToThread; threadToRun->run(); if( threadToRun->isDetatched() ) { // thread detached, so we must destroy it delete threadToRun; } return 0; } primrose-6+dfsg1.orig/minorGems/system/win32/BinarySemaphoreWin32.cpp0000644000175000017500000000401707722702212024324 0ustar pabspabs/* * Modification History * * 2001-January-27 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. */ #include "minorGems/system/BinarySemaphore.h" #include /** * Win32-specific implementation of the BinarySemaphore class member functions. */ /** * Native object pointer A is the semaphore handle. * Pointer B is not used. */ BinarySemaphore::BinarySemaphore() : mSemaphoreValue( 0 ) { // allocate a handle on the heap mNativeObjectPointerA = (void *)( new HANDLE[1] ); // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; semaphorePointer[0] = CreateSemaphore( (LPSECURITY_ATTRIBUTES) NULL, // no attributes 0, // initial count 1, // maximum count (LPCTSTR) NULL ); // no name } BinarySemaphore::~BinarySemaphore() { // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; // destroy the semaphore CloseHandle( semaphorePointer[0] ); // de-allocate the handle from the heap delete [] semaphorePointer; } int BinarySemaphore::wait( int inTimeoutInMilliseconds ) { // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; if( inTimeoutInMilliseconds == -1 ) { WaitForSingleObject( semaphorePointer[0], INFINITE ); return 1; } else { // timeout int result = WaitForSingleObject( semaphorePointer[0], inTimeoutInMilliseconds ); if( result == WAIT_TIMEOUT ) { return 0; } else { return 1; } } } void BinarySemaphore::signal() { // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; ReleaseSemaphore( semaphorePointer[0], 1, (LPLONG) NULL ); } primrose-6+dfsg1.orig/minorGems/system/win32/LauncherWin32.cpp0000644000175000017500000000065007637725606023015 0ustar pabspabs/* * Modification History * * 2003-January-10 Jason Rohrer * Created. * * 2003-March-24 Jason Rohrer * Fixed a syntax typo. */ #include "minorGems/system/Launcher.h" #include #include void Launcher::launchCommand( char *inCommandName, char **inArguments ) { _spawnvp( _P_NOWAIT, inCommandName, inArguments ); } primrose-6+dfsg1.orig/minorGems/system/win32/MutexLockWin32.cpp0000644000175000017500000000341107554370760023160 0ustar pabspabs/* * Modification History * * 2001-January-27 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2002-October-18 Jason Rohrer * Moved common include out of header and into platform-specific cpp files, * since MemoryTrack uses a mutex lock. * * 2002-October-19 Jason Rohrer * Changed to use malloc instead of new internally to work with debugMemory. * Made use of mNativeObjectPointer a bit cleaner. * Fixed a few bugs with new use of mNativeObjectPointer. */ #include "minorGems/common.h" #include "minorGems/system/MutexLock.h" #include #include /** * Win32-specific implementation of the MutexLock class member functions. */ MutexLock::MutexLock() { // allocate a handle on the heap mNativeObjectPointer = malloc( sizeof( HANDLE ) ); // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; // create the mutex *mutexPointer = CreateMutex( (LPSECURITY_ATTRIBUTES) NULL, // no attributes (BOOL) false, // not initially locked (LPCTSTR) NULL ); // no name } MutexLock::~MutexLock() { // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; // destroy the mutex CloseHandle( *mutexPointer ); // de-allocate the mutex structure from the heap free( mutexPointer ); } void MutexLock::lock() { // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; WaitForSingleObject( *mutexPointer, INFINITE ); } void MutexLock::unlock() { // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; ReleaseMutex( *mutexPointer ); } primrose-6+dfsg1.orig/minorGems/system/win32/TimeWin32.cpp0000644000175000017500000000447010133647061022135 0ustar pabspabs/* * Modification History * * 2001-November-7 Jason Rohrer * Created. * * 2002-April-11 Jason Rohrer * Added missing include, and fixed a bug. * * 2004-January-29 Jason Rohrer * Fixed so that 0-point of time is the same as on other platforms. * * 2004-October-14 Jason Rohrer * Fixed bug in second/millisecond callibration. * Fixed bug in win32 time to ANSI time translation. * Fixed daylight savings time bug. */ #include "minorGems/system/Time.h" #include #include #include #include /** * Windows implementation of Time.h. * * The 0-point should match the ANSI standard. */ void Time::getCurrentTime( unsigned long *outSeconds, unsigned long *outMilliseconds ) { // convert from win32 broken-down time (which has msec resolution) // to an ANSI time struct and then convert to an absolute time in // seconds // This procedure ensures that the 0-point matches the ANSI standard. // note: // we cannot simply call ANSI time() to get the seconds and then rely // on GetLocalTime to get the milliseconds, since the seconds value // used by GetLocalTime is (strangely enough) not calibrated to the seconds // value of time(). // In other words, it is possible for the time() seconds to advance // at a different clock cycle than the GetLocalTime seconds. // get time using a win32 call SYSTEMTIME win32TimeStruct; GetLocalTime( &win32TimeStruct ); // convert this win32 structure to the ANSI standard structure struct tm ansiTimeStruct; ansiTimeStruct.tm_sec = win32TimeStruct.wSecond; ansiTimeStruct.tm_min = win32TimeStruct.wMinute; ansiTimeStruct.tm_hour = win32TimeStruct.wHour; ansiTimeStruct.tm_mday = win32TimeStruct.wDay; // ANSI time struct has month in range [0..11] ansiTimeStruct.tm_mon = win32TimeStruct.wMonth - 1; // ANSI time struct has year that is an offset from 1900 ansiTimeStruct.tm_year = win32TimeStruct.wYear - 1900; // unknown daylight savings time (dst) status // if we fail to init this value, we can get inconsistent results ansiTimeStruct.tm_isdst = -1; unsigned long secondsSinceEpoch = mktime( &ansiTimeStruct ); *outSeconds = secondsSinceEpoch; *outMilliseconds = (unsigned long)( win32TimeStruct.wMilliseconds ); } primrose-6+dfsg1.orig/runToBuild0000755000175000017500000000105611201637510015467 0ustar pabspabs#!/bin/sh # # Modification History # # 2007-November-12 Jason Rohrer # Copied from Cultivation. # cd tilePlacementGames/game1 chmod u+x ./configure ./configure cd gameSource echo "Building Primrose..." make cd ../../.. mkdir graphics mkdir settings cp tilePlacementGames/game1/gameSource/Primrose ./Primrose cp tilePlacementGames/game1/documentation/Readme.txt . cp tilePlacementGames/game1/gameSource/graphics/* ./graphics #no default settings files #cp tilePlacementGames/game1/gameSource/settings/* ./settings echo "Run Primrose to play." primrose-6+dfsg1.orig/tilePlacementGames/0000755000175000017500000000000011201637730017217 5ustar pabspabsprimrose-6+dfsg1.orig/tilePlacementGames/game1/0000755000175000017500000000000011201637757020222 5ustar pabspabsprimrose-6+dfsg1.orig/tilePlacementGames/game1/Makefile.GnuLinux0000644000175000017500000000150211144655174023427 0ustar pabspabs# # Modification History # # 2006-June-27 Jason Rohrer # Created. Condensed from X86 and PPC makefiles in Transcend project. # # 2007-April-23 Jason Rohrer # Removed unneeded libraries. # ## # The common GnuLinux portion of Makefiles. # Should not be made manually---used by configure to build Makefiles. ## PLATFORM_COMPILE_FLAGS = -DLINUX # various GL and X windows librariesneeded for linux # also need portaudio library (which in turn needs pthreads) PLATFORM_LINK_FLAGS = -L/usr/X11R6/lib -lGL -lGLU -lX11 -lSDL -lpthread # All platforms but OSX support g++ and need no linker hacks GXX = g++ LINK_FLAGS = ## # Platform-specific minorGems file path prefixes ## PLATFORM = Linux PLATFORM_PATH = linux TIME_PLATFORM = Unix TIME_PLATFORM_PATH = unix DIRECTORY_PLATFORM = Unix DIRECTORY_PLATFORM_PATH = unix primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/0000755000175000017500000000000011201637756022313 5ustar pabspabsprimrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/game.cpp0000644000175000017500000013645411175635676023756 0ustar pabspabs#include "game.h" #include "spriteBank.h" #include "sound.h" #include "GridSpace.h" #include "NextPieceDisplay.h" #include "numeral.h" #include "ColorPool.h" #include "Button.h" #include "Panel.h" #include "MenuPanel.h" #include "ScoreBundle.h" #include "secureSalt.h" #include #include #include #include "minorGems/util/random/CustomRandomSource.h" #include "minorGems/util/SettingsManager.h" #include "minorGems/crypto/hashes/sha1.h" unsigned int gameSeed = time( NULL ); CustomRandomSource randSource( gameSeed ); // global used to track how many sprite draws occur per frame int spriteDrawCount = 0; int screenW, screenH; int pointerX, pointerY; #define gridW 7 #define gridH 7 #define numGridSpaces 49 Color scoreColor( 255/255.0, 255/255.0, 160/255.0 ); // fade title out when app launches float titleFade = 1.0; char titleBlocked = false; GridSpace *spaces[gridW][gridH]; GridSpace *allSpaces[ numGridSpaces ]; #define numButtons 6 Button *allButtons[ numButtons ]; Button *undoButton; Button *menuButton; Button *doneButton; Button *playStopButton; Button *stepButton; Button *fastSlowButton; #define numPanels 1 Panel *allPanels[ numPanels ]; Panel *menuPanel; ColorPool *colorPool; NextPieceDisplay *nextPiece; // true if placement in progress char piecePlaced = false; // track the level of the piece just place (in case the level increments // due to this placement) int levelOfPlacement = 1; // grid spot where last piece placed int lastGridX = -1; int lastGridY = -1; int score = 0; int moveCount = 0; char savedStateAvailable = false; // for smooth transition between scores int lastScore = 0; float scoreTransitionProgress = 1; // for rewind int savedScore = 0; int chainLength = 1; char gameOver = false; char scoreWasSent = false; // for scheduling a restart char mustRestart = false; char playerName[9]; // has the player ever set a name? char nameSet = false; char colorblindMode = false; char soundOn = true; ScoreBundle *gameToPlayback = NULL; int gamePlaybackStep = 0; char gamePlaybackDone = false; char autoPlay = false; int stepsSinceLastAutoMove = 0; int stepsBetweenAutoMoves = 25; char manualStep = false; // for save/restore int savedPlaybackStep = 0; char playbackFast = false; // only fetch once per app run char *savedServerURL = NULL; // we'll destroy these when they're finished (instead of blocking on them // with a join) SimpleVector threadsToDestory; void addThreadToDestroy( FinishedSignalThread *inThread ) { threadsToDestory.push_back( inThread ); } // used to keep high score panel consisten across the destroys that // happen to it when a new game is triggered SimpleVector savedAllTimeScores; SimpleVector savedTodayScores; void clearSavedScores() { int i; for( i=0; i 48 ) { printf( "Bad base-49 encoding request: %c\n", inLetter ); return 0; } else { return returnValue; } } SimpleVector moveHistory; // for saving game char *savedMoveHistory = NULL; void newGame() { moveHistory.deleteAll(); if( savedMoveHistory != NULL ) { delete [] savedMoveHistory; savedMoveHistory = NULL; } if( gameToPlayback == NULL ) { gameSeed = time( NULL ); } else { gameSeed = gameToPlayback->mSeed; } randSource.reseed( gameSeed ); piecePlaced = false; levelOfPlacement = 1; lastGridX = -1; lastGridY = -1; score = 0; moveCount = 0; savedStateAvailable = false; lastScore = 0; scoreTransitionProgress = 1; savedScore = 0; chainLength = 1; gameOver = false; scoreWasSent = false; playbackFast = false; pointerX = -100; pointerY = -100; int i=0; int x; int y; for( y=0; y 0 ) { spaces[y][x]->mNeighbors[ GridSpace::top ] = spaces[y-1][x]; } if( y < gridH-1 ) { spaces[y][x]->mNeighbors[ GridSpace::bottom ] = spaces[y+1][x]; } if( x > 0 ) { spaces[y][x]->mNeighbors[ GridSpace::left ] = spaces[y][x-1]; } if( x < gridW-1 ) { spaces[y][x]->mNeighbors[ GridSpace::right ] = spaces[y][x+1]; } } } /* nextPiece = new NextPieceDisplay( 19 + 21, inHeight - (19 + 41) ); */ // center below grid colorPool = new ColorPool( spaces[6][3]->mX, screenH - 20 - 19 - 1 ); nextPiece = new NextPieceDisplay( spaces[6][3]->mX, spaces[6][3]->mY + 40 + 20 + 19 + 1, colorPool ); undoButton = new Button( nextPiece->mX - 60, nextPiece->mY - 20, "undo" ); menuButton = new Button( spaces[0][0]->mX, colorPool->mY - 41 - 19, "p" ); doneButton = new Button( undoButton->mX, menuButton->mY, "send" ); // up a bit from undo (to give space between play button) stepButton = new Button( undoButton->mX, undoButton->mY - 10, "step" ); // above menu button fastSlowButton = new Button( menuButton->mX, stepButton->mY, "fast" ); // same spot as done button playStopButton = new Button( doneButton->mX, doneButton->mY, "run" ); allButtons[0] = undoButton; allButtons[1] = menuButton; allButtons[2] = doneButton; allButtons[3] = playStopButton; allButtons[4] = stepButton; allButtons[5] = fastSlowButton; undoButton->setVisible( false ); menuButton->forceVisible(); doneButton->setVisible( false ); playStopButton->setVisible( false ); stepButton->setVisible( false ); fastSlowButton->setVisible( false ); if( gameToPlayback != NULL ) { playStopButton->setVisible( true ); stepButton->setVisible( true ); } menuPanel = new MenuPanel( screenW, screenH ); allPanels[0] = menuPanel; if( mustRestart ) { // previous menu panel requested a restart // show this new one at full blend at first, then fade out to // restarted game if( gameToPlayback == NULL ) { menuPanel->forceVisible(); } else { // it was high score display that triggered restart ( (MenuPanel *)menuPanel )->forceFadeOutScoreDisplay(); } } menuPanel->setVisible( false ); } void endGame() { int i; for( i=0; isetVisible( false ); scoreWasSent = true; SettingsManager::setHashingOn( true ); SettingsManager::setSetting( "scoreWasSent", 1 ); SettingsManager::setHashingOn( false ); } void playbackGame( ScoreBundle *inBundle ) { if( gameToPlayback != NULL ) { delete gameToPlayback; } gameToPlayback = inBundle; gamePlaybackStep = 0; gamePlaybackDone = false; // default to not autoPlay autoPlay = false; stepsSinceLastAutoMove = 0; manualStep = false; //printf( "Playing back game with moves:\n%s\n", inBundle->mMoveHistory ); mustRestart = true; } void initFrameDrawer( int inWidth, int inHeight ) { #ifdef IPHONE // working directory on iPhone is inside bundle, but // we can't save persistent files there. // Document directory is backed up. SettingsManager::setDirectoryName( "../Documents" ); #endif // don't use the same salt every time // read the last-used salt off the disk char *lastHashSalt = SettingsManager::getStringSetting( "hashSalt" ); if( lastHashSalt != NULL ) { // salt used is always saved salt plus internal security salt char *totalSalt = autoSprintf( "%s%s", lastHashSalt, secureSalt ); delete [] lastHashSalt; SettingsManager::setHashSalt( totalSalt ); delete [] totalSalt; } else { SettingsManager::setHashSalt( secureSalt ); } SettingsManager::setHashingOn( false ); int i; for( i=0; i<10; i++ ) { //printf( "Rand output: %u\n", randSource.getRandomInt() ); } screenW = inWidth; screenH = inHeight; initSpriteBank(); char *nameSetting = SettingsManager::getStringSetting( "name" ); if( nameSetting != NULL ) { int nameLength = strlen( nameSetting ); if( nameLength > 8 ) { nameLength = 8; } memcpy( playerName, nameSetting, nameLength ); playerName[ nameLength ] = '\0'; delete [] nameSetting; } else { memcpy( playerName, "anon", 5 ); } char found; nameSet = SettingsManager::getIntSetting( "nameSet", &found ); if( !found ) { nameSet = false; } colorblindMode = SettingsManager::getIntSetting( "colorblindMode", &found ); if( !found ) { colorblindMode = false; } soundOn = SettingsManager::getIntSetting( "soundOn", &found ); if( !found ) { soundOn = true; } initSound(); //exit( 0 ); if( soundOn ) { setSoundPlaying( true ); } newGame(); // should we restore from disk? // saved games are secure // note that I realize this is weak security. // all someone needs to do is figure out the secure salt, which // they can do by looking at the code. However, it's still // harder than simply editing the settings files with a text // editor. Strong security is impossible here. SettingsManager::setHashingOn( true ); int wasSaved = SettingsManager::getIntSetting( "saved", &found ); if( found && wasSaved ) { char anyFailed = false; char *state = SettingsManager::getStringSetting( "moveHistorySaved" ); if( state != NULL ) { moveHistory.setElementString( state ); delete [] state; } else { anyFailed = true; } state = SettingsManager::getStringSetting( "nextPieceDisplaySaved" ); if( state != NULL ) { nextPiece->restoreFromSavedState( state ); delete [] state; } else { anyFailed = true; } state = SettingsManager::getStringSetting( "colorPoolSaved" ); if( state != NULL ) { colorPool->restoreFromSavedState( state ); delete [] state; } else { anyFailed = true; } state = SettingsManager::getStringSetting( "randStateSaved" ); if( state != NULL ) { unsigned int randState; int numRead = sscanf( state, "%u", &randState ); if( numRead == 1 ) { randSource.restoreFromSavedState( randState ); } else { anyFailed = true; } delete [] state; } else { anyFailed = true; } state = SettingsManager::getStringSetting( "gameSeedSaved" ); if( state != NULL ) { sscanf( state, "%u", &gameSeed ); delete [] state; } else { anyFailed = true; } score = SettingsManager::getIntSetting( "scoreSaved", &found ); if( !found ) { anyFailed = true; score = 0; } gameOver = (char)( SettingsManager::getIntSetting( "gameOverSaved", &found ) ); if( !found ) { anyFailed = true; gameOver = 0; } scoreWasSent = (char)( SettingsManager::getIntSetting( "scoreWasSent", &found ) ); if( !found ) { anyFailed = true; // assume score sent if flag not present scoreWasSent = 1; } if( gameOver && !scoreWasSent ) { doneButton->setVisible( true ); } state = SettingsManager::getStringSetting( "gridSaved" ); if( state != NULL ) { int numParts; char **parts = split( state, "#", &numParts ); if( numParts == numGridSpaces ) { for( int i=0; i= 0 ) { c = colorPool->pickColor( index ); } allSpaces[i]->setColor( c ); } else { anyFailed = true; } } } else { anyFailed = true; } for( int i=0; isetVisible( true ); stepButton->setVisible( true ); } else { gamePlaybackDone = true; } // never allow sending score on a playback game doneButton->setVisible( false ); } else { anyFailed = true; } gamePlaybackStep = SettingsManager::getIntSetting( "gamePlaybackStepSaved", &found ); if( !found ) { anyFailed = true; gamePlaybackStep = 0; } } } else { anyFailed = true; } if( anyFailed ) { // game was supposedly saved, but we failed to load // the whole thing (hash-checked)... // corrupted, so don't trust any of it // don't want to load only certain parts of a saved game // correctly (like the score, but not the grid) printf( "Failed to load part of saved game." " Starting new game instead.\n" ); endGame(); newGame(); } } // back to normal, insecure settings mode SettingsManager::setHashingOn( false ); if( colorblindMode ) { for( i=0; i<4 && !titleBlocked; i++ ) { if( ! spaces[5][ 2 + i ]->isEmpty() ) { titleBlocked = true; } } } } void freeFrameDrawer() { if( savedStateAvailable ) { printf( "Saving game state %d moves in\n", moveCount ); // secure // new hash each time char *saltSeed = autoSprintf( "%d%s\n", time( NULL ), secureSalt ); char *newSalt = computeSHA1Digest( saltSeed ); delete [] saltSeed; // save so that it can be used when loading game next time SettingsManager::setSetting( "hashSalt", newSalt ); // salt used for hashing is always saved salt plus internal // security salt char *totalSalt = autoSprintf( "%s%s", newSalt, secureSalt ); delete [] newSalt; SettingsManager::setHashSalt( totalSalt ); delete [] totalSalt; SettingsManager::setHashingOn( true ); // save the last saved (known good) state out to disk SettingsManager::setSetting( "moveHistorySaved", savedMoveHistory ); char *state = nextPiece->getSavedState(); SettingsManager::setSetting( "nextPieceDisplaySaved", state ); delete [] state; state = colorPool->getSavedState(); if( state != NULL ) { SettingsManager::setSetting( "colorPoolSaved", state ); delete [] state; } state = autoSprintf( "%u", randSource.getSavedState() ); SettingsManager::setSetting( "randStateSaved", state ); delete [] state; state = autoSprintf( "%u", gameSeed ); SettingsManager::setSetting( "gameSeedSaved", state ); delete [] state; SettingsManager::setSetting( "scoreSaved", savedScore ); SettingsManager::setSetting( "gameOverSaved", (int)gameOver ); SettingsManager::setSetting( "scoreWasSent", (int)scoreWasSent ); int i; SimpleVector gridState; for( i=0; igetSavedColor(); int index = colorPool->getColorIndex( c ); gridState.push_back( autoSprintf( "%d", index ) ); } char **gridStateArray = gridState.getElementArray(); state = join( gridStateArray, gridState.size(), "#" ); delete [] gridStateArray; for( i=0; imName, gameToPlayback->mScore, gameToPlayback->mSeed, gameToPlayback->mMoveHistory ); SettingsManager::setSetting( "gameToPlaybackSaved", state ); delete [] state; SettingsManager::setSetting( "gamePlaybackStepSaved", savedPlaybackStep ); SettingsManager::setSetting( "playingBackGameSaved", 1 ); } else { SettingsManager::setSetting( "playingBackGameSaved", 0 ); } SettingsManager::setSetting( "saved", "1" ); SettingsManager::setHashingOn( false ); } endGame(); freeSpriteBank(); freeSound(); // we don't do this in endGame because sometimes we're ending // last game before starting a new playback if( gameToPlayback != NULL ) { delete gameToPlayback; } gameToPlayback = NULL; if( savedServerURL != NULL ) { delete [] savedServerURL; } savedServerURL = NULL; if( savedMoveHistory != NULL ) { delete [] savedMoveHistory; } savedMoveHistory = NULL; clearSavedScores(); // what about any threads? for( int i=0; iisFinished() ) { printf( "Warning: Thread not finished at freeFrameDrawer.\n" " Letting it leak instead of blocking.\n" ); } else { delete thread; } } } void computeEarLoudness( int inPieceX, float *outLeftVolume, float *outRightVolume ) { float rightEarX = 4; float leftEarX = 2; float screenDistance = 5; // use triangles float vLeft = sqrt( pow( screenDistance, 2 ) + pow( leftEarX - inPieceX, 2 ) ); float vRight = sqrt( pow( screenDistance, 2 ) + pow( rightEarX - inPieceX, 2 ) ); *outLeftVolume = pow( screenDistance, 2 ) / pow( vLeft, 2 ); *outRightVolume = pow( screenDistance, 2 ) / pow( vRight, 2 ); } int computeGroupScoreFactor( int inGroupSize ) { if( inGroupSize < 11 ) { return (int)( 10 * sqrt( inGroupSize ) ); } else { return inGroupSize + 21; } } // one round of non-chained clearing // returns true if some pieces cleared char checkAndClear() { char someCleared = false; int i; int j; for( i=0; imVisited = false; allSpaces[i]->mChecked = false; allSpaces[i]->mMarkedForClearing = false; } char playingClearingSound = false; for( j=0; jmVisited = false; } GridSpace *space = allSpaces[j]; if( ! space->mChecked ) { Color *c = space->checkSurrounded(); if( c != NULL ) { // space returns its own color if its group is // surrounded by nothing but edges // must be surrounded by another color (not just edges) // to clear if( ! space->colorMatches( c ) ) { // all visited spaces part of group // tally score int groupSize = 0; int groupColorIndex = -1; // accumulate average volume float leftEarWeight = 0; float rightEarWeight = 0; for( i=0; imVisited ) { allSpaces[i]->mMarkedForClearing = true; groupColorIndex = allSpaces[i]->getColorIndex(); groupSize ++; float lV, rV; int x = i % gridW; computeEarLoudness( x, &lV, &rV ); leftEarWeight += lV; rightEarWeight += rV; } } // play at most one per round if( !playingClearingSound && soundOn ) { // start sounds playClearingSound( groupColorIndex, groupSize, chainLength, leftEarWeight / groupSize, rightEarWeight / groupSize ); playingClearingSound = true; } // set score for them all for( i=0; imVisited ) { /* // old scoring allSpaces[i]->mScore = (int)( pow( groupSize, 2 ) ) * (int)( pow( chainLength, 4 ) ) * (int)( pow( levelOfPlacement, 2 ) ); */ // new scoring allSpaces[i]->mScore = (int) ( // level bonus added in instead of // multiplied ( computeGroupScoreFactor( groupSize ) + 12 * (levelOfPlacement - 1) ) * pow( chainLength, 4 ) ); } } } delete c; } } } // clear any that are marked for( i=0; imMarkedForClearing ) { allSpaces[i]->flipToClear(); someCleared = true; } } if( someCleared ) { chainLength ++; } return someCleared; } void saveStateForUndo() { int i; for( i=0; isaveState(); } nextPiece->saveState(); colorPool->saveState(); randSource.saveState(); savedScore = score; if( savedMoveHistory != NULL ) { delete [] savedMoveHistory; } savedMoveHistory = moveHistory.getElementString(); savedPlaybackStep = gamePlaybackStep; savedStateAvailable = true; } void placeNextPieceAt( unsigned int inSpaceNumber ) { // always disable immediately after piece placement // to avoid player trying to undo during animation undoButton->setVisible( false ); char considerNonActive = true; if( nextPiece->isSecondPiece() ) { considerNonActive = false; } if( moveCount == 0 ) { // no saved state, because no moves made yet // save starting state here saveStateForUndo(); } char encodedMove = base49Encode( inSpaceNumber ); moveHistory.push_back( encodedMove ); // modulate random source by player's move // draw some random numbers and discard them // the number of draws depends in inSpaceNumber AND the current // state of the generator (so that reordering a sequence of moves // DOES NOT lead to the same generator state). int numToDraw = randSource.getRandomBoundedInt( 0, inSpaceNumber ); // this approach works well because it requires no extra state // and it doesn't compromise the statistical properties of the random // generator (like mixing inSpaceNumber into the generator seed can) for( int d=0; dgetNextPiece(); if( soundOn ) { int x = inSpaceNumber % gridW; float leftVolume, rightVolume; computeEarLoudness( x, &leftVolume, &rightVolume ); playPlacementSound( colorPool->getColorIndex( c ), leftVolume, rightVolume ); } allSpaces[inSpaceNumber]->setColor( c ); piecePlaced = true; levelOfPlacement = colorPool->getLevel(); colorPool->registerMove(); lastGridY = inSpaceNumber / gridW; lastGridX = inSpaceNumber % gridW; // reset chain length counter chainLength = 1; if( !considerNonActive ) { // just placed in an active spot (second piece) // all to non-active for( int i=0; imActive = false; } } } void drawFrame() { if( mustRestart ) { endGame(); // we need to prevent people from using the last saved state, // which lingers after a new game is started, as a checkpoint. // If they play no moves in the new game before quitting, they // can restart Primrose later and get back into the old saved state, // EVEN IF they made some moves past the saved state before starting // the new game. // disable the last saved state: SettingsManager::setHashingOn( true ); SettingsManager::setSetting( "saved", "0" ); SettingsManager::setHashingOn( false ); newGame(); mustRestart = false; } int i; // look for threads that are finished for( int i=0; iisFinished() ) { delete thread; threadsToDestory.deleteElement( i ); i--; } } if( titleFade > 0 ) { titleFade -= 0.02; if( titleFade < 0 ) { titleFade = 0; } } char animDone = true; for( i=0; istep(); if( playbackFast ) { // double-step allSpaces[i]->step(); } animDone &= allSpaces[i]->isAnimationDone(); } for( i=0; istep(); } for( i=0; istep(); } nextPiece->step(); colorPool->step(); if( playbackFast ) { // double-step nextPiece->step(); colorPool->step(); } if( piecePlaced && animDone ) { // done with placement, all placement (or clearing) animations done /* // accumulate any points scored lastScore = score; for( i=0; imScore > 0 ) { score += allSpaces[i]->mScore; allSpaces[i]->mScore = 0; } } if( lastScore != score ) { scoreTransitionProgress = 0; } */ // check if any more clear (which will start more animations) lastScore = score; if( !checkAndClear() ) { // check if board full char full = true; for( i=0; iisEmpty() ) { full = false; } } if( full ) { gameOver = true; if( gameToPlayback == NULL ) { // don't save final state yet // need to update nextPiece first. doneButton->setVisible( true ); } else { // done with playback playStopButton->setVisible( false ); stepButton->setVisible( false ); fastSlowButton->setVisible( false ); playbackFast = false; gamePlaybackDone = true; } } nextPiece->update(); if( gameOver ) { // save state again incase game terminated after // game ends // can't undo back beyond this point anyway, // now that game is over! saveStateForUndo(); } piecePlaced = false; if( nextPiece->isSecondPiece() ) { // allow undo of first piece if( !full && gameToPlayback == NULL ) { undoButton->setVisible( true ); } // set grid spaces in same row/column to active int x; int y; char anyActive = false; for( y=0; yisEmpty() ) { space->mActive = true; anyActive = true; } } for( x=0; xisEmpty() ) { space->mActive = true; anyActive = true; } } if( !anyActive ) { // all empty active for( i=0; iisEmpty() ) { allSpaces[i]->mActive = true; } } } } else { // placing new first piece undoButton->setVisible( false ); // save state here to support undoing back to it after // next move saveStateForUndo(); } } } // recheck animDone if( animDone ) { animDone = true; for( i=0; istep(); animDone &= allSpaces[i]->isAnimationDone(); } } // check if we should auto/manual step replay game // only step when animation from previous step done // pause when sub-panels visible char somePanelVisible = false; // skip drawing board when one fully visible char somePanelFullyVisible = false; for( i=0; iisVisible() ) { somePanelVisible = true; } if( allPanels[i]->isFullyVisible() ) { somePanelFullyVisible = true; } } if( animDone && !somePanelVisible ) { if( gameToPlayback != NULL && !gamePlaybackDone ) { if( autoPlay && ( playbackFast || stepsSinceLastAutoMove > stepsBetweenAutoMoves ) || manualStep ) { if( gamePlaybackStep < gameToPlayback->mNumMoves ) { unsigned int spaceNumber = base49Decode( gameToPlayback->mMoveHistory[ gamePlaybackStep ] ); placeNextPieceAt( spaceNumber ); gamePlaybackStep ++; } stepsSinceLastAutoMove = 0; manualStep = false; } else if( autoPlay ) { // only step after animations done stepsSinceLastAutoMove ++; } else if( !autoPlay ) { // animations done, re-enable stepButton->setVisible( true ); } } } spriteDrawCount = 0; if( !somePanelFullyVisible ) { for( i=0; idrawGrid(); } for( i=0; idraw(); } for( i=0; idrawPieceCenter(); } for( i=0; idrawPieceHalo(); } nextPiece->draw(); colorPool->draw(); // additive needed for smooth cross-fade between last score and // new score glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE ); if( scoreTransitionProgress < 1 ) { drawScoreBig( lastScore, 320 - 19, nextPiece->mY + 41, &scoreColor, 1 - scoreTransitionProgress ); } if( scoreTransitionProgress > 0 ) { drawScoreBig( score, 320 - 19, nextPiece->mY + 41, &scoreColor, scoreTransitionProgress ); } if( titleFade > 0 && !titleBlocked ) { drawStringBig( "primrose", left, spaces[5][2]->mX, spaces[5][2]->mY, &scoreColor, titleFade ); } glDisable( GL_BLEND ); if( scoreTransitionProgress < 1 ) { scoreTransitionProgress += 0.075; if( scoreTransitionProgress > 1 ) { scoreTransitionProgress = 1; } } } for( i=0; idraw(); } //printf( "%d sprites drawn this frame\n", spriteDrawCount ); } void undoMove() { int i; for( i=0; irewindState(); } nextPiece->rewindState(); colorPool->deRegisterMove(); randSource.rewindState(); moveCount--; if( moveHistory.size() > 0 ) { moveHistory.deleteElement( moveHistory.size() - 1 ); } int temScore = score; score = savedScore; lastScore = temScore; scoreTransitionProgress = 0; // only one step of undo allowed undoButton->setVisible( false ); } void pointerDown( float inX, float inY ) { pointerX = (int)inX; pointerY = (int)inY; } void pointerMove( float inX, float inY ) { pointerX = (int)inX; pointerY = (int)inY; } void pointerUp( float inX, float inY ) { pointerX = (int)inX; pointerY = (int)inY; //printf( "Pointer Up at %f,%f\n", pointerX, pointerY ); // pass through to visible panels char somePanelVisible = false; int i; for( i=0; iisVisible() || allPanels[i]->isSubPanelVisible() ) { somePanelVisible = true; allPanels[i]->pointerUp( pointerX, pointerY ); } } if( somePanelVisible ) { // don't pass click to grid return; } char someButtonPressed = false; for( i=0; iisVisible() && allButtons[i]->isInside( pointerX, pointerY ) ) { someButtonPressed = true; if( allButtons[i] == undoButton ) { undoMove(); } else if( allButtons[i] == menuButton ) { menuPanel->setVisible( true ); } else if( allButtons[i] == doneButton ) { char *moveString = moveHistory.getElementString(); ScoreBundle *b = new ScoreBundle( playerName, score, gameSeed, moveString ); delete [] moveString; //printf( "posting score\n" ); ( (MenuPanel*)menuPanel )->postScore( b ); } else if( allButtons[i] == playStopButton ) { if( autoPlay ) { playStopButton->setString( "run" ); playbackFast = false; } else { playStopButton->setString( "stop" ); playbackFast = false; fastSlowButton->setString( "fast" ); } autoPlay = !autoPlay; stepButton->setVisible( !autoPlay ); fastSlowButton->setVisible( autoPlay ); // re-enable display of active markers if coming out of // fast mode here. for( i=0; imActiveMarkerVisible = !playbackFast; } } else if( allButtons[i] == stepButton ) { manualStep = true; // disable during step animations stepButton->setVisible( false ); } else if( allButtons[i] == fastSlowButton ) { if( playbackFast ) { fastSlowButton->setString( "fast" ); } else { fastSlowButton->setString( "slow" ); } playbackFast = !playbackFast; // disable display of active markers in fast mode // (because they flicker in an annoying way) for( i=0; imActiveMarkerVisible = !playbackFast; } } } } if( someButtonPressed ) { // don't pass click to grid return; } if( gameToPlayback != NULL ) { // don't pass click to grid return; } if( piecePlaced ) { // last placement still in progress // ignore grid clicks return; } // don't count clicks below a certain point as grid clicks // (don't want player to miss clicking a button and place a piece by // accident) if( pointerY > spaces[6][0]->mY + 29 ) { // no grid clicks this far down return; } char considerNonActive = true; if( nextPiece->isSecondPiece() ) { considerNonActive = false; } unsigned int x; unsigned int y; // sloppy pointing: // if none hit, look for closest space char noneHit = true; int closestIndex = -1; float closestDistanceSquared = 99999999; float closestXDeltaSquared = 99999999; float closestYDeltaSquared = 99999999; for( y=0; yisEmpty() && ( considerNonActive || space->mActive ) ) { unsigned int i = y * gridW + x; if( space->isInside( pointerX, pointerY ) ) { closestIndex = i; noneHit = false; } else { float xDeltaSquared = (space->mX - pointerX) * (space->mX - pointerX); float yDeltaSquare = (space->mY - pointerY) * (space->mY - pointerY); float distanceSquared = xDeltaSquared + yDeltaSquare; if( distanceSquared < closestDistanceSquared ) { closestDistanceSquared = distanceSquared; closestIndex = i; closestXDeltaSquared = xDeltaSquared; closestYDeltaSquared = yDeltaSquare; } } } } } // ignore clicks more than a 3/4 space-width away from // closest space center (space width is 40) float limit = 30 * 30; // of course, if piece hit directly, ignore distance if( ( closestXDeltaSquared < limit && closestYDeltaSquared < limit && closestIndex >= 0 ) || ! noneHit ) { placeNextPieceAt( closestIndex ); } } void addToScore( int inPointsToAdd ) { score += inPointsToAdd; scoreTransitionProgress = 0; } char getNameSet() { return nameSet; } char *getName() { return playerName; } void saveName() { if( strlen( playerName ) == 0 ) { // default to anon memcpy( playerName, "anon", 5 ); } SettingsManager::setSetting( "name", playerName ); SettingsManager::setSetting( "nameSet", 1 ); nameSet = true; } char getColorblindMode() { return colorblindMode; } void setColorblindMode( char inOn ) { colorblindMode = inOn; SettingsManager::setSetting( "colorblindMode", (int)colorblindMode ); } char getColorblindSymbol( Color *inColor ) { return colorPool->getColorblindSymbol( inColor ); } int getColorIndex( Color *inColor ) { return colorPool->getColorIndex( inColor ); } char getSoundOn() { return soundOn; } void setSoundOn( char inOn ) { soundOn = inOn; SettingsManager::setSetting( "soundOn", (int)soundOn ); setSoundPlaying( soundOn ); } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/TutorialPanel.h0000644000175000017500000000166011134543746025252 0ustar pabspabs#include "Panel.h" #include "NextPieceDisplay.h" #include "TutorialPanelB.h" class TutorialPanel : public Panel { public: TutorialPanel( int inW, int inH ); ~TutorialPanel(); // overrides these: char pointerUp( int inX, int inY ); void setVisible( char inIsVisible ); void step(); protected: // override void drawBase(); // receive close event void closePressed(); private: void setStageZero(); Button mNextButton; TutorialPanelB mNextPanel; NextPieceDisplay mNextPieceDemo; GridSpace *mGridDemo[4][7]; GridSpace *mAllDemoSpaces[28]; int mDemoStage; int mStepsBetweenStages; int mStepCount; }; primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/gridLineRight.png0000644000175000017500000000277211130754644025561 0ustar pabspabsPNG  IHDR@@iq pHYs  tIME! ttEXtCommentCreated with The GIMPd%npIDATxn۸sHJr@Y Eyʼfq3. tS*Ksf!qbwsՈa&LZwG=" <}cݝ@?A 퐮tL?A.Touv: ƶ[ʛ7Xf 9]bZxxA駩xA|_n~ea֗[[mqU3ë N-H),BGrבon(wws8L^48~ DS1kIF/8o[۷z.3zyu9Ʊ:%6M5%6@=m3!D?Fw9WLdQI됗/q iu-"?"j{QǓ#K\סǩR@y i[Q0!21 )`,4f4)U0_hۢ^`#1"U8!f*4+O2[~GyeX "_#WWR&! !9$itׯ+`z `XV+ `xel4b9c&"Y3V V=S5V+b68NYf0 R('*ER s!Bf BSoR(g ,*Bxs]&.Hg]r)2#C1# RsdCTX]c_RꚒJ4ct,LF3FU"XJJ]Sc%E&hGH@R)aK9Y$Ҥq<`H40޽ú2 #a c_U-CfmK!$ضմ p 9K}#?D}o@!]]߿q,myY~.l23ȗ>$ئ#fXnqt)]f s"{f )]UEܜB`nr2!cJf`)1cǑQvY =z_ِ񯿦ӴlH]Gޗo(̿>4[g}pwGgߦ =ЉIENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/gameGLUT.cpp0000644000175000017500000001012211142633144024407 0ustar pabspabs#include "game.h" #include #include #include #include // callbacks for GLUT void callbackMotion( int inX, int inY ); // ignore passive motion // void callbackPassiveMotion( int inX, int inY ); void callbackMouse( int inButton, int inState, int inX, int inY ); void callbackDisplay(); void callbackTimer( int inValue ); // keyboard to catch quit keys (don't pass to game) void callbackKeyboard( unsigned char inKey, int inX, int inY ); void callbackReshape( int inW, int inH ); void cleanUpAtExit() { printf( "Exiting...\n" ); freeFrameDrawer(); } int w = 320; int h = 480; // 25 fps //int frameMS = 40; int frameMS = 500; // s and f keys to slow down and speed up for testing //char enableSlowdownKeys = false; char enableSlowdownKeys = true; int main( int inNumArgs, char **inArgs ) { glutInit( &inNumArgs, inArgs ); atexit( cleanUpAtExit ); glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowSize( w, h ); glutCreateWindow( "game1" ); glutMotionFunc( callbackMotion ); glutMouseFunc( callbackMouse ); //glutPassiveMotionFunc( callbackPassiveMotion ); glutDisplayFunc( callbackDisplay ); //glutIdleFunc( callbackIdle ); glutReshapeFunc( callbackReshape ); // 25 fps glutTimerFunc( frameMS, callbackTimer, 0 ); glutKeyboardFunc( callbackKeyboard ); #ifdef __mac__ // make sure working directory is the same as the directory // that the app resides in // this is especially important on the mac platform, which // doesn't set a proper working directory for double-clicked // app bundles // arg 0 is the path to the app executable char *appDirectoryPath = stringDuplicate( inArgs[0] ); char *appNamePointer = strstr( appDirectoryPath, "tileGame1.app" ); if( appNamePointer != NULL ) { // terminate full app path to get parent directory appNamePointer[0] = '\0'; chdir( appDirectoryPath ); } delete [] appDirectoryPath; #endif initFrameDrawer( w, h ); glutMainLoop(); return 0; } void callbackDisplay() { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( 0, 320, 480, 0, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glDisable( GL_TEXTURE_2D ); glDisable( GL_CULL_FACE ); glDisable( GL_DEPTH_TEST ); drawFrame(); glutSwapBuffers(); } /* void callbackIdle() { glutPostRedisplay(); } */ void callbackTimer( int inValue ) { glutTimerFunc( frameMS, callbackTimer, 0 ); if( glutGet( GLUT_WINDOW_WIDTH ) != w || glutGet( GLUT_WINDOW_HEIGHT ) != h ) { glutReshapeWindow( w, h ); } glutPostRedisplay(); } void callbackMotion( int inX, int inY ) { pointerMove( inX, inY ); } void callbackMouse( int inButton, int inState, int inX, int inY ) { if( inState == GLUT_DOWN ) { pointerDown( inX, inY ); } else if( inState == GLUT_UP ) { pointerUp( inX, inY ); } else { printf( "Error: Unknown mouse state received from OpenGL\n" ); } } void callbackKeyboard( unsigned char inKey, int inX, int inY ) { // q or escape if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) { exit( 0 ); } if( enableSlowdownKeys ) { if( inKey == 's' || inKey == 'S' ) { // slow frameMS = 500; } if( inKey == 'f' || inKey == 'F' ) { // normal frameMS = 40; } } } void callbackReshape( int inW, int inH ) { // force original size glutReshapeWindow( w, h ); // note that we also need to check this in the main loop above // because sometimes callbackReshape isn't getting called (maybe // after releasing the mouse near the end of a resize) } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/mnopqrstuvwx_big.png0000644000175000017500000002476611133721703026464 0ustar pabspabsPNG  IHDR InbKGDC pHYs  tIME7 D IDATx}ͫ$IGDG0^ftA4=H$, VaIIS0 P뮗2"tH3/ OWU]R/_~{fpED~]Wzjc@ŨsjHL8sڀ=iTn*<~į˿TWsc̣Gp+l6POWWWRJ)<v'ƤJks%6$)h]SC^__h16A>~nEOb"k9Ѱ6ejH !Xce$d2of YFd[: Eq]d(ccB}_=o03y%ObZ1""F heZ!#k )LoVP2q~c V15' Ǐ:PdogG#c2F T֢ KM1%.c܏i"cҠs*]xth wAK=RlH録!dZ?~|N<@&bZ RJ _zCGH I1RJZK9*_à:[`(`)szX u=^2$Pb']OӌrIIc}=Ԁo!@tiM4zͪnBT x8N rhOJP"fw ŋO>qnahkM4{M$=q=!5Q]8Ajgq3Nt'|f.qƒxQC8am0p¥u_v='Ӧ,Vv]خh!j GjDn$ۉPM qoP{I+<'7;I !$" Mq}۶#Np}}]R>&|‡#/B_cp¦iV!"vZ$9\](M4-sƇz0u\)?eQσ*Jfe6:;fCx^Ncw@ ČFK }Oq]WD4BXҽ5#=H%! G"OHzP~ȭ(%BbteN,Bq<>lhZbej"2%J&+s@*%(X],){u$ڤYcD*ȍ쓐}-rVRRJ}+I[ xI! lk V xeDBkLJ{'\R-XkZD۝Єw,jRːf%|!5c7?ƤR)pQ0$1iYسJOZL)9B9ED1$%:6ϕFzNIB YRR, GرRN8!2tL(eE6@iJ}4ٱ\-/a5\x}}-Զm{1L@d\ݙfzBGE4N!nDsHu J0j'|(J~p7gAtVXP8n}'#8Ƈ> 'TYXY'deĬQD!a%TţqBDputVF][ᄍ ;(mT0 r}'7~08^O bG.i6υc,?f۰G;mF 3ElQRJ" Qrֆl۶8 E&a.#(Fϯ l>!aP44@΍+רOܙǏs4#}SJًZA5CtagU!rV%lHWLh;`:`HvVv?2R%^fR!b#2'NoIƘȷ<8#W5)(f/O׈+{D`댖j(>Q0;=a5CIH>" ̖1̪|ƦiJL !$jӳ<{cbO P!ϡd"&"`G1h'aɡ[@8!"s.y*zv Gք|uD,Qo""cPz@Ͼ#žh'mv...o&T%0= 3W=km_Eր>X-hԞ|BS1ι-W̯&U>!?Tn4t8sK\:UӬw q݆ݾ4' v[A$_\+ e)?g-a y b,8r=OXAEgy*$sr x>M؃SJ&x"}'U |£xh#s@ԃ+? V~,HuV~*N^8yr5d3Nx>!W.wӐ{8!߮P'T kvSFk||B&> ~m/(>!/k>%( _~m`iO(C z429 !U>٘0 ^Uc;=1*uC9K^GI#_޷Yk_op&].$>{ Xt<j5&OR&,+e7wJXkԓ=nj'@0bպ7*R8CDRdj{%D$%@ž㈜Pp \\Ǐ҃Z )QEr%|:.5lv#L딡ɠ1rw=,dZ,Á|u\JlYnl:" !.DP>@'.I|҄GU|¦!6Ms^AcԊ#C.R`^9Uft-:bS c9! "FD/MR,uN~@z9'a> K}PwAXQчFM1clm䛈;sB w|@a f4>ppZW5$8  !6( sroNlC~'ℵZc3Nh nBj^+(|_&XR˿īp>O3MO'q `3x|BZ;;;D Z&8. %{4q8tPx2G6qn4$vK0>LJJTƊRI 屖hud1tB={|'Ǧ˭2:${ PSS$8H M["e vo~q,WZN!@ >}LGKeᔳx4MC0s%Ft+PmZ, 18QU)ma'?#l>4(駟o*gf3!55MqLmfEO?LMlHxSJ>J. QS#9 '^"pe xg7'[.~*U2IWcY{"ڪI;2;:Av5*@1m=oU81Ε2z"`Ƕ 1i2 iȑGւebnE2Bɀ97ڶ`eZO( U2*]|\I R:Qq}ֆ,@$WNKH>a- 0I8|2>}4FI jItv`;q{?wfӧW_}UGɎZ8-d# _|-K^5 ]_|2Fk9́ǢgG Rp6PI=C6 s>ɹL6 <ѹLeZV3kă;:u][oxJ}8d 'ԍ!)<&!HKKD)YѢVԶfDp-0j:T|-_|0y/H|;"rΤP8YDN*^rd%w.<{$>4D,3D HINNeyRٸ?|bTqB+lL&OiUTӎ/HZ`݄Oc4*WqFɸ룘elGmQ.//"PѶPò*Q8B'kU`(L:Q8PYN_=,)OX H =qwwgj:lUi\'f Lr_7Y8bZh!5)%ct1&*iK췿-~W%}:sWDJAEa pR^\\ hj*TjF1j 8/k1:F}u]ITk !D\1(WDaPk:DfuJ&0*E? X,C*X:11 fԜ))U2SZ\OkWAaFp$Y!?X(,ޕN9DVFNS[ȯ2sfsTR̸9f08ڶ]?0zq|gyQT;2[K}'cLlO !t9!497`X? /aӊ !8@'2d!G*˗/5}06p!5܅ι;1mu^~}HщȍOU"0D=@ʼðg07ynfh<.h<5"!' sXs|Bs|w'*bΝa%б]f{'ㄕYn^|i>}j7Mcm 7:Ddgw.ќ|40 0WWWKxi"Vƾ'wOTmA'sx,E['p s;O?E)8ڦi">!Yl{o۶ A.ض-7-rM51m'eu{t7ݫ1"tamc1۔Zrܢ*N.sa+"XT̈́k$JL1[=Gh۴^s!"#:l+>79bmu,g!T Ccv)_!G1Zᮗ P=/fΐ ˘K'o*ץęƘL^bTxqiG43@7* -ngtt1*MKh9@Ř`E{b/IncOD{OpEqRJV<蓂2]IDL8Ӓs5bCG6>߰t]QIbCWAP^zo69xg;ט pl.b\w‡Ә'Q& =<+M;x5_n\AO~+g}orW^٦iG}ۭCDZ2{R(%Z=Q_F=maG+r]gܨÛz.LJS90`a c!7C[" !CTV^PdzqεhH9`59+  w=\u}Y^+7FkJR"auՍk.8qb#i~n2uN8 :tJjxQֿr8܀JwK hAJ! n0jEL( WM%jniP(Aҍ'F59ǵUGoRr)%\r^憪E%PJk-*c12Y:cI:A.X1DRJRjTBa^Z{L)aWm@۶2IL{[4M3R.+;6LPkiSJI)VE?0܋\q=u](*Ӥ  RJ*5ƈ92*89֬%ER9@fGgCP""U8}!?-+2 u*P] u"J&)$\Ҏ)%RDe,J>%4,.:Lh/thTҺ tYtdƘhPdut^3nHD>SJ1T5>@8FnPH9"t; 8֠y$$g7_kM"F rYcśͦ#"B49kB9ᲠiffZ-, LS:NN5jjjśGNpSQ9 f.5\U\&<(AO z9=z^]]/twwG)BOp|wǤ6;>!/x PQ k/q)oi@b9|z:Ǐ}X0DDpuuE&4ToHN̜AdfN̎v`Vt@IAfM8W18^b.18C6:sŠLBcȳ=L,? 0 nG ぀BXi2N4MBFpZDlq0uM&VH3{.?/g_{-"n EVL݌ `*e4rXhG^'3: PF>Jdsl^-Κ777ymۂ)1^3A\ڶ%5okN:qT,!U4eram%wiG%ڝ3Ni݂1fg8"c@`HP8٪2/..yN WreC5IBNg]Ĉj,1Ix1|_5M|rsB'Z|Rm' ?SBJ2|L!b2w`8 lٳN S D̬RuhZ8mI!(cI(V!U1 ߋN(ϟ?oY(²'"oɁ1#yv-~'(DiZa轏Mx!cīF1`TϿ0ui"&S8ksKCsn97{ ^2>w]1@V`a:p^tJ:y7ic4YNXz#|"*c ,여eIY@㩆 9JfSZ@4asay.:>Ai<~_j|WΤU'D!`Dh|J:_|u:_|u;G[0<IENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/abcdefghijkl_big.png0000644000175000017500000002471011133670005026227 0ustar pabspabsPNG  IHDR InbKGDC pHYs  tIME x IDATx}ͫ[_Ȭtmmipc^nwƸޘx?'6 1x׋մlhuGU/*(ɬ{4=7!u*<EADp "~wd8w֙QaTU_W 7٨q"TYPT[.TT]T.KnkkXw+m%PM^}.#"S 0QA}-CHz{kN>9LJɨ{9c>p{oBWp 4=t[眩sI*\PriiXι+SJRJZ+Mb9''uNfO^Z 0Xkuܟ5ƃ<޾8u7t"j^?VkIJ+t]WBJJAcLN)%-v2 \'{]r΀.l+AD91i7yzk 9c ZqazQzRADs^c1O] c {r1IgX*/HcG!rΆ,wV ɽ!DZ{}=(Sv PGa$#Cp@9>1Z1. 0TW,<2Jx9)E9gvO'`%SZac x  Ƙ_V }Q]u "9u0U4|L|=@1ZG]ⷡqll8 5E"5"$km&$f[{-D&"Jڡl˪["&3!]__*<#"UdRF|m^d1jYP?{=~x"\ZkYD"VKBP""&Iy!f1{y{#}kls 0 )u5zfZ"x?>dW0VrBA)(VJ'(RfuuhC{O!ۅP<G7͸^G#m ^`bWsC(<] }6yӧEnW3jL)VU>|!sAAYu]Zs{Ro1wffOjQi>Z///G5Kr0aK`G +*DtdV%BI>t:(^h;-O N Ħ<'| p¿8aa'L)i +y2$bD=No]pBQj%Vp's(%[5J&os !!ڕ"qbK怐z5mA( \?D2dV0BZVœ3i~28uA@'_ Fu83ÇX-Ҝ5$7Shx[` ӧOa:R XkIu 2Dc&"˔RR ,c irMuUπcPI3 HR|OVlrMDLy#T̪1&Zub ,h,@%w<?'Yk .&]@ln) cJA\SPm{S!m WURҌ#2 ,6zw@s.Vͤ"HD`js*\0呟=|+YPİuakX#Zk.$ "xOTWX)$vD,X>0Z:Tkeo d%:띌B{?*c8@ !DX 'T~v)EEDBNl4J Hɓ'enfZj'vB.//ӓ'ObVy9=Y=r/9:%H%[ |;Bǁ'NCP+g[]pB { 5VI%)KvFe2s:;;Ko߾Mϟ? c,NSpBETi ' i,Nxuu:qTs"BlB$HDcschAt-@+DvFDֳUz'QJI*C`(D$GDiz!iZ Z(m!?ޛƴ]JWR_sC@i+_֛bR ځ!7%pӱҩtJ) J1T/VĹA(Mi@uJ$^t*x Aٍȯmf6#d5Fݐr"oQH,ۆjA( 0 ivю/oBUADPt>H)Mt>DLzHD~ EDĺ= eY\s\1ޔHjͲ 48 .TMmTh^NƄ!" 63n!'"-7؆H7za aSJ{\]GD!YZP?pd>58yJD{8!ېwQ+&<#&IQ+&1?~<+}~լrDKzIxd>9Hj ']p~p޷~ǧtI߃x2{!3Тftfn)dsN9RJϞ=5f7HDQqG]yp!zF2k " }ߏV-pR& kp9Wι.+2[ctC$+ge'DĎ / OmIP;9;::\%a}j)1^uc0<3逈~nOҢ1`?13l¨ c6h1V ^ O됈X]jN֠ErRIDD] 2Sٜ']00V( iin#"ƜFI!)Pժc',0}SJZp3~EcVn` 8a=x,N̪I)( Akt.KDF[H)3RJ)眳Tι=27ozxH)D {nnP_]PdUl;2hd]ϜzyfV=%n[e4Ni'Jd)CD+뼵 ZrΑsNnj ckmݜe`6CDM;Rq"#51!BzDؑ9cL;1tf '1FY[ %2$Z&Y9s)眸p[ٔT@ Q8!;? WzZjn!1ιb9Lsιff9'i䝳  (ebvH(߾Xϸ+ƫ/E,?v]`b2'jv8᝕Ϯ| p-w OVN_TwOh,Du@榿nnnZw&W^5w /v5 ̙l>ft|BP~'q+|B#q p^M@b0CO(,g?ӕXUqMD+"uٔQbdT\[UP)pyGJׅ~콯Up2'>.P]9e(N(~9^?gmX > 0Цbb|oRJ=Kc,s~<eV21XkR:M4QJ:9璸} oX@wS֒6c6Ok`:)awow"#`c/i8Dpr8"rLBF?$:>Q/eEI[Q{3nRÛ7oJ`IW&a6k!\U|&q7,o7Ç<]\\4^ 0?)<o^s{X'Bt}}:%HD~}9gϞիWŋE:߽,7s>8N9>9{/E..)sA7A`A?t=;CpDtB֛6$"^P2AKQi†CFl ޽{7g=2ZP2*2c1kF%gϞZCu24Q?iHE0vnA7$zqdOc/7DT=}WG o4;.WP\Fꫯ1hnLD=6>cZԼb hsdG&1[vu`eo(۪MUdߟk%>aAI8,[Uf9DАlKJdYk7oݱof yLpS$*oPpl϶Eifw8.ƏD]č9^:p-,1[:(zh) gA:߾}>|ml~˵snǤ+I(:/..ow} DQ,Ϟ=y;!9!QIn@G!!'~#+-XCnY8'm* <&=C|6> 8)>aw"@w, l,J~K#GewNw icT&S=[@ðRT!b3p1FWh.//A0 h)Ӌ!:i~-z\fR\!4Dʆts8.YR%FYa#[`2E.E+`?ާBpYD̏~hxlv^"3U9c{B"K(IxN\}$b97%D{E%GI> =I6.:X3SB5 !PJi)T(DdT#,c&  m8] RYiJgPJd> '$"Xj&MiRِv'\Ǒ ___c;,ILA哬w1 v]W'\c"dgce~P KyL'yL`c\ {.; $|PcK3͸9Ƙx y}yLXyInc2 CD@D1)۔b~<& |<&:+O Inִ+l㋋ [Y>U|ugw|hH!E-f\۷o=}m6vZwj/n]~*Du3]T%6z ; 3vMpqq`,a8KDrC+"*׈hBXW 3 QʬqZ&\q8/ӆV{ibvni$ bTI8HpUU'\EgjUZJ9V'$.睪hg-l5Nhmz01'mPyعxX.aU)+fL7蕳Xyu777#$"!YkS Eϊi "gU(8!3LTE*lsKEr%|xǩV-'&+`FھL7= RX:Ho)i\jeE@~&f)1F!*9;p9TgǾȠoQ&T$1*[<M7< /iv4&C3OV@9ۚLRn@EJ,RcIR*Q[1>F|3'pBXJ Y Z}BDIW8Zc1GnSI)mRJM)mWwA*Ϟtc(tlQ. xOt7A3 Ƙ}dtMQ0 Q6# rsNz6dnvmv|F@o\3 5L'a:vf73ܐ9z-计DjV ƭ 8gouvǧOnDD^hF7aPGÇBHϟ?U9^qSu#9Q!~I~?z_DET"Kt>wgxQ"1͑uJf'SBSǡ F 3c'JmHT }uufnv= zlV777ՕkgHllH5JjR!cV%,Ӱ v!b-b$@ѸZZGa5kŦJ@aC6$ٴbhTW)48f FUjc1~%JeB&h+K)Gц0 {H_Gx\V+sk&+DQ(i-, P@+˿*I>-n2ㄢ!oZ m癝*Wz!,s~Uw;..| ${?GH1F1e=޼yC@777y亄{˳@ g"?z(@Ǒxa2N2hN{Y10:M@fT𚈀#?qeQB sIAMÒaG3WB9ߌ1`C^֤8v]`^seѣGVƍ&% [u$KM䊔Zg3y/YЀLe,VnacH :kKI-D 0n0 #_gFر'91IJJ>i"C<"s"j8Bxs&99F9w!8v#":./IGDNn࣓ 91%? Ece/sZXrpde*5v #LpA1 DU ( լnW^!G*׮2d$_]I#.UT+xyN?ze_Ds:^_B<ѝ{ϊ=~k'v=~@ x Ņo̻w̑"+po2޼}OYD6$q[XevNJ8i O5Xc`ɑsem⢍Uی|!_ IIDATvogA-0ARap!cb c;fF'wjgZvZ/c|gccׯ_(w@MШDn[}>a`9Îwhf\$.9ω8H+*Zr,.IuZQa8݈A(OZ۷YxsÎYx:8>1NM2i%|'dN s%mt`/rT8Xpӈ/7 dm~y=!(0n9FDp 2Żcxh<"ZQB[Oy oVZ㕥Gz̠g^lsZV*c:N)Id1%j9W0{2vt3O~ޟJ*(C62ٌϒ\ ׳Q;^BduWq1J^bhbp; fo1s[b;3lcZb 3#SextZBv,L`[Wma ͏˝'6qCMxݖ١iaخvz؇jC59qxѬsM]~:Y7OG%k~B>9Nxd>k2ϚN&TOT8s8aODOyO2؄ 8!c{9ݩ<a '؇V8a(y<0i Nx~~^l +58~nlf>|| MfpMh.m.I!&$kO)ꪖ"I7,;fMQYk=0ODw651yLbJ):cF! CI1*9T,jsɄyLcZ5/Z2թLW+qVxEMsc L?JE{Vh9ǜszqel4Y_.//ɓ'{|†$U {޾}#G?X/'(ɧM5R){OX{8x8x8x8<x IENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/mnopqrstuvwx_working.xcf0000644000175000017500000005201011133721703027356 0ustar pabspabsgimp xcf file}si_UKA7-# BB$gimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) !"ABTR blur6 copy     ")"5 \   4 /      /     ((         4 /      /     ((         4 /      /     ((        !""! ",2332," ,8?BB?8, 1>FHHF>1 !2>DEED>2! 0;??;0 -687786-*230032*'--++--' !&&$$&&!           $*,*$  %07850' +7==;7/$ -8<;:83(-797664*,453243++230022+)00--00)&--**--& !&&$$&&!           %,//,%  %18;;81% +7>@@>7+-8=>>=8--7:99:7--675576--675576--7:99:7--8=>>=8-+7>@@>7+ %18;;81%  %,//,%                                                                                     %,00,%  %2:==:2% -:BEEB:, 1?GHHE=/"4CIKIE=/$6ELLID:,$6EKID=3& "3@D@91' -782*! $++$           %,//,%  %18;;81% +7>@@>7+-9=>>=8-.8:996,-685452*-68533/'-79752-$ *59862,"  $.4540) #),,)#           %,00,%  %2:==:2% -:CFFC:- 2@GJJG?1 "5CKNNKB3!$7GPSSOD4!$7HQUUOC1"5DMQQK>- /;4+  /;@=5+             '  / (     1           '  / (     1           '  / (     1/7.$-:AA=6,  (6?CC>5'  #0;BED;- +6?EE=/'2>=8-+7>@@>7+ %18;;81%  %,//,%           !&&$$&&! &-,**,-&)0/--/0))00--00)'..,,..' #*+**+*#    '  / 4   %      '  / 4   %      '  / 4   %    $&''&$ !""!     &      !&&$$&&! '--++--'*230032*-687786- 0;??;0 !2>DEED>2! 1>FHHF>1 ,8?BB?8, ",2332," !""!  $       "#!!#"  %&&%  $&''&$  !%''%!  $''$  $&&$   #$$#         @blur6     ""B<BH#*o3<   4 /      /     ((         4 /      /     ((         4 /      /     ((        !""! ",2332," ,8?BB?8, 1>FHHF>1 !2>DEED>2! 0;??;0 -687786-*230032*'--++--' !&&$$&&!           $*,*$  %07850' +7==;7/$ -8<;:83(-797664*,453243++230022+)00--00)&--**--& !&&$$&&!           %,//,%  %18;;81% +7>@@>7+-8=>>=8--7:99:7--675576--675576--7:99:7--8=>>=8-+7>@@>7+ %18;;81%  %,//,%                                                                                     %,00,%  %2:==:2% -:BEEB:, 1?GHHE=/"4CIKIE=/$6ELLID:,$6EKID=3& "3@D@91' -782*! $++$           %,//,%  %18;;81% +7>@@>7+-9=>>=8-.8:996,-685452*-68533/'-79752-$ *59862,"  $.4540) #),,)#           %,00,%  %2:==:2% -:CFFC:- 2@GJJG?1 "5CKNNKB3!$7GPSSOD4!$7HQUUOC1"5DMQQK>- /;4+  /;@=5+             '  / (     1           '  / (     1           '  / (     1/7.$-:AA=6,  (6?CC>5'  #0;BED;- +6?EE=/'2>=8-+7>@@>7+ %18;;81%  %,//,%           !&&$$&&! &-,**,-&)0/--/0))00--00)'..,,..' #*+**+*#    '  / 4   %      '  / 4   %      '  / 4   %    $&''&$ !""!     &      !&&$$&&! '--++--'*230032*-687786- 0;??;0 !2>DEED>2! 1>FHHF>1 ,8?BB?8, ",2332," !""!  $       "#!!#"  %&&%  $&''&$  !%''%!  $''$  $&&$   #$$#         @sharp      BCRRC.GKOT   T   T   T                                                            T T T T@ New Layer     SxSSSSSSS@primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/spriteBank.cpp0000644000175000017500000000751611150656130025120 0ustar pabspabs#include "spriteBank.h" #include "common.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/stringUtils.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" const char *spriteNames[ numSprites ] = { "gridLineTop", "gridLineBottom", "gridLineLeft", "gridLineRight", "plus", "piece", "pieceHalo", "pieceCenter", "pieceBrightHalo", "pieceBrightCenter", "numerals", "numeralsBig", "abcdefghijkl", "mnopqrstuvwx", "yzplus", "abcdefghijkl_big", "mnopqrstuvwx_big", "yzplus_big" }; SingleTextureGL *spriteTextures[ numSprites ]; void initSpriteBank() { for( int i=0; ir, inColor->g, inColor->b, inAlpha ); } else { glColor4f( 1, 1, 1, inAlpha ); } texture->enable(); // NOTE: this won't look good if we do the zoom-to-clear effect glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); const GLfloat squareVertices[] = { inCenterX - inXRadius, inCenterY - inYRadius, inCenterX + inXRadius, inCenterY - inYRadius, inCenterX - inXRadius, inCenterY + inYRadius, inCenterX + inXRadius, inCenterY + inYRadius, }; /* const GLubyte squareColors[] = { 255, 255, 0, 255, 0, 255, 255, 255, 255, 0, 0, 0, 255, 0, 255, 255, }; */ const GLfloat squareTextureCoords[] = { 0, inSubsectionOffset, 1, inSubsectionOffset, 0, inSubsectionOffset + inSubsectionExtent, 1, inSubsectionOffset + inSubsectionExtent }; glVertexPointer( 2, GL_FLOAT, 0, squareVertices ); glEnableClientState( GL_VERTEX_ARRAY ); //glColorPointer( 4, GL_FLOAT, 0, squareColors ); //glEnableClientState( GL_COLOR_ARRAY ); glTexCoordPointer( 2, GL_FLOAT, 0, squareTextureCoords ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* glBegin( GL_QUADS ); { glTexCoord2f( 0, inSubsectionOffset ); glVertex2f( inCenterX - inXRadius, inCenterY - inYRadius ); glTexCoord2f( 1, inSubsectionOffset ); glVertex2f( inCenterX + inXRadius, inCenterY - inYRadius ); glTexCoord2f( 1, inSubsectionOffset + inSubsectionExtent ); glVertex2f( inCenterX + inXRadius, inCenterY + inYRadius ); glTexCoord2f( 0, inSubsectionOffset + inSubsectionExtent ); glVertex2f( inCenterX - inXRadius, inCenterY + inYRadius ); } glEnd(); */ texture->disable(); spriteDrawCount ++; } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/yzplus_working.xcf0000644000175000017500000001407411133717772026132 0ustar pabspabsgimp xcf file@(7-# BB$gimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches)  @b@ blur6 copy     v@@  ! .      J  t  ! .      J  t  ! .      J  t      ")*()*)# (14463*,7<>@@<0 ,9AFIIC5# (6AHMNG7$ #0@@<0 ,9AFIIC5# (6AHMNG7$ #0<#/&@M~7+o-RxV$;S&@%7}3Iwg`fe7Gk0LF,ٜ_\\DGz33Yr (}+'O8dAjp|^0m ~j p K:S#X,21T8]ׅ< >43 @>f Mm[bg}π{̌BafN<{,J*$-%}%q$=t* I2Kb`(?NCG݀_?s mg{}S ҟ]Ւ0@n̤wN?<1{o= ;?lLo0?^__B80waX,O%0Ybz tCYBm% OlLw JL1R4mHP[j>$M'|,YBlل,G3kݸ#igggo0sm1>4v))LM4>w%zq2˙x=~cfn4 9PY~yye¾oЖ4&i8iڶPu'.#WU5l6E!BjjVVc00O686eYV̆Tg/8繶mWi-H3g<l6j\ p&'МЅI/OEnm~WEٶmEv:@gggjbJ>NFܕaPb $'tR:ɝ.= ޑ`@/3;nL= i ui89Mr=IzO)+TUu$R҃$ٯBb`.vi8qJN=k/}^+h"{ $f6$kn=!frm7 mResponse; char mResultReady; char *mResult; HostAddress *mSuppliedAddress; HostAddress *mNumericalAddress; BringNetworkUpThread *mNetworkUpThread; LookupThread *mLookupThread; Socket *mSock; }; #endif primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/HighScorePanel.h0000644000175000017500000000250411134376405025314 0ustar pabspabs#ifndef HIGH_SCORE_PANEL_INCLUDED #define HIGH_SCORE_PANEL_INCLUDED #include "Panel.h" #include "ScoreBundle.h" class HighScorePanel : public Panel { public: HighScorePanel( int inW, int inH ); ~HighScorePanel(); // pointer to menu panel, which this panel returns to sometimes void setMenuPanel( Panel *inMenuPanel ) { mMenuPanel = inMenuPanel; } void clearScores(); // destroyed by this class void addAllTimeScore( ScoreBundle *inScore ); void addTodayScore( ScoreBundle *inScore ); // overrides these: void setVisible( char inIsVisible ); char pointerUp( int inX, int inY ); protected: // override void drawBase(); void closePressed(); private: SimpleVector mAllTimeScores; SimpleVector mTodayScores; // scores associated with each button, or NULL ScoreBundle *mAllScores[16]; Button *mAllTimeButtons[8]; Button *mTodayButtons[8]; Button *mAllButtons[16]; Panel *mMenuPanel; }; #endif primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/WebRequest.cpp0000644000175000017500000002756611154475521025122 0ustar pabspabs#include "WebRequest.h" #include "networkInterface.h" #include "gameControl.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/StringBufferOutputStream.h" #include "minorGems/network/SocketClient.h" WebRequest::WebRequest( char *inMethod, char *inURL, char *inBody ) : mError( false ), mURL( stringDuplicate( inURL ) ), mRequest( NULL ), mRequestPosition( -1 ), mResultReady( false ), mResult( NULL ), mSock( NULL ) { char *startString = "http://"; char *urlCopy = stringDuplicate( inURL ); char *urlStart = stringLocateIgnoreCase( urlCopy, startString ); char *serverStart; if( urlStart == NULL ) { // no http:// at start of URL serverStart = urlCopy; } else { serverStart = &( urlStart[ strlen( startString ) ] ); } // find the first occurrence of "/", which is the end of the // server name char *serverNameCopy = stringDuplicate( serverStart ); char *serverEnd = strstr( serverNameCopy, "/" ); char *getPath = strstr( serverStart, "/" ); if( serverEnd == NULL ) { serverEnd = &( serverStart[ strlen( serverStart ) ] ); getPath = "/"; } // terminate the url here to extract the server name serverEnd[0] = '\0'; int portNumber = 80; // look for a port number char *colon = strstr( serverNameCopy, ":" ); if( colon != NULL ) { char *portNumberString = &( colon[1] ); int numRead = sscanf( portNumberString, "%d", & portNumber ); if( numRead != 1 ) { portNumber = 80; } // terminate the name here so port isn't taken as part // of the address colon[0] = '\0'; } mSuppliedAddress = new HostAddress( stringDuplicate( serverNameCopy ), portNumber ); mNumericalAddress = NULL; mNetworkUpThread = NULL; mLookupThread = NULL; if( ! isNetworkAlwaysOn() ) { // start thread to make sure it is on // (start name lookup thread later, after it is on) mNetworkUpThread = new BringNetworkUpThread( inURL ); } else { // network always on // launch right into name lookup mLookupThread = new LookupThread( mSuppliedAddress ); } mSock = NULL; // compose the request into a buffered stream StringBufferOutputStream tempStream; tempStream.writeString( inMethod ); tempStream.writeString( " " ); tempStream.writeString( getPath ); tempStream.writeString( " HTTP/1.0\r\n" ); tempStream.writeString( "Host: " ); tempStream.writeString( serverNameCopy ); tempStream.writeString( "\r\n" ); if( inBody != NULL ) { char *lengthString = autoSprintf( "Content-Length: %d\r\n", strlen( inBody ) ); tempStream.writeString( lengthString ); delete [] lengthString; tempStream.writeString( "Content-Type: application/x-www-form-urlencoded\r\n\r\n" ); tempStream.writeString( inBody ); } else { tempStream.writeString( "\r\n" ); } mRequest = tempStream.getString(); mRequestPosition = 0; delete [] serverNameCopy; delete [] urlCopy; } WebRequest::~WebRequest() { // pass these to global thread destroyer, so we don't block here if( mNetworkUpThread != NULL ) { addThreadToDestroy( mNetworkUpThread ); } if( mLookupThread != NULL ) { addThreadToDestroy( mLookupThread ); } delete mSuppliedAddress; if( mNumericalAddress != NULL ) { delete mNumericalAddress; } delete [] mURL; if( mSock != NULL ) { delete mSock; } if( mRequest != NULL ) { delete [] mRequest; } if( mResult != NULL ) { delete [] mResult; } } int WebRequest::step() { if( mError ) { return -1; } if( mSock == NULL ) { // either mNetworkUpThread is NULL or mLookupThread is NULL, // but not both (lookup thread created when network up thread done) if( mNetworkUpThread != NULL ) { if( mNetworkUpThread->isNetworkCheckDone() ) { if( mNetworkUpThread->isNetworkUp() ) { // delete directly, because it is already finished delete mNetworkUpThread; mNetworkUpThread = NULL; mLookupThread = new LookupThread( mSuppliedAddress ); } else { // failed to bring network up printf( "Error: " "WebRequest failed to bring network up.\n" ); return -1; } } else { // still bringing network up return 0; } } // we know mLookupThread is not NULL if we get here if( mLookupThread->isLookupDone() ) { mError = true; mNumericalAddress = mLookupThread->getResult(); if( mNumericalAddress != NULL ) { // use timeout of 0 for non-blocking // will be set to true if we time out while connecting char timedOut; mSock = SocketClient::connectToServer( mNumericalAddress, 0, &timedOut ); if( mSock != NULL ) { mError = false; } } if( mError ) { // lookup or socket construction failed if( mNumericalAddress == NULL ) { printf( "Error: " "WebRequest failed to lookup %s\n", mSuppliedAddress->mAddressString ); } else { printf( "Error: " "WebRequest failed to construct " "socket to %s:%d\n", mNumericalAddress->mAddressString, mNumericalAddress->mPort ); } return -1; } } else { // still looking up return 0; } } int connectStatus = mSock->isConnected(); if( connectStatus == 0 ) { // still trying to connect return 0; } else if( connectStatus < 0 ) { // failed to connect mError = true; printf( "Error: " "WebRequest failed to connect to %s:%d\n", mNumericalAddress->mAddressString, mNumericalAddress->mPort ); return -1; } else if( connectStatus == 1 ) { // connected if( mRequestPosition < (int)( strlen( mRequest ) ) ) { // try to send more char *remainingRequest = &( mRequest[ mRequestPosition ] ); int numSent = mSock->send( (unsigned char *)remainingRequest, strlen( remainingRequest ), // non-blocking false ); if( numSent == -1 ) { mError = true; printf( "Error: " "WebRequest failed to connect to " "send full request\n" ); return -1; } if( numSent == -2 ) { return 0; } mRequestPosition += numSent; // don't start looking for response in same step, // even if we just sent the entire request // in practice, it's never ready that fast return 0; } else if( mResultReady ) { return 1; } else { // done sending request // still receiving response long bufferLength = 5000; unsigned char *buffer = new unsigned char[ bufferLength ]; // non-blocking // keep reading as long as we get full buffers int numRead = bufferLength; while( numRead > 0 ) { numRead = mSock->receive( buffer, bufferLength, 0 ); if( numRead > 0 ) { for( int i=0; iŌjƃXfaܽ6$\s ΢!!,1\\ܶab&^D$~2;fqp[ uoYNL$YMalˡ@kDgr^ tk/n;kxyPeUOxlS)^j2mfHp' ɝ9EEPxdmG9,Ot#̦{XQ +3UWeF `1b!IQ"03QΌ*^fpwtyz>. mY-"!1a3Ǒ ] Xqhfyϩ`''Կ:a88-|s ./Sռd]OKdm.0=khQJvd1bÀScǥBy~ ͰF={o&Gm?rv;(:ÚCh ɮç2/~맧7mn̿#<#<#<8~UB}'S9Ȍ ]fm M+vqDbDZu{Hm B+T(!$R/@OO/mm~sxSJLktJjƈBFM}o N*Tpz fP+-Z;Ӳ^TԷo !US.Mg3Az:+<۹xPBĘ}c$YKe?~8+9yg @Rǔ9c,=IkYw]bv'KF@5B!TJB35%:2tWil)r(@Z])ޅP5nGU7">`Q5DYR٤)U/绁ҘH+Sk-ffkۄ3pM1!sSfsזv1#lGKiCy8zUxoЊHf2o\&{6~}0 _ݸO}fIS-lY%EDs/@҉7щDqW UDGZyJ/{fo-m>apu`"TvUqUܽj/dYgE!@m#H E3::հoC:j.h9hb"m "A{=a"/VzHtM?u'IPg"& hf&ӫTK| q{MNCx"GJ5 qkWQZ;82W*?XHR3'i,B:<#O Fk N۶o۶ӢdnILR,\̍vŒj33 k%"3%.Z1Ƥ>pvvF%n*3@D**L<~L~uy+L`zhC8FR0ѩ̼W0Df> Z -3ωHD)lX1Bm DJl,?ax ibFĽ,K5߁-L$XUVQM)A^` JeUPN-)Tk.H$sE‰X2ȚʺW0q(10( >ڝCzR(+Z:)/Η*q@i2$<7P}!|s1{_@]Ი8ӘE&f on[kmQL4ҋJHV3pmna)l<84ZSuMJ 1Fc41F3zk2䮂~a,ڶ,aQ*@!M<,\ugnU4 ܇Y{Ku]/jff+VbQ<1)o)yֲmlkvZtZDWCԾıiɏHN031oݺe1OO!'qib,4 {c%"z{K2Fb,9,q>sx'zu]#~BX P)%C x(t!KH6`u]R͘/Z $05fϪ2p=xLڟSJ0Zo1iXR6㦵ٮ|mI5hzf*HC·YH%HDT""xwʛIԝ,H2m]8^{5"jutj9NT^8"2%X8;gv٢֟ ՝nݺe?V>jy:G{3|0I*ű8Yf5yʭ 8Z44ٽ9D>j&{9u2܏H~^?\A$ M0!A/پAq4FBXp# R6޼ys|NL8d#Y:[뽱ś= ʃ u'sS\Ym<aE8bNKx2I<؉dL)c,P/57^/oHWyvZ,QpW71v\so:/DbGK7/:^X(]D4! Wx'}?Q'Ħi'ʗh2O,Vz"jd濡)<r24W%yqjH ק w#( c18p|[/CCARr yuxKV>p¸է[ڳo$'} 3ޒvafzjqs̙Oݻwr޽.yS)Ke w0hW!-Ltggg9 #f>b挋IW3R eRQ=ϽVk3fx 't}7}7}xʋOP4 eڕ1$k{-yH]1N)I)cXLf|+z V+#j.##;ֻDy -ck,iDoR a]4;P01j$4gwǎIۈXd]]Wuu=nuKSIIENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/plus.png0000644000175000017500000000240211131427744023776 0ustar pabspabsPNG  IHDR szzbKGD pHYs  tIME9~|tEXtCommentCreated with The GIMPd%nfIDATX=r% ?}G#Y*R2 g -‰2*eDdIi򽾷8h g*O gȟH.#!"}i쯿}On60Ok %AOOoYn;l6Dߓwwq|L޽B^K-:0`},O;{QAƬ5}x8lK 䗗Zaag ЙtNsƑٌ6M-~vFB^_#Ln(]GjT[zy=:[螓=;C[ᴈj3֙DZ+@DR͘"ػ08^qvv$gY>R`t}Oɪ56!RAW=20;t*{v"LR͘w;s)>g@&dʌ;eɰ֪K|D7Lzb`F᎛DkcџKA{FͰiR8dc"lToK.N0iҀZ1o r~! O7dAZRj)눲ElqAcNdΤf,'~G5l1gX8.wt-UJ[d! YJډ`}n6KӄD }WX}1# t&-]ZגLӗqu;??.R9!Dl3;3Ҍ\^0 4%K!JU#ZS-S{{X≍}&졛"Za[#Z#>_;41Ռ*LLDM2E^]fٻSyZn_wB}-T9Н*[UL'F E`Ό;U#xkZk?KN2;̙L- TWZŊ٩21׊ݗ<7 t֮a L~O0LdǫViG_j==>ACDB=6-#  &-48:97533579:84-&  %*-/.-+**+-./-*%  !#$$#! !#$$#!                      #%&&%$!  "',024431.*&   %-4:?CDEDA>93,%  %/9BIOSTUTQMG@8/&  "-9DOW^bddc`\VNE:/$  '4BOZdjoqqpmicZPD8,   ,:IWdmtxzzxvrmdZN@2&  #0?O^jtz}~~}{xslbUG8*  %3CSanv|~~}|zvpgZL=.! &5EUcow{||{zzywrj^P@1$  '6FUdnuxywvv urk`RC3%  (6FVcmsuurqpqssqk`SD4&  (6FUbkpqpmkklopoj`TE5'  (6FUajnoliggilnmi`TE6'  (6ET`hlliecceiklh_SE6'  (6ES_gjjgc``cgjjg_SE6'  '6ES_fiiea__aehif^SE6'  '5DR^ehgd`]]_cghe]RD5'  '4CQ\dfeb^[[^befd\QC4'   .      ,    ,            .      ,    ,            .      ,    ,          O &3BOZadc`\YY\`cdaZOB3&  $1?LW^a`\YVVY\`a^WL?1$  #/==>ACDB=6-#  &-48:97533579:84-&  %*-/.-+**+-./-*%  !#$$#! !#$$#!                        #%&''&%#   "',03566530,'"  %-4;@CFGGFC@;4-%  %/9BIOSVWWVSOIB9/%  "-9DOX^cfggfc^XOD9-"  '4BOZdkprttrpkdZOB4'  ,:IWdnty{||{ytndWI:,  #0?O^jtz~~ztj^O?0#  %3CSanw||wnaSC3%  &5EUcow{}}||}}{wocUE5&  '6FVdnuyyxwwxyyundVF6'  (6FVcmsuusrrsuusmcVF6(  (6FUblqrqnmmnqrqlbUF6(  (7FUbkopnkiiknpokbUF7(  (6FUajnnliggilnnjaUF6(  (6FUajnnliggilnnjaUF6(  (7FUbkopnkiiknpokbUF7(  (6FUblqrqnmmnqrqlbUF6(  (6FVcmsuusrrsuusmcVF6(  '6FVdnuyyxwwxyyundVF6'  &5EUcow{}}||}}{wocUE5&  %3CSanw||wnaSC3%  #0?O^jtz~~ztj^O?0#  ,:IWdnty{||{ytndWI:,  '4BOZdkprttrpkdZOB4'  "-9DOX^cfggfc^XOD9-"  %/9BIOSVWWVSOIB9/%  %-4;@CFGGFC@;4-%  "',03566530,'"   #%&''&%#                     #%&''&%#   "',03566530,'"  %-4;@CFGGFC@;4-% '                      Q         '                      Q         '                      Q          %/9BJPTWXXWTPJB9/%  "-9EOX_dghhgd_XOE9-"  (4BO[elqtuutqle[OB4(  -;JXeow|~~|woeXJ;-  #1@P`mw~wm_P@1#  %4DUer}|rdTD3%  '6GXhvugWF5'  (8IZkxvhXG6'  )9J\m{vhXG6'  *:K^n|ugWF5'  *:L_p~}rdTD3%  *:L_pxm`P@1#  *:M_pzqfYJ;-  *:L_p}~wpg\PB5(  *:K]m{zsld[QE9-"  )8I[jv~{tme^VMD:/%  '6GWepvxuog_VNG?7.&  &4CR_innjcZPG?81*#  $1?MYaec^VMC:2+$  !-:FQXZXRJ@6-%  (4?HMOMG>5+#  #-7>CDA;3+"  &.48860)"  %*--+&    "#!                   #%&''&%#   "',03566530,'"  %-4;@CFGGFC@;4-%  %/9BIOSVWWVSOIB9/%  "-9DOX^cfggfc^XOD9-"  '4BOZdkprttrpkdZOB4'  ,:IWdnty{||{ytndWI:,  #0?O^jtz~~ztj^O?0#  %3CSbnw||wnbSC3%  &5EUcow|}}|wocUE5&  '6FVdovyzyxxyzyvodVF6'  (7FVdntwvtsstvvtncVF6'  (7FVcmrtsqooprsrlbUF6'  (7FVclrsqommnprpkbTE6'  (7FVclqsqomlnpqpjaTE5'  (7FVcmrtsqooprrpjaSD5&  (7GVdnuwwusstuurkaSD4&  '6FVdovz{zyyzxtlaSC3%  &5EUdpx}|wnaRB2$  %3CSbox~xnaQA1#  #0@O^kv}yn`P?0"  ,;JXepx~wl^N=.! (4BP\gpv{{rgYJ:+  "-9FQ[dkptwxvrj`SD5(  %0:DMU\bfikjf_VJ=0$  &.7?FLQVY[[XRJ@4)  #*06;@DHJJHC=5+"          1                            1                            1                    #(,04799850)"  "%')*)'#                    #%&''&%#   "',03566530,'"  %-4;@CFGGFC@;4-%  %/9BJPTWXXWTPJB9/%  "-9EOX_dghhgd_XOE9-"  (4BO[elqtuutqle[OB4(  -;JXepw|~|wpeXJ;-  #1@P`mw⅃wm`P@1#  %4DUer}㈄}reUD4%  '6GXhv㊇vhXF6'  (8IZkx㌉xjZH7(  )9J\m{=zl[I8(  *:L^o}{m[I8(  *:L_q|m[I7'  *;M`q|lZG6&  *;M`r{kXE4%  *;M`ryhUB1# *:L_pudQ?.   )9J\m|~o^L:+  (7HYiwwhXF5'  &4DUdpzyn`P@0#  $1@O]iqwz||zvoeXI:+  !.;IU_gknoponjd[OA3&  )5ALU[_abba]XPE9-!  $.9BIORSTTSPKD;1&  '07>BDEFFEC>81(  &-25788752-'   #&)*++*)&#                       #%&&O%#   "',024432/,(#  %-4:?BCDC@=83-&  %/9AINRSSQNJD>6-%  "-9DOW]aba_[UOG>4*!  '4BOZcjmmkhc]VMC9.$  -;JXdmsvusnhaYPE:/%  #1@P_ktz{zvpibYOE:/$  %3CTcpy~~|wpiaXND9.$  &5FWfs{|vog^ULB7,"  '6GXgt||vnf^UKA7,#   ڿ             A                 ڿ             A                 ڿ             A                '6GXht}}wph`WNC9.$  '6FWgt}ztle\SH=2'  &4EVes|~ysldZPD8,!  $2BSbpzztmdYL?1%  "/?O^lw}vmbTF7*   ,;JYgs|~uj\L=.! )7FTbnx|pbRA1#  &3AO]is{tfUD4%  $0>KYeoxwhWF5&  ".;HUblu}vhWE5&  !,9FS_js{teUD3%   +7DQ\gpw}ynaQ@1#  )5AMXbkrw{}|xqfYJ;-  &1=HR\cinqrqmf\PB5(  #-7AJSY_beec_YPE9-"  &/8@GLQTUUSPJB9/%  '.4:>ADEDC?;4-%  #(-0345430,("   #%&&%#                    "%&''&%"  $*/256652/*$   (/7=BEGGEB=7/(   '0:CKQVXXVQKC:0'  "-8CNX`ehhe`XNC8-"  %1=JWbkquuqkbWJ=1%  &2@N\hrz~~zrh\N@2&  %1?N]jv~~vj]N?1%  ".==>ACDB=6-#  (3=FKNMJGEEGJMNKF=3(   ,8DMSVUROMMORUVSMD8,   #/==>ACDB=6-#  (3=FKNMJGEEGJMNKF=3(   ,8DMSVUROMMORUVSMD8,   #/LX`efecaacefe`XL>0#  !.;IT]ceedccdeec]TI;.! 6         1         (   6         1         (   6         1         (    *7DOY_bdccdb_YOD7*  &2>ISZ_bccb_ZSI>2&  !,7BLTZ^`aa`^ZTLB7,!  &0;DMTY\]]\YTMD;0&  )2BEEB>81)"   '-369963-'   #(+--+(#   ""                        !#$$#! !#$$#!  %*-/.-+**+-./-*%  &-48:97533579:84-&  #-6=BDCA>==>ACDB=6-#  (3=FKNMJGEEGJMNKF=3(   ,8DMSVUROMMORUVSMD8,   #/KV_gknppnkg_VK>1%  %1>JV_fknoonkf_VJ>1%  %2>KV_ejlmmlje_VK>2%  '3@LV^dhijjihd^VL@3'  (4ALV^beffeb^VLA4(  (5ALU\_``_\ULA5(  (5@KSX[[ZYYZ[[XSK@5(  '3>HOSTTRQQRTTSOH>3'  %/:BILMKJHHJKMLIB:/%  !*3;@CCB@??@BCC@;3*!  %,37997644679973,%  $)-..-+**+-..-)$   #$$"! !"$$#              @ fat     !7 WS_k )    R    )    R    )    R    )    R    R        )R        )R        )R        )(        \        ((        \        ((        \        ((        \        ()        T    )        T    )        T    )        T            R    .        R    .        R    .        R    .)    R)    R)    R)    RV    )V    )V    )V    )()()()()@ sharp       9 e}J   J   J   J       J     J     J     JI      II      II      II      IJ      J      J      J             N       N       N       OJ   J   J   J   WJ WJ WJ WJIWWJIWWJIWWJIWWJ@  New Layer      ƿ NjǗǣ  +;K[k{@primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/Button.cpp0000644000175000017500000000723311144115746024273 0ustar pabspabs#include "Button.h" #include "numeral.h" #include "minorGems/util/stringUtils.h" #include #include Button::Button( int inX, int inY, char *inString ) : mX( inX ), mY( inY ), mString( stringDuplicate( inString ) ), mSpace( inX, inY ), mVisible( false ), mFadeProgress( 0 ), mLastString( NULL ), mStringTransitionProgress( 1 ) { } Button::~Button() { delete [] mString; if( mLastString != NULL ) { delete [] mLastString; } } void Button::setString( char *inString ) { if( mLastString != NULL ) { delete [] mLastString; } mLastString = mString; mString = stringDuplicate( inString ); mStringTransitionProgress = 0; } void Button::forceString( char *inString ) { if( mLastString != NULL ) { delete [] mLastString; } mLastString = mString; mString = stringDuplicate( inString ); mStringTransitionProgress = 1; } char Button::isInside( int inX, int inY ) { // slightly bigger than underlying grid // to make it easier to press if( fabs( inX - mX ) < 23 && fabs( inY - mY ) < 23 ) { return true; } return false; } void Button::setVisible( char inIsVisible ) { mVisible = inIsVisible; } void Button::forceVisible() { setVisible( true ); mFadeProgress = 1; } void Button::forceInvisible() { setVisible( false ); mFadeProgress = 0; } void Button::step() { if( mVisible && mFadeProgress < 1 ) { mFadeProgress += 0.1; if( mFadeProgress > 1 ) { mFadeProgress = 1; } } else if( !mVisible && mFadeProgress > 0 ) { mFadeProgress -= 0.1; if( mFadeProgress < 0 ) { mFadeProgress = 0; } } if( mStringTransitionProgress < 1 ) { mStringTransitionProgress += 0.2; if( mStringTransitionProgress > 1 ) { mStringTransitionProgress = 1; } } } Color buttonStringColor( 76/255.0, 76/255.0, 255/255.0 ); void Button::draw() { if( mFadeProgress > 0 ) { mSpace.drawGrid( mFadeProgress ); // additive to support smooth cross-blending glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE ); float alpha; if( mStringTransitionProgress > 0 ) { alpha = mFadeProgress * mStringTransitionProgress; if( strlen( mString ) < 3 ) { drawStringBig( mString, center, mSpace.mX, mSpace.mY, &buttonStringColor, alpha ); } else { drawString( mString, center, mSpace.mX, mSpace.mY, &buttonStringColor, alpha ); } } if( mStringTransitionProgress < 1 ) { alpha = mFadeProgress * ( 1 - mStringTransitionProgress ); if( strlen( mString ) < 3 ) { drawStringBig( mLastString, center, mSpace.mX, mSpace.mY, &buttonStringColor, alpha ); } else { drawString( mLastString, center, mSpace.mX, mSpace.mY, &buttonStringColor, alpha ); } } glDisable( GL_BLEND ); } } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/BringNetworkUpThread.cpp0000644000175000017500000000161411142203151027047 0ustar pabspabs#include "BringNetworkUpThread.h" #include "networkInterface.h" #include "minorGems/util/stringUtils.h" BringNetworkUpThread::BringNetworkUpThread( char *inURL ) : mURL( stringDuplicate( inURL ) ), mNetworkCheckDone( false ), mResult( false ) { start(); } BringNetworkUpThread::~BringNetworkUpThread() { join(); delete [] mURL; } char BringNetworkUpThread::isNetworkCheckDone() { mLock.lock(); char done = mNetworkCheckDone; mLock.unlock(); return done; } char BringNetworkUpThread::isNetworkUp() { mLock.lock(); char result = mResult; mLock.unlock(); return result; } void BringNetworkUpThread::run() { char result = makeSureNetworkIsUp( mURL ); mLock.lock(); mNetworkCheckDone = true; mResult = result; mLock.unlock(); setFinished(); } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/secureSalt.h0000644000175000017500000000004511174117464024573 0ustar pabspabs#define secureSalt "secret_path_six" primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/spriteBank.h0000644000175000017500000000162011133723765024565 0ustar pabspabs#ifndef SPRITE_BANK_INCLUDED #define SPRITE_BANK_INCLUDED #include "minorGems/graphics/Color.h" #define numSprites 18 enum SpriteHandle { gridLineTop = 0, gridLineBottom, gridLineLeft, gridLineRight, plus, piece, pieceHalo, pieceCenter, pieceBrightHalo, pieceBrightCenter, numerals, numeralsBig, abcdefghijkl, mnopqrstuvwx, yzplus, abcdefghijkl_big, mnopqrstuvwx_big, yzplus_big }; void initSpriteBank(); void freeSpriteBank(); // subsection selects a particular y region of the underlying sprite texture void drawSprite( SpriteHandle inSpriteHandle, float inCenterX, float inCenterY, float inXRadius, float inYRadius, Color *inColor = NULL, float inAlpha = 1.0, float inSubsectionOffset = 0, float inSubsectionExtent = 1 ); #endif primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/GridSpace.cpp0000644000175000017500000003425511156476557024702 0ustar pabspabs #include "GridSpace.h" #include "spriteBank.h" #include "numeral.h" #include "gameControl.h" #include #include extern char colorblindMode; GridSpace::GridSpace( int inX, int inY ) :mX( inX ), mY( inY ), mActive( false ), mActiveMarkerVisible( true ), mVisited( false ), mChecked( false ), mMarkedForClearing( false ), mScore( 0 ), mAddToGlobalScore( true ), mDrawColor( NULL ), mPieceColor( NULL ), mPieceColorIndex( -1 ), mLastColor( NULL ), mPieceInvertedColor( NULL ), mLastInvertedColor( NULL ), mColorShiftProgress( 0 ), mBrightHalo( false ), mBrightHaloProgress( 0 ), mActiveProgress( 0 ), mScoreFade( 0 ), mScoreSent( false ), mSavedColor( NULL ), mSavedActive( false ), // no pause to start... set counter way over limit mPauseStepsAfterAnimationDone( 999 ) { for( int n=0; n<4; n++ ) { mNeighbors[n] = NULL; } } GridSpace::~GridSpace() { if( mLastColor != NULL ) { delete mLastColor; } if( mPieceColor != NULL ) { delete mPieceColor; } if( mDrawColor != NULL ) { delete mDrawColor; } if( mSavedColor != NULL ) { delete mSavedColor; } if( mLastInvertedColor != NULL ) { delete mLastInvertedColor; } if( mPieceInvertedColor != NULL ) { delete mPieceInvertedColor; } } char GridSpace::isInside( int inX, int inY ) { if( fabs( inX - mX ) < 20 && fabs( inY - mY ) < 20 ) { return true; } return false; } void GridSpace::setColor( Color *inColor ) { if( mLastColor != NULL ) { delete mLastColor; delete mLastInvertedColor; } mLastColor = mPieceColor; mLastInvertedColor = mPieceInvertedColor; mPieceColor = inColor; mPieceColorIndex = ::getColorIndex( mPieceColor ); mPieceInvertedColor = NULL; if( inColor != NULL ) { mPieceInvertedColor = inColor->copy(); int i; float valueSum = 0; for( i=0; i<3; i++ ) { float value = (*mPieceInvertedColor)[i]; valueSum += value; } // invert the estimated brightness float setAllTo = 1; if( valueSum > 1.5 ) { setAllTo = 0; } for( i=0; i<3; i++ ) { (*mPieceInvertedColor)[i] = setAllTo; } } mColorShiftProgress = 0; } void GridSpace::saveState() { if( mSavedColor != NULL ) { delete mSavedColor; } if( mPieceColor != NULL ) { mSavedColor = mPieceColor->copy(); } else { mSavedColor = NULL; } mSavedActive = mActive; } void GridSpace::rewindState() { mActive = mSavedActive; if( mSavedColor != NULL ) { setColor( mSavedColor->copy() ); } else { setColor( NULL ); } } Color *GridSpace::getSavedColor() { return mSavedColor; } Color gridLineColor( 1, 1, 1 ); void GridSpace::drawGrid( float inAlpha ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); drawSprite( gridLineTop, mX, mY, 32, 32, &gridLineColor, inAlpha ); drawSprite( gridLineLeft, mX, mY, 32, 32, &gridLineColor, inAlpha ); if( mNeighbors[bottom] == NULL ) { drawSprite( gridLineBottom, mX, mY, 32, 32, &gridLineColor, inAlpha ); } if( mNeighbors[right] == NULL ) { drawSprite( gridLineRight, mX, mY, 32, 32, &gridLineColor, inAlpha ); } if( mActiveProgress > 0 ) { drawSprite( plus, mX, mY, 16, 16, &gridLineColor, inAlpha * mActiveProgress ); } glDisable( GL_BLEND ); } Color scorePipColor( 255/255.0, 255/255.0, 160/255.0 ); void GridSpace::drawPieceCenter( float inAlpha ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); //glBlendFunc( GL_SRC_ALPHA, GL_ONE ); if( mDrawColor != NULL && mDrawColor->a > 0 ) { drawSprite( pieceCenter, mX, mY, 32, 32, mDrawColor, mDrawColor->a * inAlpha ); if( colorblindMode ) { char stringToDraw[2]; stringToDraw[1] = '\0'; if( mPieceColor != NULL ) { stringToDraw[0] = getColorblindSymbol( mPieceColor ); drawStringBig( stringToDraw, center, mX, mY, mPieceInvertedColor, mColorShiftProgress * inAlpha ); } if( mLastColor != NULL ) { stringToDraw[0] = getColorblindSymbol( mLastColor ); drawStringBig( stringToDraw, center, mX, mY, mLastInvertedColor, (1 - mColorShiftProgress) * inAlpha ); } } } if( mPieceColor == NULL && mScore > 0 ) { float pipAlpha = mColorShiftProgress * mScoreFade * inAlpha; if( pipAlpha > 0 ) { drawScorePip( mScore, mX, mY, &scorePipColor, pipAlpha ); } } glDisable( GL_BLEND ); mPauseStepsAfterAnimationDone++; } void GridSpace::drawPieceHalo( float inAlpha ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); //glBlendFunc( GL_SRC_ALPHA, GL_ONE ); if( mDrawColor != NULL && mDrawColor->a > 0 ) { drawSprite( pieceHalo, mX, mY, 32, 32, mDrawColor, mDrawColor->a * inAlpha ); if( mBrightHalo && mBrightHaloProgress > 0 ) { //for( int i=0; i<4; i++ ) { drawSprite( pieceBrightHalo, mX, mY, 32, 32, mDrawColor, mBrightHaloProgress * mDrawColor->a * inAlpha ); //} Color white( 1, 1, 1, 1 ); glBlendFunc( GL_SRC_ALPHA, GL_ONE ); drawSprite( pieceBrightCenter, mX, mY, 32, 32, &white, mBrightHaloProgress * mDrawColor->a * inAlpha ); } } glDisable( GL_BLEND ); } void GridSpace::step() { if( mDrawColor != NULL ) { delete mDrawColor; mDrawColor = NULL; } if( mLastColor != NULL || mPieceColor != NULL ) { Color *blendA; if( mLastColor == NULL ) { // piece color with total transparency blendA = mPieceColor->copy(); blendA->a = 0; } else { blendA = mLastColor->copy(); } Color *blendB; if( mPieceColor == NULL ) { // last color with total transparency blendB = mLastColor->copy(); blendB->a = 0; } else { blendB = mPieceColor->copy(); } mDrawColor = Color::linearSum( blendB, blendA, mColorShiftProgress ); delete blendA; delete blendB; if( mColorShiftProgress < 1 ) { if( mLastColor != NULL && mPieceColor != NULL ) { // slow shift between colors mColorShiftProgress += 0.1; } else { // faster shift to on or off mColorShiftProgress += 0.2; } } if( mColorShiftProgress > 1 ) { mColorShiftProgress = 1; } } if( mBrightHalo ) { if( mBrightHaloProgress == 1 ) { if( mPieceColor != NULL ) { setColor( NULL ); } else if( mColorShiftProgress == 1 ) { // completely faded out mBrightHaloProgress = 0; mBrightHalo = false; } } else { // slower than color switch time mBrightHaloProgress += 0.1; if( mBrightHaloProgress > 1 ) { mBrightHaloProgress = 1; } } } if( mScoreFade > 0 && !mBrightHalo && mColorShiftProgress == 1 ) { // only add to score once if( !mScoreSent ) { if( mAddToGlobalScore ) { addToScore( mScore ); } mScoreSent = true; } mScoreFade -= 0.075; if( mScoreFade < 0 ) { mScoreFade = 0; // done drawing score mScore = 0; } } // only allow marker to grow in visibiltiy if visible flag set if( mActive && mActiveMarkerVisible &&mActiveProgress < 1 ) { mActiveProgress += 0.2; if( mActiveProgress > 1 ) { mActiveProgress = 1; } } else if( !mActive && mActiveProgress > 0 ) { mActiveProgress -= 0.2; if( mActiveProgress < 0 ) { mActiveProgress = 0; } } } char GridSpace::isAnimationDone() { if( mDrawColor == NULL ) { return true; } else if( mColorShiftProgress == 1 && ! mBrightHalo && mScoreFade == 0 ) { // animation done... if( mPauseStepsAfterAnimationDone < 4 ) { // ...but not enough pause steps return false; } return true; } // animation still in progress // set up a pause for after it ends mPauseStepsAfterAnimationDone = 0; return false; } char GridSpace::colorMatches( Color *inColor ) { if( isEmpty() ) { if( inColor == NULL ) { return true; } else { return false; } } else if( inColor != NULL ) { return inColor->equals( mPieceColor ); } else { return false; } } Color *GridSpace::checkSurrounded() { mVisited = true; mChecked = true; if( isEmpty() ) { return NULL; } int n; // first, make sure all neighbors have our color or a single other color Color *surroundColor = NULL; for( n=0; n<4; n++ ) { GridSpace *space = mNeighbors[n]; if( space != NULL ) { if( space->isEmpty() ) { // neighbor empty, not surrounded if( surroundColor != NULL ) { delete surroundColor; } return NULL; } if( ! space->colorMatches( mPieceColor ) ) { if( surroundColor == NULL ) { surroundColor = space->getColor(); } else if( ! space->colorMatches( surroundColor ) ) { // surrounded by more than one color if( surroundColor != NULL ) { delete surroundColor; } return NULL; } } } } // have surround color, or NULL if surrounded by like-colored pieces // and edges // no neighbors are empty // check each like-colored, unvisited neighbor for( n=0; n<4; n++ ) { GridSpace *space = mNeighbors[n]; if( space != NULL ) { if( ! space->mVisited ) { if( space->colorMatches( mPieceColor ) ) { Color *c = space->checkSurrounded(); if( c == NULL ) { if( surroundColor != NULL ) { delete surroundColor; } return NULL; } if( ! c->equals( mPieceColor ) ) { if( surroundColor == NULL ) { surroundColor = c; } else if( ! surroundColor->equals( c ) ) { delete surroundColor; delete c; // color mismatch return NULL; } else { delete c; } } else { delete c; } } } } } // done checking neighbors... if we got here, we have our surrounding // color... or NULL if surrounded by edges if( surroundColor == NULL ) { return mPieceColor->copy(); } else { return surroundColor; } } void GridSpace::flipToClear() { mBrightHaloProgress = 0; mBrightHalo = true; mScoreFade = 1; mScoreSent = false; // flip any other-colored neighbors (if they are not also clearing) for( int n=0; n<4; n++ ) { GridSpace *space = mNeighbors[n]; if( space != NULL ) { if( ! space->isEmpty() && ! space->mMarkedForClearing && ! space->colorMatches( mPieceColor ) ) { space->setColor( mPieceColor->copy() ); } } } } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/numeralsBig.png0000644000175000017500000002247311133407532025270 0ustar pabspabsPNG  IHDR InbKGDC pHYs  tIME cD IDATx}ͪ$IDf:UgjiF]F Bziz\B Ի@B" D/4 Qi:?cZ3/ OS<f}fЈ"V^gtlGp⨎{XU(N 6=.t#O: V#UO:f..vO>``l66 D o:=}U'J'܁^;"2wk=2䪻]^^vЍu]CsΤ 9r1QއqCu# \^^ꉉew/w-(Tw?ǨFk,Kx/UF=Vdcz\M:j"BS>SWSrr,Tw7772 rΓk+SːzRrc9cL1&Q"!"vrAg2y1F Zkr3)%ԏ Z##a{眩$i9T?D""km-E I8c29g֦F0 򽔒tJ>C>zII/߱N)1SJ_'7r9'_#puuUf:HOX~5u&ט2&RJtQW^HX~%^n#9X`]2Ɛ, cL鄜Kν؁}zs-1猼C$sHZ2 \2j""LJLVC=管;@j"-Tfgu"Z4s94+ YYٍ^_1&ׂHjnưD1 YNFD`AތjsG@,s.!n/?ADQ ގZ|Z^sQqss///'ڭ6ƃeY+%p줮L:=2kLM >djVSҁ5|h8i-E1&a=+xyy8Ru1015LƛpyyYw*әf/85=}4@|q8y ?y(~@NVtk;p1¥>Rko#P`|kFa[и_݁2G90jo>x;4ndњWQ0+޼{N}0 av0lqݝD^zeFTgCD ""ՆG򙉧1NDM GV\nh wdIGD[DwL75׮l,2 |qou1 q"Ze[! q]u6sS~$i!T'́pAPez 9p8dwWVhs*|S70+ݠ<k-ZkQƇEw?r9'V3}o>} o߾<|z@5^}8nE, g}v""%0h"4R"C9?avi:粵YMl%$s}P{NwD$9?jc{[D~n{߼y^x44vLЎcr΅MkpYs)c1֎n\}x6S@AuR*l+Q?&mNOB#7&QS:kE$’g`1/CdkM E"1#:D9g!I=j%z _~tR<t)MJiR䜻O)a؁"2%'?ӻI"l61'ι'D%!"En7J-9PO@ 6>c p pε+DZ{ctq_3Ɣg-~"}Ji/br%+2ˬ!-ת-s'vTpН8T:4io7a |soz e) na"#hd6 Cyi6noo 8K1'C+BN6kܨuXO[,_ v4fKyiD eKH<'fE1ŗ/_b[Dfdl>87؏8v;wprn;;";A }P"،|ýl9! u1&}1Ql6=}!"(tS7(5zBFmu]g8dƆm:ح6L7Mm$bG|X~ pN1Ҍ1:[ǀUv-H9 V.Au?yqµ8!̓?9\۷cCpq?Op{6F'ĆxM;":n{nm;RJ;M 1FZ).7Ev-/Jh- gkVutQЭ }Jcxd շٸc F30 @ffjsVlȔ8al6 R!/F+Qb+ߔءZ%,yZ1Y#4(4 )U doP7F_~s$<_K ev!/H%tιp Mtr0p'fɌ<'@):P63b`!ADJN=dM1d%D̕ߠ I 5cL4E\ !]3{_56(rl bui ` Uމ@:hh9ѱ܂ VIDRJ6kd8" ιuqDn1Q*MIjtNU\bpۆeC{>Ӱl7oUCnqDt7xo0! /^p?En8;6`޿o?"'O$Ř\ȌIKg$ ݵPҷoZ{v- pv;sTվn>|pv'&XOhh.CGsssc qsB["*6 80 55kww]\\lqzc=GcEzuoOhdv.\[F ⎱azц6 d~5P9 ZSi[gIh_%su{&b~B t{&;9ˉsιrQ Y\\:)vF3?!`6 2!!Jv+ʊqY{6 c`dN( 8w1j{qr :qknz \]]0 B\e&Fg8΢dbe!35sR]sv|Xe#de^%#" KlKF?Τ<9DHyCq̬-S+E"_V972P['=9gNV ;B-j٬J7l?kmGDZHEL[=< A. paģfI)2"&LwGÖc".8ODZ[Xu̢Xr0D%;eK]/~ n(':"?}@5 /иOvIXRey{YDO/yՉ I#m+x%cr#Gp'ltZ`";#$ dTSQyTWFʚh[bhx~݁46:ܽn9SJ1?>N6ךp 9o}/&x޽{eA7o2cA'_y<qȘCH  Xف'vq@ W\?K|:&֟{"yKE0A;#nP#uL-B ugh 'hd:&P%K~v 3i,Uţv\nq,'..s֌#;Ge`2-k݁IZ1hKDq藍1hD5Nsl"x:#_mW @D!A(լ\g똈Rš2"N $yU鈘ݿ1"zBDu0:Q"*ٻ{"hZE_w̼1kH2Diz^:FX`LǓaJ!:U vu(,Śr1Fq cTya1p2 @&slT|i!)`Q Nǣ8T찊# )%o߅p?5%}–S54P7 34Pホℵd7Eut7NF 1B+duQ'Zcp',1#̫`_N )LsM[oEp.SiED4MERŭ:XW)k.+] kVnQ].8;jxU$\'E1$D[jP[$>Ǭ(>H=$cL`Xl +Mp.lPK8DCN,^VF"La#ܳr Bv 'l'Ԋn*ڃpBDCsN`ۑ= U8:x9ǚȉW:y#{BTy Q䜋!]t$p6?a9wlt. DZ[l8qnueb0'O~;;>gQq>'# Qfhz?Ox{{1%?!": !8pQQ2FѦ$? \^^>8?a:POȠcFOK)6DTEKuLPiB9"Wg>٧'ӂku\{U~2y'<`Ox3)GmRJ?X. Ј?]K+?;"HRˬl\MV`%9^]ektb|r6sGb@~MCE.YϿw~,l Hc v6f۷o#Y0 8}1D4 c!;L1LDJ\Rچr 8.Ld(=q K|/fh D9p¥r_ \sj̇EpKCPn|2 \{wE%[fƈ:&-e5U,@DVKB#w%܏CLBA%&]sj$X5N'0w0a^G5RcD 5 ?؆:&AUuLtp)sdK46?R@꘤J L+Rkh¤2 Cb_*I;IϱZ'##PDs\Tssqj;WDs-12G>]+e32k&4⹪ɁV[ ~:>3 TVh)Ƙ!)yu;9EK'T;>UYIDAT\Kizv'AB4oDĠJ7똬<:l,hwSkk, D5 ˗|B5?~>!93'< ON@֢d8Ox 8'!-"S80 ~xj E\?SU8:) cSJN\O %&ap`2  ?*B(׹8^︵IYI3.d"xCН?'l̘CʆaDWSjXQ޾}[6 U5rrhSHkpBzy3?!q)+[ gj s'\ȹF,[F9^ +8bU'4/):SC {6V FŤ3 JڔK=ĬnKnnqQH//OqBkmw%WYЫYnb"%"鈜q+VaKgc:d7$;w~KAEО[8Yh_L2N-TVpDu" c "uzkAI BEO@x1p?tSvúmǫ4\!1+K'őů˰ r篖Іɹ۹۹۹۹۹۹۹۹۹۹۹۹۹۹۹۹۹I = *RIENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/common.h0000644000175000017500000000042311130717257023747 0ustar pabspabs#ifndef COMMON_INCLUDED #define COMMON_INCLUDED #include "minorGems/graphics/Image.h" //#include // reads a TGA file from the default ("graphics") folder Image *readTGA( char *inFileName ); Image *readTGA( char *inFolderName, char *inFileName ); #endif primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/yzplus_big_working.xcf0000644000175000017500000002707711133777227026763 0ustar pabspabsgimp xcf file (nZF2  BB$gimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) #(K-A blur 12     s "      &                           &                           &                                N    !#$$#! !#$$#!  %*-/.-+**+-./-*%  &.48:98544589:84.&  #-6>CEEB@>>@BEEC>6-#  (3>GMOOMJHHJMOOMG>3(   ,9EOVYYWTRRTWYYVOE9,!  #0=JU]ab`]\\^`bb^VK>0#  %2AO[dijifeegikje\PA3%  &4CR_ioqponnprsqkaTE5'  &5DTbltwxxwxz{{xqfXG7(  &5EUcow|~~vjZI8)  %4DTcpyzm]K:*  $2ARaoy~p_L:*  "/>N^lwq`M;*   ,;JYgs}r`M;+  )7FTbnyr`M;*  &3AP]jt}q_M:*  $0>KYepy~o]K9)  ".;HVbmv~{l[I7(  !,9FS_jt|vhWF5&   +7DQ]gpx~{pbRA2$  )5AMXbkrw{}|yrgZK<-  &1=HR\cjnqrqmf\PC5(  #-7AJSY_beec_YPE9-"  &/8@GLQTUUSPJB9/%  '.4:>ADEDC?;4-%  #(-0345430,("   #%&&%#                     #%&&$"   #(,0244.30,'"  &-39=ACDDB?:4-%  %.6>EKORTTSOIB9/%  !*4>GOV\`cdb^XOE9-"  #.9CNW_eknpole[OB4'  $/:FQ[dkrwyyvoeXI:,  $.:EQ[enu{}vl^O?/"  ",8COZenw~{pbRB2#   *5AMXcmw~|rdSB2$  )4@LWcmv~{qbRA1#  )5AMYdnw~xm_O>/! !,8DP\gqx~|thZJ:,  %0=JVbltz~|vmaSD5'  *7DQ^irx|~|xpfZL=/#  #/=LZfpx|~|xri^QD7*  '5DSamv|~ztlbVJ=0%  ,:JZht|~xqg\PD8,! !/>O_mx~wndYMA5)                                                                      / #1ARbq{~vmcWL@4)  $2BSdr|~wmcXMA5*   #2BRbp{~wneZOC8,"  "/?O^lv}{une[QE:.$  ,:IXeovyywrkd[QF:/$  '4BO[elopnke_WNC9.#  "-9EOX^bdc`\VOG>4*!  %/9BIOSTTROKE>6.%  %-4:?BDDCA=93-&  "',034420,(#   "$&&%#                  "&((&"  !(.3663.(!  #+4 Panel::Panel( int inW, int inH ) : mW( inW ), mH( inH ), mFadeProgress( 0 ), mVisible( false ), mCloseButton( 19 + 21, 19 + 21, "back" ) { mCloseButton.setVisible( false ); addButton( &mCloseButton ); } Panel::~Panel() { } void Panel::setVisible( char inIsVisible ) { mVisible = inIsVisible; int i; for( i=0; isetVisible( mVisible ); } } void Panel::forceVisible() { setVisible( true ); mFadeProgress = 1; int i; for( i=0; iforceVisible(); } } void Panel::forceInvisible() { setVisible( false ); mFadeProgress = 0; int i; for( i=0; iforceInvisible(); } } char Panel::pointerUp( int inX, int inY ) { int i; char somePanelVisible = false; // process in reverse order // since higher index panels are drawn on top, // we should look for button presses on them first for( i=mSubPanels.size() - 1; i>=0; i-- ) { Panel *p = *( mSubPanels.getElement( i ) ); if( p->isVisible() ) { somePanelVisible = true; // only pass pointer clicks to fully-visible panels if( p->isFullyVisible() ) { char consumed = p->pointerUp( inX, inY ); // stop as soon as consumed if( consumed ) { return true; } } } } if( !somePanelVisible ) { if( mCloseButton.isInside( inX, inY ) ) { // inform subclass of close closePressed(); setVisible( false ); return true; } } return false; } void Panel::step() { if( mVisible && mFadeProgress < 1 ) { mFadeProgress += 0.1; if( mFadeProgress > 1 ) { mFadeProgress = 1; } } else if( !mVisible && mFadeProgress > 0 ) { mFadeProgress -= 0.1; if( mFadeProgress < 0 ) { mFadeProgress = 0; } } int i; for( i=0; istep(); } for( i=0; istep(); } } void Panel::addSubPanel( Panel *inPanel ) { mSubPanels.push_back( inPanel ); } void Panel::addButton( Button *inButton ) { mButtons.push_back( inButton ); } char Panel::isSubPanelVisible() { int i; for( i=0; iisVisible() ) { return true; } } return false; } char Panel::isSubPanelFullyVisible() { int i; for( i=0; iisFullyVisible() ) { return true; } } return false; } void Panel::draw() { // skip drawing this panel if hidden if( mFadeProgress > 0 && ! isSubPanelFullyVisible() ) { drawBase(); } drawSubPanels(); } void Panel::drawBase() { if( mFadeProgress > 0 ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glColor4f( 0, 0, 0, mFadeProgress ); const GLfloat squareVertices[] = { 0, 0, mW, 0, 0, mH, mW, mH, }; glVertexPointer( 2, GL_FLOAT, 0, squareVertices ); glEnableClientState( GL_VERTEX_ARRAY ); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisable( GL_BLEND ); int i; for( i=0; idraw(); } } } void Panel::drawSubPanels() { int i; for( i=0; idraw(); } } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/TutorialPanel.cpp0000644000175000017500000001534711144137333025604 0ustar pabspabs#include "TutorialPanel.h" #include "numeral.h" #include "gameControl.h" #include "sound.h" #include Color nextPieceDemoColors[3] = { Color( 255/255.0, 112/255.0, 0/255.0 ), Color( 128/255.0, 255/255.0, 0/255.0 ), Color( 96/255.0, 0/255.0, 192/255.0 ) }; TutorialPanel::TutorialPanel( int inW, int inH ) : Panel( inW, inH ), mNextButton( inW - ( 19 + 21 ), 19 + 21, "next" ), mNextPanel( inW, inH ), mNextPieceDemo( inW / 2, inH / 3, NULL, nextPieceDemoColors[0].copy(), nextPieceDemoColors[1].copy() ), mDemoStage( 0 ), mStepsBetweenStages( 50 ), mStepCount( 0 ) { addButton( &mNextButton ); addSubPanel( &mNextPanel ); int x, y, i; i=0; int gridH = 4; int gridW = 7; int yOffset = mNextPieceDemo.mY + 41 + 40; for( y=0; y 0 ) { mGridDemo[y][x]->mNeighbors[ GridSpace::top ] = mGridDemo[y-1][x]; } if( y < gridH-1 ) { mGridDemo[y][x]->mNeighbors[ GridSpace::bottom ] = mGridDemo[y+1][x]; } if( x > 0 ) { mGridDemo[y][x]->mNeighbors[ GridSpace::left ] = mGridDemo[y][x-1]; } if( x < gridW-1 ) { mGridDemo[y][x]->mNeighbors[ GridSpace::right ] = mGridDemo[y][x+1]; } } } } TutorialPanel::~TutorialPanel() { for( int i=0; i<28; i++ ) { delete mAllDemoSpaces[i]; } } void TutorialPanel::setStageZero() { int i; for( i=0; i<28; i++ ) { mAllDemoSpaces[i]->mActive = false; mAllDemoSpaces[i]->setColor( NULL ); } } void TutorialPanel::setVisible( char inIsVisible ) { Panel::setVisible( inIsVisible ); } char TutorialPanel::pointerUp( int inX, int inY ) { char consumed = Panel::pointerUp( inX, inY ); if( consumed ) { return true; } if( ! isSubPanelVisible() ) { if( mNextButton.isInside( inX, inY ) ) { mNextPanel.setVisible( true ); return true; } } return false; } void TutorialPanel::step() { Panel::step(); mNextPieceDemo.step(); int i; for( i=0; i<28; i++ ) { mAllDemoSpaces[i]->step(); } if( isVisible() && ! isSubPanelVisible() ) { mStepCount++; } else { // return to step 0 mDemoStage = 0; mStepCount = 0; setStageZero(); } if( mStepCount >= mStepsBetweenStages ) { mStepCount = 0; mDemoStage++; if( mDemoStage > 2 ) { mDemoStage = 0; } if( mDemoStage == 0 ) { setStageZero(); } else if( mDemoStage == 1 ) { GridSpace *s = mGridDemo[2][2]; s->setColor( nextPieceDemoColors[0].copy() ); if( getSoundOn() ) { int x = 2; float leftVolume, rightVolume; computeEarLoudness( x, &leftVolume, &rightVolume ); playPlacementSound( s->getColorIndex(), leftVolume, rightVolume ); } for( i=0; i<28; i++ ) { GridSpace *other = mAllDemoSpaces[i]; if( other != s ) { if( other->mY == s->mY || other->mX == s->mX ) { other->mActive = true; } } } } else if( mDemoStage == 2 ) { GridSpace *s = mGridDemo[0][2]; s->setColor( nextPieceDemoColors[1].copy() ); if( getSoundOn() ) { int x = 2; float leftVolume, rightVolume; computeEarLoudness( x, &leftVolume, &rightVolume ); playPlacementSound( s->getColorIndex(), leftVolume, rightVolume ); } for( i=0; i<28; i++ ) { mAllDemoSpaces[i]->mActive = false; } } } } Color tutorialTextColor( 255/255.0, 255/255.0, 160/255.0 ); void TutorialPanel::drawBase() { Panel::drawBase(); if( mFadeProgress > 0 ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); drawString( "colored tiles come in pairs", left, 19, mNextPieceDemo.mY - 41 - 30, &tutorialTextColor, mFadeProgress ); drawString( "press grid to place first tile", left, 19, mNextPieceDemo.mY + 41 + 20, &tutorialTextColor, mFadeProgress ); drawString( "second tile of pair must go in", left, 19, mGridDemo[3][0]->mY + 20 + 20, &tutorialTextColor, mFadeProgress ); drawString( "the same row or column", left, 19, mGridDemo[3][0]->mY + 20 + 40, &tutorialTextColor, mFadeProgress ); glDisable( GL_BLEND ); mNextPieceDemo.draw( mFadeProgress ); int i; int numGridSpaces = 28; for( i=0; idrawGrid( mFadeProgress ); } for( i=0; idrawPieceCenter( mFadeProgress ); } for( i=0; idrawPieceHalo( mFadeProgress ); } } } void TutorialPanel::closePressed() { // return to step 0 mDemoStage = 0; mStepCount = 0; setStageZero(); } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/Button.h0000644000175000017500000000241211144115746023732 0ustar pabspabs#ifndef BUTTON_INCLUDED #define BUTTON_INCLUDED #include "GridSpace.h" class Button { public: // constructs w/ center location on screen and a string label // if label is 1 or 2 characters, drawn with big font // if 3 or 4 chars, drawn with little font Button( int inX, int inY, char *inString ); ~Button(); // resets string // smooth transition void setString( char *inString ); // instant transtition void forceString( char *inString ); char isInside( int inX, int inY ); void setVisible( char inIsVisible ); char isVisible() { return mVisible; } // forces to become completely visible instantly void forceVisible(); void forceInvisible(); // steps animations void step(); // draws onto screen void draw(); int mX, mY; char *mString; private: GridSpace mSpace; char mVisible; float mFadeProgress; char *mLastString; float mStringTransitionProgress; }; #endif primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/yzplus_big.png0000644000175000017500000000667511133777227025230 0ustar pabspabsPNG  IHDR jfkbKGDC pHYs  tIME(8o& JIDATxZ͊$Ir<2"+({*qozy9.tE944M3fCxzFVUfu@Uff}ng\fFw~I?WzbbzJЧ| B'&F,k!݂0XzJ0޽{x ϛP=o߅7>sR#n_?UV\[DdzGB vLD{""~o}6~O}ߗlߛ0 bxU5J_UqUjWmժcuJGxpwwwi={3Yc ͻ] OBcDҟBRDBRSͬXzW7p@GD3*&\"b29gy@C/ƮޫJи}T0M!x"T :k{_j }L^;^f4[VR*!ཇ'"TQ%Z13SU_y O7E?|vzM 0_1F !lcdr^qT "'"+a8X.M)oJU9gZws/{1 X͊땹C uJ3܃T34M-D HhX2(X"a"cL]ը>pRFDBDbf:RTf\F3`@ :K)9*{Tldf#3D4W~PSP [3@Ds{<Ϛs.?l}iG""NRJ1Rr-d,1F !Ff?V4M777tqqUa@23!QVU "щx>D7+m9оyZ 8Q!SSRvӅ(*9k^#N@Zrx EeGNO\Ȟ}.K\j1b36|$I7D?~]nKV88g}ɜ-?,_i]Qѕ+h!&U&Ho߾7oj$O>/n 0i8ًHZ<,8Hɿ\ ILԅ\u)%ffof3wP@ J]ׅVD1sP;f.@);4ˏ'@4y"k0?@-Bf 404 m[@]Qdi끣ʹ섺mbi2ጾ-ƈŸRJC&*{]<sN5kZv^jEz"*IU:ofNDsQa{4;U.񋙨)""fFu'kWkk\숿VΙs*'mwwwy"DHDpZj|# ~8czt"ҩ*WY6TD&URJbDA<0CKg=D䌈ߚ2`ߥfUխaLruu%m. wyy9\ ffVQ`kR.'~^}]]]4Muݜ?}LsOPRx)ْTdGNLu]8Z|^DDEDSJRRf.)v@„fssXQVfs=U/Q >Tinr<0?{?%Mӄ̼Z/ӲG"$̞ׯ_$Qu2N VsNsvl3eX!T@p~FJo CƄv;؜/-jURyAff]zU#p JmmnաFl"ycu^EFSFX@T)%aDDM1P/ հ`RJ潟9O.Ð>}$/^%Ң.{{5!;sK\Q9 !4MV85R]0)"Ux倫50naBq["ZH`Ueȧ e!v2 6;bnl!p0xB)=ZVUА*!"bf)p`9 EditNamePanel::EditNamePanel( int inW, int inH ) : Panel( inW, inH ), mName( getName() ), mOverrideName( NULL ), mSendButton( inW - 19 - 21, 19 + 21, "send" ), mScoreToPost( NULL ), mScoreHandler( NULL ) { int i=0; int xStep = 41 + 19; int xStart = ( inW - xStep * 4 ) / 2; int yStep = xStep; int yStart = inH - (19 + 21) - ( yStep * 5 ); // grid of 6x5, but stop at 28 buttons for( int y=0; y<6 && i<28; y++ ) { for( int x=0; x<5 && i<28; x++ ) { char *s; if( i < 25 ) { s = new char[2]; s[0] = 'a' + i; s[1] = '\0'; } else if( i == 25 ) { s = stringDuplicate( "bksp" ); } else if( i == 26 ) { s = stringDuplicate( "z" ); } else { s = stringDuplicate( "clr" ); } if( i<26) { mKeyButtons[i] = new Button( xStart + x * xStep, yStart + y * yStep, s ); } else if( i==26 ){ // center mKeyButtons[i] = new Button( xStart + (x+1) * xStep, yStart + y * yStep, s ); } else if( i==27 ){ // right mKeyButtons[i] = new Button( xStart + (x+2) * xStep, yStart + y * yStep, s ); } delete [] s; addButton( mKeyButtons[i] ); i++; } } mSendButton.setVisible( false ); addButton( &mSendButton ); } EditNamePanel::~EditNamePanel() { for( int i=0; i<28; i++ ) { delete mKeyButtons[i]; } if( mOverrideName != NULL ) { delete [] mOverrideName; mOverrideName = NULL; } if( mScoreToPost != NULL ) { delete mScoreToPost; } } void EditNamePanel::setScoreToPost( ScoreBundle *inScore, Panel *inScoreHandler ) { if( mScoreToPost != NULL ) { delete mScoreToPost; } mScoreToPost = inScore; mScoreHandler = inScoreHandler; } void EditNamePanel::setVisible( char inIsVisible ) { Panel::setVisible( inIsVisible ); if( inIsVisible ) { // switch to displaying actual global name if( mOverrideName != NULL ) { delete [] mOverrideName; mOverrideName = NULL; } if( mScoreToPost == NULL ) { mSendButton.setVisible( false ); } else { mSendButton.setVisible( true ); } } } char EditNamePanel::pointerUp( int inX, int inY ) { char consumed = Panel::pointerUp( inX, inY ); if( consumed ) { return true; } if( ! isSubPanelVisible() ) { if( mSendButton.isVisible() && mSendButton.isInside( inX, inY ) ) { // treat as if close pressed // (save name, etc) closePressed(); if( strlen( mName ) > 0 ) { // replace the name in the bundle with the name // actually entered // blindly copy all 9 characters, which will include // a \0 somewhere in the middle memcpy( mScoreToPost->mName, mName, 9 ); } // else leave default name in place (instead of sending blank // name to server) MenuPanel *menuPanel = (MenuPanel *)mScoreHandler; // this will pop up the high score loading panel menuPanel->postScore( mScoreToPost ); mScoreToPost = NULL; mScoreHandler = NULL; // prevent double-sends // since we're not // actually popping up a sub panel here to block button presses mSendButton.setVisible( false ); return true; } for( int i=0; i<28; i++ ) { if( mKeyButtons[i]->isInside( inX, inY ) ) { char *buttonString = mKeyButtons[i]->mString; int oldNameLength = strlen( mName ); if( strlen( buttonString ) == 1 ) { // a letter if( oldNameLength < 8 ) { mName[ oldNameLength ] = buttonString[0]; mName[ oldNameLength + 1 ] = '\0'; } } else if( i == 25 ) { // backspace mName[ oldNameLength - 1 ] = '\0'; } else if( i==27 ) { // clear mName[0] = '\0'; } return true; } } } return false; } Color nameDisplayColor( 76/255.0, 76/255.0, 255/255.0 ); Color nameCapColor( 1, 1, 1 ); void EditNamePanel::drawBase() { Panel::drawBase(); if( mFadeProgress > 0 ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); int textY = 75; // draw end caps around 8-char wide text area /* drawSprite( gridLineTop, mKeyButtons[1]->mX, textY, 32, 32, &nameCapColor, mFadeProgress ); */ drawSprite( gridLineLeft, mKeyButtons[1]->mX, textY, 32, 32, &nameCapColor, mFadeProgress ); /* drawSprite( gridLineBottom, mKeyButtons[1]->mX, textY, 32, 32, &nameCapColor, mFadeProgress ); */ /* drawSprite( gridLineTop, mKeyButtons[3]->mX, textY, 32, 32, &nameCapColor, mFadeProgress ); */ drawSprite( gridLineRight, mKeyButtons[3]->mX, textY, 32, 32, &nameCapColor, mFadeProgress ); /* drawSprite( gridLineBottom, mKeyButtons[3]->mX, textY, 32, 32, &nameCapColor, mFadeProgress ); */ if( mOverrideName == NULL ) { drawStringBig( mName, center, mW / 2, textY, &nameDisplayColor, mFadeProgress ); } else { drawStringBig( mOverrideName, center, mW / 2, textY, &nameDisplayColor, mFadeProgress ); } glDisable( GL_BLEND ); } } void EditNamePanel::closePressed() { if( strlen( mName ) == 0 ) { // setting it to blank // game system will override this instantly when we save it // this is jaring (as panel fades out) // override to blank if( mOverrideName != NULL ) { delete [] mOverrideName; } mOverrideName = stringDuplicate( mName ); } saveName(); } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/numerals.png0000644000175000017500000000576111131734755024657 0ustar pabspabsPNG  IHDRRNbKGDC pHYs  tIME 5Hg ~IDATxZK-GVyss Ap! /$/ 78A@"_p \={z98vݽ>9&&4w?oU4txZ%# {60tF %ct yx̗DJff*Xz%/7"G2rd'/S4ޒ{y0Ni+m38X^7sԝ{kZfN̜rm vp.Zk)%kۖzBy.f9@DjĉUubm)Dg)[ B|";"bff1M#s}g"Lko,SXw(vF:%m@gF< ki 1$C,fDG;P6(DYwb|'N.//-)Y=>>>B0+S2rm&xXV^ڍTUECZ렸8Cٳg0э!nnʋPs?x e$pNʀ@w||2V\{і eAWuNQ'T1YJ0;q$ Zgk-r9Z[Kw¸~1 Z}, ,_^J[fӪc&" =)h!x_hC"e,˥h2sfd2Q駟^zrgeʛK0sGDr"/Õ:IEYgveعL㫎 &LhĔc7ZVcN1󖵶wbN E6wb@BDd &zf3jH ,9LR_FfCv]39gt]g@gggũ~`Tx0^X^ 녾2mt:-`#j0 tRs٪v\\i,!,弮Z\xfa9Y.\N"y܌dq|̅;h_B$"1ۡzb7՛XQ{=Zct1s&"6%nW1i4/ы7t:RxCS yQeqݩH|k:tu5_cq{oSJ\^@s3hǯks1Fw~~Nef`.4M)Ƙl6'OxzO9gcPhX АU@"kmYDZ۲It[;IL5%&"w u*bH*ªW≝ 34UDdC7GGG}Xmm=c$$ &ʆI)Y mDttRc"iL&F7 ZbX?|p 7V5Lrƀ~&,kl[ѫf@D*K!vZucu$fO9|޺ *XB̫ "cBUUVu켩;z! &~=@'wh>q=T>X6_9a暈384Io^ JJw∜ tU+ V}cB2l9LU܋J!\_ ӻb^_`[B+u w$(8u)\gD'j/NeN>sߒZwA \'|&ZުqʽZyoݟXBgzb [ٟX'NDz[`ED/ W3f~Ʋ)GY sroƲ& \Qgp3$19^c)o v~gڙ10эDObN>QU3 #1.&^O,,]}uM>q\~3+DkoOC?9ߵs;djψ5F7W_j ʑ㭠kl}09C:gG V$ضQX:FdPV-S hPzk;%޵v]kwݵ/e=}IENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/TutorialPanelB.h0000644000175000017500000000216111144137333025341 0ustar pabspabs#include "Panel.h" #include "TutorialPanelC.h" class TutorialPanelB : public Panel { public: TutorialPanelB( int inW, int inH ); ~TutorialPanelB(); // overrides these: char pointerUp( int inX, int inY ); void setVisible( char inIsVisible ); void step(); protected: // override void drawBase(); // receive close event void closePressed(); private: void setStageZero(); Button mNextButton; TutorialPanelC mNextPanel; GridSpace *mGridDemo[4][7]; GridSpace *mAllDemoSpaces[28]; // surrounded GridSpace *mInnerSpaces[4]; // surrounding GridSpace *mOuterSpaces[7]; // final to complete GridSpace *mKeySpace; int mInnerSpacesX[4]; int mDemoStage; int mStepsBetweenStages; int mStepCount; }; primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/pieceHalo.png0000644000175000017500000000352411131025307024677 0ustar pabspabsPNG  IHDR@@iq pHYs  tIME$(FAIDATxKr8 ee+0izݧ-^li|aMiFĝXU,ɉ-!z\O}GugEDP~!l~wρGg*~yxN;P^FtqfB$RTcq@0g()?3"S.LDC>K_)r\埞z6}7 t]gv%\ضm!t]?==z9Ux537DTZļ#3"\n)?< k^3qΚcjnO̜(#=Ka}^\ ۷RDDZS*̌1F^_]ĐO}mH.TXk cx]!IAb1"ce]J`,EF7ikS_(!w3d|tz~P-~6MQW֎M@LAxZy=s}{Dhn|-m6>sZ)eBZ8ZmmGt(>kjH`v֎ v+{6DDmۖBS~4hbPZ”P9edp i̺t J@= BPJ!O::!̘ aX`X11%ŢoM{?ZJIk\go&m4  c {#_@Z=g5Џ}(M,`N <!)? "dY5j%s,cR"ѩ` rt3nP+(#c~AƀCIWhJsQs )~)5ܹ3˻;Z#i_u:u>5Js3hc$c(pP}c x,P1D 8j]1eRZ߹C|++`(eSqX$7!XkAPg9}r|,PZK,=4c8?vUy! ^"#$IQU03R\ʚ9rvJsR 2qaQnWIVrxH὇ bӓ.ȳ]뺽+U%9@ HN; ZQ,c`=7MR4Mٴ(Sٿbcdۍ"DTm+e1 7 gݎ(ˊ4cA*],k~$ڀc1q^1NG0Hq8 N#{\/ 1: k1 xxxjoooZKZ`!1- !ԅ߇ax1rcQ(9X)lZ0 :]CK? WffNI ?K닓z|?JIENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/piece.png0000644000175000017500000000352411130765610024102 0ustar pabspabsPNG  IHDR@@iq pHYs  tIME,Y}tIDATxKr8 ee+1izݧ)^li|aMiFĝXU,ɉ-!z\O}GugEDP~!l~wρGg*~yxN;P^FtqfB$RTcq@0g()?3"S.LDC>K_)r\埞z6}7 t]gv%\ضm!t]?==z9Ux537DTZļ#3"\n)?< k^3qΚcjnO̜(#=Ka}^\ ۷RDDZS*̌1F^_]ĐO}mH.TXk cx]!IAb1"ce]J`,EF7ikS_(!w3d|tz~P-~6MQW֎M@LAxZy=s}{Dhn|-m6>sZ)eBZ8ZmmGt(>kjH`v֎ v+{6DDmۖBS~4hbPZ”P9edp i̺t J@= BPJ!O::!̘ aX`X11%ŢoM{?ZJIk\go&m4  c {#_@Z=g5Џ}(M,`N <!)? "dY5j%s,cR"ѩ` rt3nP+(#c~AƀCIWhJsQs )~)5ܹ3˻;Z#i_u:u>5Js3hc$c(pP}c x,P1D 8j]1eRZ߹C|++`(eSqX$7!XkAPg9}r|,PZK,=4c8?vUy! ^"#$IQU03R\ʚ9rvJsR 2qaQnWIVrxH὇ bӓ.ȳ]뺽+U%9@ HN; ZQ,c`=7MR4Mٴ(Sٿbcdۍ"DTm+e1 7 gݎ(ˊ4cA*],k~$ڀc1q^1NG0Hq8 N#{\/ 1: k1 xxxjoooZKZ`!1- !ԅ߇ax1rcQ(9X)lZ0 :]CK? WffNI ?K닓z|?J/WIENDB`primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/Makefile.all0000644000175000017500000000566711146315105024525 0ustar pabspabs# # Modification History # # 2006-June-27 Jason Rohrer # Created. Copied from Transcend. # ## # The portion of game1 Makefiles common to all platforms. # # Should not be made manually---used by game1/configure to build Makefiles. ## ROOT_PATH = ../../.. LAYER_SOURCE = \ gameSDL.cpp \ game.cpp \ common.cpp \ spriteBank.cpp \ GridSpace.cpp \ NextPieceDisplay.cpp \ numeral.cpp \ ColorPool.cpp \ Button.cpp \ Panel.cpp \ MenuPanel.cpp \ EditNamePanel.cpp \ HighScoreLoadingPanel.cpp \ WebRequest.cpp \ ScoreBundle.cpp \ HighScorePanel.cpp \ TutorialPanel.cpp \ TutorialPanelB.cpp \ TutorialPanelC.cpp \ networkInterfaceGeneric.cpp \ BringNetworkUpThread.cpp \ sound.cpp \ LAYER_OBJECTS = ${LAYER_SOURCE:.cpp=.o} GAME_GRAPHICS = \ graphics/gridLineTop.tga \ graphics/gridLineBottom.tga \ graphics/gridLineLeft.tga \ graphics/gridLineRight.tga \ graphics/plus.tga \ graphics/piece.tga \ graphics/pieceCenter.tga \ graphics/pieceHalo.tga \ graphics/pieceBrightHalo.tga \ graphics/pieceBrightCenter.tga \ graphics/numerals.tga \ graphics/numeralsBig.tga \ graphics/abcdefghijkl.tga \ graphics/mnopqrstuvwx.tga \ graphics/yzplus.tga \ graphics/abcdefghijkl_big.tga \ graphics/mnopqrstuvwx_big.tga \ graphics/yzplus_big.tga \ NEEDED_MINOR_GEMS_OBJECTS = \ ${SINGLE_TEXTURE_GL_O} \ ${TYPE_IO_O} \ ${STRING_UTILS_O} \ ${STRING_BUFFER_OUTPUT_STREAM_O} \ ${PATH_O} \ ${TIME_O} \ ${THREAD_O} \ ${FINISHED_SIGNAL_THREAD_O} \ ${MUTEX_LOCK_O} \ ${TRANSLATION_MANAGER_O} \ ${SOCKET_O} \ ${HOST_ADDRESS_O} \ ${SOCKET_CLIENT_O} \ ${NETWORK_FUNCTION_LOCKS_O} \ ${LOOKUP_THREAD_O} \ ${SETTINGS_MANAGER_O} \ ${SHA1_O} \ ${ENCODING_UTILS_O} \ TEST_SOURCE = TEST_OBJECTS = ${TEST_SOURCE:.cpp=.o} DEPENDENCY_FILE = Makefile.dependencies # targets all: Primrose ${GAME_GRAPHICS} clean: rm -f ${DEPENDENCY_FILE} ${LAYER_OBJECTS} ${TEST_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} Primrose ${GAME_GRAPHICS} Primrose: ${LAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${EXE_LINK} -o Primrose ${LAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${PLATFORM_LINK_FLAGS} # sed command for fixing up the dependencies generated by g++ # g++ (pre-3.0) leaves the path off of the .o target # look for a .o file at the beginning of a line (in other words, one # without a path), and replace it with the full-path version. # This should be compatible with g++ 3.0, since we only replace .o names # that occur at the beginning of a line (using the "^" modifier) GAME_1_SED_FIX_COMMAND = sed ' \ ' # build the dependency file ${DEPENDENCY_FILE}: ${LAYER_SOURCE} ${TEST_SOURCE} rm -f ${DEPENDENCY_FILE} ${COMPILE} -MM ${LAYER_SOURCE} ${TEST_SOURCE} >> ${DEPENDENCY_FILE}.temp cat ${DEPENDENCY_FILE}.temp | ${GAME_1_SED_FIX_COMMAND} >> ${DEPENDENCY_FILE} rm -f ${DEPENDENCY_FILE}.temp include ${DEPENDENCY_FILE} # # Generic: # # Map all png files into .tga files # # $@ represents the name.tga file # $< represents the name.png file # graphics/%.tga: %.png convert $< $@ primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/networkInterfaceGeneric.cpp0000644000175000017500000000051411140771234027616 0ustar pabspabs// Default for platforms that have always-on networking char isNetworkAlwaysOn() { // for testing //return false; return true; } #include "minorGems/system/Thread.h" // does nothing char makeSureNetworkIsUp( char *inTestURL ) { // for testing //Thread::staticSleep( 5000 ); return true; } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/HighScoreLoadingPanel.cpp0000644000175000017500000003333611175575767027175 0ustar pabspabs#include "HighScoreLoadingPanel.h" #include "numeral.h" #include "spriteBank.h" #include "gameControl.h" // defines a secret string shared with server // must contain: // // #define secureSalt "change_me" // // where "change_me" is a value shared with the server. #include "secureSalt.h" #include "minorGems/util/stringUtils.h" #include "minorGems/crypto/hashes/sha1.h" #include #include Color scoreLoadingGreen( 0, 1, 0 ); Color scoreLoadingRed( 1, 0, 0 ); extern char *savedServerURL; void HighScoreLoadingPanel::startConnectionTry() { mFailed = false; mBlinkTime = 0; mStatusLight.setColor( scoreLoadingGreen.copy() ); mLightRed = false; if( mServerURL == NULL && mServerURLFetchRequest == NULL ) { // try again mServerURLFetchRequest = new WebRequest( "GET", mServerFinderURL, NULL ); } } void HighScoreLoadingPanel::setFailed() { mFailed = true; mTryingToPostScore = false; mLastMessage = mMessage; mMessage = "connect failed"; // smooth transition to failure mStringTransitionProgress = 0; } HighScoreLoadingPanel::HighScoreLoadingPanel( int inW, int inH ) : Panel( inW, inH ), mMessage( "loading scores" ), mLastMessage( NULL ), mStringTransitionProgress( 1 ), mStatusLight( inW / 2, inH / 2 ), mBlinkTime( 0 ), mTryingToPostScore( false ), mScoreToPost( NULL ), mWebRequest( NULL ), mServerFinderURL( "http://hcsoftware.sourceforge.net/primrose/serverLocation6.txt" ), mServerURL( NULL ), mServerURLFetchRequest( NULL ), mFailed( false ), mLightRed( false ), mDisplayPanel( inW, inH ) { if( savedServerURL != NULL ) { mServerURL = stringDuplicate( savedServerURL ); } startConnectionTry(); // do not manage as sub-panel // addSubPanel( &mDisplayPanel ); } HighScoreLoadingPanel::~HighScoreLoadingPanel() { if( mScoreToPost != NULL ) { delete mScoreToPost; } if( mWebRequest != NULL ) { delete mWebRequest; } if( mServerURL != NULL ) { delete [] mServerURL; } if( mServerURLFetchRequest != NULL ) { delete mServerURLFetchRequest; } } void HighScoreLoadingPanel::setLoadingMessage() { mLastMessage = mMessage; mMessage = "loading scores"; // force message mStringTransitionProgress = 1; } void HighScoreLoadingPanel::setScoreToPost( ScoreBundle *inBundle ) { if( mScoreToPost != NULL ) { delete mScoreToPost; } mScoreToPost = inBundle; if( inBundle != NULL ) { mTryingToPostScore = true; mLastMessage = mMessage; mMessage = "posting score"; // force message mStringTransitionProgress = 1; startConnectionTry(); } else { mTryingToPostScore = false; } } void HighScoreLoadingPanel::step() { Panel::step(); mStatusLight.step(); mBlinkTime += 0.2; // allow some blinking (for reading message) // before we consider message transitions // or consider light c if( isFullyVisible() && mBlinkTime > 9 ) { if( mFailed && ! mLightRed ) { mLightRed = true; mStatusLight.setColor( scoreLoadingRed.copy() ); } if( mStringTransitionProgress < 1 ) { mStringTransitionProgress += 0.2; if( mStringTransitionProgress > 1 ) { mStringTransitionProgress = 1; } } } // check if we should hide ourself if( mVisible && mDisplayPanel.isFullyVisible() ) { // display showing setVisible( false ); } if( mServerURLFetchRequest != NULL ) { int stepResult = mServerURLFetchRequest->step(); if( stepResult == 1 ) { // done char *result = mServerURLFetchRequest->getResult(); SimpleVector *tokens = tokenizeString( result ); delete [] result; if( tokens->size() > 0 ) { char *returnedURL = *( tokens->getElement( 0 ) ); if( mServerURL != NULL ) { delete [] mServerURL; } mServerURL = stringDuplicate( returnedURL ); printf( "Got server URL: %s\n", mServerURL ); // save it if( savedServerURL != NULL ) { delete [] savedServerURL; } savedServerURL = stringDuplicate( mServerURL ); } else { printf( "Error: " "Got bad response when fetching server URL.\n" ); setFailed(); } for( int i=0; isize(); i++ ) { delete [] *( tokens->getElement( i ) ); } delete tokens; delete mServerURLFetchRequest; mServerURLFetchRequest = NULL; } else if( stepResult == -1 ) { // error delete mServerURLFetchRequest; mServerURLFetchRequest = NULL; printf( "Error: " "WebRequest failed when fetching server URL.\n" ); setFailed(); } } else if( mWebRequest != NULL ) { int stepResult = mWebRequest->step(); // don't consider processing result until at least a bit of blinking // has happened // (thus, we give the user time to read the loading/posting // message before the score display is shown) // still, we want to detect a successful score post right away // to prevent the user from clicking BACK while we're blinking // and then reposting the score later // Note that this ignores whether the result is well-formatted // oh well! if( stepResult == 1 ) { if( mTryingToPostScore ) { // post success... // prevent reposts scoreSent(); mTryingToPostScore = false; } } // now consider processing full result after enough blinking if( mBlinkTime > 9 && stepResult == 1 ) { // done char goodResult = false; char *result = mWebRequest->getResult(); SimpleVector *tokens = tokenizeString( result ); delete [] result; if( tokens->size() >= 2 ) { int numAllTime; int numRead = sscanf( *( tokens->getElement( 0 ) ), "%d", &numAllTime ); if( numRead == 1 ) { if( tokens->size() >= 2 + numAllTime ) { mDisplayPanel.clearScores(); int i; for( i=0; igetElement( 1 + i ) ) ); mDisplayPanel.addAllTimeScore( b ); } int numToday; int numRead = sscanf( *( tokens->getElement( 1 +numAllTime ) ), "%d", &numToday ); if( numRead == 1 ) { if( tokens->size() >= 2 + numAllTime + numToday ) { int i; goodResult = true; for( i=0; igetElement( 2 + numAllTime + i ) ) ); mDisplayPanel.addTodayScore( b ); } } } } } } if( !goodResult ) { printf( "Error: " "Got unparsable high score table from server.\n" ); setFailed(); } else { mDisplayPanel.setVisible( true ); } for( int i=0; isize(); i++ ) { delete [] *( tokens->getElement( i ) ); } delete tokens; delete mWebRequest; mWebRequest = NULL; } else if( stepResult == -1 ) { // error delete mWebRequest; mWebRequest = NULL; printf( "Error: " "WebRequest failed when posting or fetching scores.\n" ); setFailed(); } } else if( mScoreToPost != NULL && mServerURL != NULL ) { // need to generate a request char *stringToHash = autoSprintf( "%s%u%u%s%s", mScoreToPost->mName, mScoreToPost->mScore, mScoreToPost->mSeed, mScoreToPost->mMoveHistory, secureSalt ); char *hash = computeSHA1Digest( stringToHash ); delete [] stringToHash; char *body = autoSprintf( "action=post_score" "&name=%s" "&score=%u" "&seed=%u" "&move_history=%s" "&hash=%s", mScoreToPost->mName, mScoreToPost->mScore, mScoreToPost->mSeed, mScoreToPost->mMoveHistory, hash ); delete [] hash; delete mScoreToPost; mScoreToPost = NULL; mWebRequest = new WebRequest( "POST", mServerURL, body ); delete [] body; } else if( mVisible && mFadeProgress == 1 && ! mDisplayPanel.isVisible() && !mFailed && mServerURL != NULL ) { // wait until fully faded in to avoid jumping abruptly to display // if request is fast // generate a load request mWebRequest = new WebRequest( "POST", mServerURL, "action=fetch_scores" ); } } void HighScoreLoadingPanel::setVisible( char inIsVisible ) { Panel::setVisible( inIsVisible ); if( inIsVisible ) { // try again, afresh startConnectionTry(); } } char HighScoreLoadingPanel::pointerUp( int inX, int inY ) { char consumed = Panel::pointerUp( inX, inY ); if( consumed ) { return true; } if( ! isSubPanelVisible() ) { } return false; } Color loadingMessageColor( 76/255.0, 76/255.0, 255/255.0 ); void HighScoreLoadingPanel::drawBase() { Panel::drawBase(); if( mFadeProgress > 0 ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE ); int textY = 100; if( mStringTransitionProgress > 0 ) { drawStringBig( mMessage, center, mW / 2, textY, &loadingMessageColor, mFadeProgress * mStringTransitionProgress ); } if( mLastMessage != NULL && mStringTransitionProgress < 1 ) { drawStringBig( mLastMessage, center, mW / 2, textY, &loadingMessageColor, mFadeProgress * (1 - mStringTransitionProgress) ); } glDisable( GL_BLEND ); mStatusLight.drawGrid( mFadeProgress ); float glowVal = sin( mBlinkTime - M_PI / 2 ) * 0.5 + 0.5; mStatusLight.drawPieceCenter( mFadeProgress * glowVal ); mStatusLight.drawPieceHalo( mFadeProgress * glowVal ); } } void HighScoreLoadingPanel::closePressed() { if( mWebRequest != NULL ) { delete mWebRequest; } mWebRequest = NULL; } primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/networkInterface.h0000644000175000017500000000074011140743472025772 0ustar pabspabs// interface for making sure network is up // used on iPhone to ensure connectivity before making a socket request... // does nothing on always-networked platforms // true for always-on platforms // makeSureNetworkIsUp can be skipped on those platforms char isNetworkAlwaysOn(); // makes sure the network is up, and tries to bring it up if it is not // uses inTestURL to check reachability // note that this call might block char makeSureNetworkIsUp( char *inTestURL ); primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/HighScoreLoadingPanel.h0000644000175000017500000000306711142122134026602 0ustar pabspabs#include "Panel.h" #include "GridSpace.h" #include "ScoreBundle.h" #include "WebRequest.h" #include "HighScorePanel.h" class HighScoreLoadingPanel : public Panel { public: HighScoreLoadingPanel( int inW, int inH ); ~HighScoreLoadingPanel(); void setLoadingMessage(); // bundle deleted after posting // posting starts when made visible void setScoreToPost( ScoreBundle *inBundle ); // display panel is NOT managed as a sub panel of this panel HighScorePanel *getDisplayPanel() { return &mDisplayPanel; } // overrides these: void step(); void setVisible( char inIsVisible ); char pointerUp( int inX, int inY ); protected: // override void drawBase(); void closePressed(); private: char *mMessage; char *mLastMessage; float mStringTransitionProgress; GridSpace mStatusLight; float mBlinkTime; char mTryingToPostScore; ScoreBundle *mScoreToPost; WebRequest *mWebRequest; char *mServerFinderURL; char *mServerURL; WebRequest *mServerURLFetchRequest; char mFailed; char mLightRed; void startConnectionTry(); void setFailed(); HighScorePanel mDisplayPanel; }; primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/abcdefghijkl_working.xcf0000644000175000017500000005424411133717772027164 0ustar pabspabsgimp xcf file}si_UKA7-# BB $gimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) !%IXWfblur 6 copy 50%      %%                                                                     %,00,%  %2:==:2% -:BEEB:- 1?GIIG?1 "4CJLLJC4"$6FNPPNF6$$6FNPPNF6$"3AHJJHA3"-8=>>=8-%-0//0-% !"!!"!         %,0/,%  %2:==91% -:BEDA9+ 1?FHGD0$7FNOMH>0%8HPROJ?0$7GPRPJ@0"4DMPNI?//>GJID;, '4<@?;2%  &-11-&          $*+("  $/54/' *696.$ -670& -53* ,30%,30%-53* -670& *696.$  $/54/'  $*+("                                                       $*,*$  %07850' +7==;7/$ -8<;:83(-798774*-675454+-675454+-798774*-8<;:83(+7==;7/$  %07850'  $*,*$          %*+("  %1761( ,9>;3)  1=A<2& "4AD>2%$6DHA5'$8FKE8)$7EKF:, "4BHD:-  .;3)  1=A<2& "4@C=1$$6CF?3$ $6CF?2$ "3?A9- -66."$+*"         $*+("  %0650( +6;92) .8;70(      #                 #                 #            .8;70)! .8;84/(  /9==;81%  /;@AA?8,/;BEEC<.,9ADEB:, %1:=>:2&  %,00-&           #)*))*)# *365563* 0<@AA@<0 #5CIKKIC5##6DLNNLD6#"3AHIIHA3"-8=>>=8-%-0//0-% !"!!"!        ),)  (383(+8=8+ (6<6(  %282%  "/5/"  "/5/"  %282%  (6<6( +8=8+(383(  ),)           $  &*& ).) #-0+ !)13, #(,166-      %            %            %       #-369;8- &29=>=7+ #.6::80% $+./,%            "))&$$# *23/+)&  0:<71+% #4@B=5,$ #5AD?6,#"2>A<3+"-684.(" %,-)&#       %       $  &*&)-)*0+ ,2.# -42) -670& *696.$  $/54/'  $*+("     @blur 6      &d&I@IL&/9B                                                                    %,00,%  %2:==:2% -:BEEB:- 1?GIIG?1 "4CJLLJC4"$6FNPPNF6$$6FNPPNF6$"3AHJJHA3"-8=>>=8-%-0//0-% !"!!"!         %,0/,%  %2:==91% -:BEDA9+ 1?FHGD0$7FNOMH>0%8HPROJ?0$7GPRPJ@0"4DMPNI?//>GJID;, '4<@?;2%  &-11-&          $*+("  $/54/' *696.$ -670& -53* ,30%,30%-53* -670& *696.$  $/54/'  $*+("                                                       $*,*$  %07850' +7==;7/$ -8<;:83(-798774*-675454+-675454+-798774*-8<;:83(+7==;7/$  %07850'  $*,*$          %*+("  %1761( ,9>;3)  1=A<2& "4AD>2%$6DHA5'$8FKE8)$7EKF:, "4BHD:-  .;3)  1=A<2& "4@C=1$$6CF?3$ $6CF?2$ "3?A9- -66."$+*"         $*+("  %0650( +6;92) .8;70(      #                 #                 #            .8;70)! .8;84/(  /9==;81%  /;@AA?8,/;BEEC<.,9ADEB:, %1:=>:2&  %,00-&           #)*))*)# *365563* 0<@AA@<0 #5CIKKIC5##6DLNNLD6#"3AHIIHA3"-8=>>=8-%-0//0-% !"!!"!        ),)  (383(+8=8+ (6<6(  %282%  "/5/"  "/5/"  %282%  (6<6( +8=8+(383(  ),)           $  &*& ).) #-0+ !)13, #(,166-      %            %            %       #-369;8- &29=>=7+ #.6::80% $+./,%            "))&$$# *23/+)&  0:<71+% #4@B=5,$ #5AD?6,#"2>A<3+"-684.(" %,-)&#       %       $  &*&)-)*0+ ,2.# -42) -670& *696.$  $/54/'  $*+("     @sharp     IJWNWZJ2MPTT     T     T     T                                                    U   U   U   U@ New Layer      XX0XXXLX\XlX|@primrose-6+dfsg1.orig/tilePlacementGames/game1/gameSource/Panel.h0000644000175000017500000000331311140751541023512 0ustar pabspabs#ifndef PANEL_INCLUDED #define PANEL_INCLUDED #include "Button.h" #include "minorGems/util/SimpleVector.h" // abstract base class // panel with a close button at the top class Panel { public: Panel( int inW, int inH); virtual ~Panel(); virtual void setVisible( char inIsVisible ); virtual char isVisible() { return mVisible; } // forces to become completely visible/invisible instantly virtual void forceVisible(); virtual void forceInvisible(); virtual char isFullyVisible() { return mVisible && (mFadeProgress == 1); } char isSubPanelVisible(); // tells panel that pointer released inside it // returns true if release consumed (triggered a button somewhere) virtual char pointerUp( int inX, int inY ); // steps animations virtual void step(); // draws onto screen // don't override this void draw(); protected: void addSubPanel( Panel *inPanel ); void addButton( Button *inButton ); char isSubPanelFullyVisible(); // subclasses override these virtual void drawBase(); virtual void closePressed() = 0; int mW, mH; float mFadeProgress; char mVisible; private: void drawSubPanels(); Button mCloseButton; SimpleVector