/* ========================================================================	*/
/*    PROGRAM:  CPFND01.C
/*    PURPOSE:  Contains library routines for Parsing of PowerBuilder Object Text
/* ========================================================================	*/

#define _CPFND01_C
#include "cpfind.h"

/* ========================================================================	*/
/*	DllMain: Main Library Routines					   
/* ========================================================================	*/
BOOL WINAPI DllMain ( HANDLE hInst, DWORD ul_reason_for_call, LPVOID lpReserved ) 
{
    switch( ul_reason_for_call ) 
	    {
	    case DLL_PROCESS_ATTACH:

			hDLL = hInst ;
		    return TRUE;


	    case DLL_THREAD_ATTACH:

	    case DLL_THREAD_DETACH:

	    case DLL_PROCESS_DETACH:
			return TRUE;
			break;
	    }
    return TRUE;
}

/* ========================================================================	*/
/*	LoadCPFind: Generic Function to load DLL in memory					   
/* ========================================================================	*/
PBINT __stdcall LoadCPFind(PBINT iDummy)
{
	return 0 ;
}

/* ========================================================================	*/
/*	StripComments: This function strips out the comments from the source.
/* ========================================================================	*/
DWORD __stdcall StripComments(DWORD hpdObjBuf)
{
	long lOrigLen, lCurIndex, lNewIndex ;
	HPSTR hpObjBuf, hpNewBuf ;
	char chQuote ;
	char chSpace = {' '};
	
	hpObjBuf = (HPSTR) hpdObjBuf ;
	lOrigLen = Hstrlen(hpObjBuf) + 2 ;
	#ifdef _DOS
	if ((hpNewBuf = _fmalloc(lOrigLen)) == NULL)
	{
		return (NULL) ;
	}
	#else
	if ((hpNewBuf = GlobalAllocPtr(GMEM_ZEROINIT, lOrigLen)) == NULL)
	{
		return ((DWORD) NULL) ;
	}
	#endif

	for (lCurIndex = 0, lNewIndex = 0 ; (hpObjBuf[lCurIndex] != '\0') ; ++lCurIndex)
	{
		if ((hpObjBuf[lCurIndex] == '\'') || (hpObjBuf[lCurIndex] == '\"'))
		{
			chQuote = hpObjBuf[lCurIndex] ;
			hpNewBuf[lNewIndex] = chQuote ;
			++lNewIndex ;
			++lCurIndex ;
			
			/* Skip complete literal  */
			for ( ; (hpObjBuf[lCurIndex] != '\0') ; ++lCurIndex)
			{
				if (hpObjBuf[lCurIndex] == '~')
				{
					/*   Move the tilde character  */
					hpNewBuf[lNewIndex] = hpObjBuf[lCurIndex] ;
					++lNewIndex ;
					++lCurIndex ;
					/*   Move the protected character  */
					hpNewBuf[lNewIndex] = hpObjBuf[lCurIndex] ;
					++lNewIndex ;
					continue ;
			  	}
				if (hpObjBuf[lCurIndex] == chQuote)
				{
					hpNewBuf[lNewIndex] = hpObjBuf[lCurIndex] ;
					++lNewIndex ;
  					break ;
				}
			}
		}

		else if ((hpObjBuf[lCurIndex] == '/') && (hpObjBuf[lCurIndex + 1] == '/'))
		{
			lCurIndex += 2 ;
			for ( ; (hpObjBuf[lCurIndex] != '\0') ; ++lCurIndex)
			{
				if (hpObjBuf[lCurIndex] == '\n')
				{
					break ;
				}
			}
		}
		else if ((hpObjBuf[lCurIndex] == '/') && (hpObjBuf[lCurIndex + 1] == '*'))
		{
			lCurIndex += 2 ;
			
			for ( ; (hpObjBuf[lCurIndex] != '\0') ; ++lCurIndex)
			{
				if ((hpObjBuf[lCurIndex] == '*') && (hpObjBuf[lCurIndex + 1] == '/'))
				{
					break ;
				}
			}
		
			/*  Loop until identifier or new line  */
			lCurIndex += 2 ;
			for ( ; (hpObjBuf[lCurIndex] != '\0') ; ++lCurIndex)
			{
				chQuote = hpObjBuf[lCurIndex] ;
				if (IsIdentifierChar(chQuote) == 1)
					{
 					break;
					}
				else if (hpObjBuf[lCurIndex] == '\n')
					{
					break ;
					}
			}
		}
		else
		{
			hpNewBuf[lNewIndex] = hpObjBuf[lCurIndex] ;
			++lNewIndex ;
		}
	}
	
	hpNewBuf[lNewIndex] = '\0' ;
	
	#ifdef _DOS
	_ffree(hpObjBuf) ;
	#else
	GlobalFreePtr(hpObjBuf) ;
	#endif
	
	return ((DWORD) hpNewBuf) ;
}

/* ========================================================================	*/
/*  GetSourceSize:  Gets the size of the object source	
/*  Added by Jane Cantz			   
/* ========================================================================	*/
long __stdcall GetSourceSize(DWORD hpdObjBuf)
{
	HPSTR hpObjBuf ;
	long lSize=0 ;

	hpObjBuf = (HPSTR) hpdObjBuf ;
	lSize = Hstrlen(hpObjBuf) ;
	
	return lSize ;
}

/* ========================================================================	*/
/*	DisplayMessage: - Standard call for MessageBox.								   
/* ========================================================================	*/
PBINT __stdcall DisplayMessage ( LPSTR lpMessage, LPSTR lpTitle )
{
	MessageBox ( NULL, lpTitle, lpMessage, MB_OK ) ;
	return 1 ;
}
  
/* ========================================================================	*/
/*	FindGeneric: Get offset of passed string 
/* ======================================================================== */
long __stdcall FindGeneric(DWORD hpdObjBuf, long lstartpos, LPSTR lpName, long lsize, PBINT iCase)
{
	HPSTR hpObjBuf ;
	long lNameOffSet=0 ;
	
	if ( iCase == 0 ) 
		{
	  	hpObjBuf = Hstrlwr ( (HPSTR) hpdObjBuf ) ;
		}
	else
		{
	   	hpObjBuf = (HPSTR) hpdObjBuf ;
		}

 
	/*  Look for next occurence of name */
	lNameOffSet = Hstrstrn( &(hpObjBuf[lstartpos]), lpName ) ;

	if ( lNameOffSet > 0 )
		{
		lNameOffSet = lNameOffSet + lstartpos ;
		return lNameOffSet ;
 		}

	return -1 ;
}

/* ========================================================================	*/
/*	ReplaceName: 
/*			hpBuf			: Pointer to string in which the Replacement is to be done
/*			lStartPos		: Position at which replacement is to be done
/*			iNoReplaceChar	: No of Characters to be Replaced
/*			lpReplaceWith	: The String which is to be Replaced with
/* ======================================================================== */
DWORD FAR PASCAL ReplaceName(DWORD hpdObjBuf, long lStartPos, PBINT iNoReplaceChar, LPSTR lpReplaceWith)
{
	long lReplaceLen, lBufLen, lNewSize ;
	HPSTR lpNewBuf, lpNewTmp, lpOldTmp ;
	HPSTR hpBuf ;

	hpBuf = ( HPSTR ) hpdObjBuf ;

	lBufLen = Hstrlen(hpBuf) ;
	lReplaceLen = Hstrlen(lpReplaceWith) ;
	lNewSize = lBufLen + (lReplaceLen - iNoReplaceChar) + 1 ;

	if ((lpNewBuf = (HPSTR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, lNewSize)) == NULL)
	{
		DisplayMessage("GlobalAllocPtr Failed, Serious Error", "System Error") ;
		return ((DWORD) NULL) ;
	}
	
	Hstrncpy(lpNewBuf, hpBuf, lStartPos) ;
	lpNewTmp = (HPSTR) &(lpNewBuf[lStartPos]) ;
	
	Hstrncpy(lpNewTmp, lpReplaceWith, lReplaceLen) ;
	lpNewTmp = (HPSTR) &(lpNewBuf[lStartPos + lReplaceLen]) ;
	lpOldTmp = (HPSTR) &(hpBuf[lStartPos + iNoReplaceChar]) ;
	
	Hstrcpy(lpNewTmp, lpOldTmp) ;
	 	
	GlobalFreePtr(hpBuf) ;
	
	return ((DWORD) lpNewBuf) ;
}


/* ========================================================================	*/
/*	PBGetClassName: Gets the classname of the loaded object
/*	Added by Jane Cantz on 12/6/96			  
/* ========================================================================	*/
long WINAPI PBGetClassName(DWORD hpdObjBuf, LPSTR lpObject, LPSTR lpClass, long ll_StartOffSet)
{
	HPSTR hpObjBuf ;
	long lOffSet, lObjLen, lSearch, lOffSet2 ;
	char lpTemp[256]   = "11111111112222222222333333333344444444445555555555" 
						 "11111111112222222222333333333344444444445555555555"
						 "11111111112222222222333333333344444444445555555555"
						 "11111111112222222222333333333344444444445555555555"
						 "11111111112222222222333333333344444444445555555555666666" ;
	char lpSearch[256] = "11111111112222222222333333333344444444445555555555" 
						 "11111111112222222222333333333344444444445555555555"
						 "11111111112222222222333333333344444444445555555555"
						 "11111111112222222222333333333344444444445555555555"
						 "11111111112222222222333333333344444444445555555555666666" ;

	strcpy ( lpSearch, "global type " ) ;
	strcat ( lpSearch, lpObject ) ;
	strcat ( lpSearch, " from " ) ;
	lSearch = strlen ( lpSearch ) ;

	hpObjBuf = (HPSTR) hpdObjBuf ;

	/*  Might not use first occurence of "global type"  */
	lOffSet = Hstrstrn( hpObjBuf, lpSearch ) ;
	lOffSet2 = Hstrstrn( &(hpObjBuf[lOffSet+1]), lpSearch ) ;
	if (lOffSet2 > 0)
		{
		lOffSet2 = lOffSet2 + lOffSet + 1 ;
		}

	if (lOffSet2 > 0)
		{
		lOffSet = lOffSet2 ;
		}

	lOffSet2 = lOffSet ;
	if (lOffSet > 0)
		{
		ll_StartOffSet = lOffSet ;
		/*  Copy information into the arguments  */
		lObjLen	= Hstrlen ( hpObjBuf ) ;
		lObjLen = lObjLen - lOffSet	 ;
		if ( lObjLen > 255 )
			{
			lObjLen = 255 ;
			}
		Hstrncpy (lpTemp, &(hpObjBuf[lOffSet+lSearch]), lObjLen) ;
		lOffSet = Hstrstrn (lpTemp, (LPSTR) "\n" ) ;
		Hstrncpy (lpClass, lpTemp, lOffSet - 1) ;
		lOffSet2 = Hstrstrn( &(hpObjBuf[lOffSet2+1]), "end type\0" ) ;
		if (lOffSet2 > 0)
			{
			lOffSet = lOffSet2 + lOffSet2 + 1 ;
			}
		}

	else 
		{
		lpClass = "" ;
		lOffSet = 0	;
		}

	return lOffSet ;
}

/* ========================================================================	*/
/*	IsIdentifierChar: Is the passed character allowed as part of identifier ?
/* ========================================================================	*/
PBINT WINAPI IsIdentifierChar(char chCur)
{
	static  PBINT bInit = FALSE ;
	static unsigned int bAllowedInIdentifier[256] ;
	unsigned char chIndex ;
	PBINT bIdentifier ;
	
	if (!bInit)
	{
		for (chIndex = (unsigned char) 0 ; ; ++chIndex)
		{
			bIdentifier = ((chIndex >= (unsigned char) '0') && (chIndex <= (unsigned char) '9')) || \
							((chIndex >= (unsigned char) 'A') && (chIndex <= (unsigned char) 'Z')) || \
							((chIndex >= (unsigned char) 'a') && (chIndex <= (unsigned char) 'z')) || \
							(chIndex == (unsigned char) '-') || \
							(chIndex == (unsigned char) '_') || \
							(chIndex == (unsigned char) '$') || \
							(chIndex == (unsigned char) '#') || \
							(chIndex == (unsigned char) '%') ;
			
			if (bIdentifier)
			{
				bAllowedInIdentifier[chIndex] = TRUE ;
			}
			else
			{
				bAllowedInIdentifier[chIndex] = FALSE ;
			}
			
			if (chIndex == (unsigned int) 255)
			{
				break ;
			}
		}
		
		bInit = TRUE ;
	}
	
	return bAllowedInIdentifier[(unsigned char) chCur] ;
}

/* ========================================================================	*/
/*	GetSource: 
/* ========================================================================	*/
void __stdcall GetSource(DWORD hpdObjBuf, LPSTR lpString)
{
	HPSTR hpObjBuf ;

	hpObjBuf = (HPSTR) hpdObjBuf ;

	Hstrcpy(lpString,(LPSTR) hpObjBuf) ;

}

/* ========================================================================	*/
/*	GetSourceContext:  Parse object code returning context items from
/*					   the source buffer.  			   
/* ========================================================================	*/
long WINAPI GetSourceContext(DWORD hpdObjBuf, PBINT iStart, long lStart, LPSTR lpSearch, LPSTR lpLine, LPSTR lpContext, long lSize, PBINT iCase, PBINT iDW)
{
	HPSTR hpObjBuf ;
	long lPhraseOffset ;

	if (iCase == 0)
		{
		hpObjBuf = Hstrlwr((HPSTR) hpdObjBuf) ;
		}
	else
		{
		hpObjBuf = (HPSTR) hpdObjBuf ;
 		}
	
	lPhraseOffset = ParseSource(hpObjBuf, iStart, lStart, lpSearch, lpLine, lpContext, lSize, iDW)  ;
	
	/*  Return to PB */
	return lPhraseOffset ;
}

/* ========================================================================	*/
/*	ParseSource: Gets the context information for the source lines
/*	Added by Jane Cantz on 11/2/96
/* ========================================================================	*/
long WINAPI ParseSource(HPSTR hpObjBuf, PBINT iStart, long lOffSet, LPSTR lpSearch, LPSTR lpLine, LPSTR lpContext, long lSize, PBINT iDW)
{
	char *token ;
	char sepspace[]   = " " ;
	char sepparen[]   = "(" ;
	char sepdot[]    = "." ;
	char sepsemi[]    = ";" ;
	char sepcolon[]    = ":" ;
	static PBINT iFound = 0 ;
	long lIdx ;
	PBINT iRetVal, iRetSrch	;
	PBINT iFunc=0 ;
  	char lpReturn[MAX_CONTEXT_LENGTH] ;
  	static char lpControl[MAX_CONTEXT_LENGTH] ;
 	char lpInit[MAX_CONTEXT_LENGTH] ;
	char lpTest[MAX_CONTEXT_LENGTH] ;
	char lpTest2[MAX_CONTEXT_LENGTH] ;
 	LPSTR lpToken1   = "11111111112222222222333333333344444444445555555555666666666677777777778888888888"
					   "99999999990000000000111111111122222222223333333333444444444455555555556666666666"
					   "77777777778888888888999999999900000000001111111111222222222233333333334444444444"
					   "5555555555666666" ;
	LPSTR lpToken2   = "11111111112222222222333333333344444444445555555555666666666677777777778888888888"
					   "99999999990000000000111111111122222222223333333333444444444455555555556666666666"
					   "77777777778888888888999999999900000000001111111111222222222233333333334444444444"
					   "5555555555666666" ;

	/*  Initialize this area  */
	for (lIdx = 0 ; (lIdx < MAX_CONTEXT_LENGTH) ; ++lIdx)
		{
		lpInit[lIdx] = ' '	;
		}

	if ( lOffSet < 0 )
		{
		return -1 ;
		}

/*  Get a line from the source buffer  */
GetLine:
	/*  Initialize lpReturn  */
	Hstrcpy ( lpReturn, lpInit ) ;

	if (iDW == 1)
		{
		lOffSet = PBGetDWLine(hpObjBuf, lOffSet, lpReturn, lSize) ;
		}
	else
		{
   		lOffSet = PBGetLine(hpObjBuf, lOffSet, lpReturn, lSize) ;
		}

	iFunc = 0 ;
  
	if (lOffSet == -1)
		return -1 ;

	if (iStart != 1 )
		{
		/*  Until further notice, we are in the forwards section  */
		if (iDW == 1)
			{
   			Hstrcpy ( lpContext, "DataWindow Attributes\0" ) ;
			}
		else
			{
			Hstrcpy ( lpContext, "Forward Declarations\0" ) ;
			}
		}

	
	/*  Look for end of forwards section  */
	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "end forward\0" ) ;
 	if (iRetVal == 0)
		{
	   	Hstrcpy ( lpContext, "Object Type Definition\0" ) ;
		goto GetLine  ;
		}

	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "type variables\0" ) ;
 	if (iRetVal == 0)
		{
	   	Hstrcpy ( lpContext, "Instance Variables\0" ) ;
		goto GetLine  ;
		}

	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "shared variables\0" ) ;
 	if (iRetVal == 0)
		{
	   	Hstrcpy ( lpContext, "Shared Variables\0" ) ;
		goto GetLine  ;
		}

	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "forward prototypes\0" ) ;
 	if (iRetVal == 0)
		{
	   	Hstrcpy ( lpContext, "Function Prototypes\0" ) ;
		goto GetLine  ;
		}

	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "event type\0" ) ;
 	if (iRetVal == 0)
		{
		/*  This is only an event declaration, skip it  */
		goto GetLine  ;
		}

	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "event \0" ) ;
 	if (iRetVal == 0)
		{
		strcpy ( lpTest, lpReturn ) ;
		iRetVal = (PBINT) Hstrstrn( lpTest, (LPSTR) "pbm_\0" ) ;
		if (iRetVal >= 0 )
			{
			/*  This is only an event declaration, skip it  */
			goto GetLine  ;
			}

		iRetVal = (PBINT) Hstrstrn( lpTest, (LPSTR) ";\0" ) ;
		if (iRetVal >= 0 )
			{	 
			/*  This is event script, save context...
				but let this fall thru so we can check for 
				occurence of string  */
			token		= strtok( lpTest, sepspace ) ;		/*  Extract 'event' keyword */
			lpToken1	= strtok ( NULL, sepsemi ) ;		/*  Extract event name */
			strcpy ( lpTest2, lpToken1) ;
		  	strcpy ( lpContext, lpTest2 ) ;
			strcat ( lpContext, " event for " ) ;
			strcat ( lpContext, lpControl ) ;
			}
		}

	/*  Look for object type definition  */
	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "global type\0" ) ;
	if (iRetVal == 0)
		{
		token		= strtok( lpReturn, sepspace ) ;	/*  Extract 'global' keyword */
		token		= strtok( NULL, sepspace ) ;		/*  Extract 'type' keyword */
		lpToken1	= strtok ( NULL, sepspace ) ;		/*  Extract object name */
		/*  Save control name  */
		strcpy ( lpControl, lpToken1 ) ;
		Hstrcpy ( lpContext, "Object Type Definition\0" ) ;
		goto GetLine  ;
		}

   	/*  Look for control type definition  */
	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "type \0" ) ;
	if (iRetVal == 0)
		{
		token			= strtok( lpReturn, sepspace ) ;				/*  Extract 'type' */
		lpToken1		= strtok ( NULL, sepspace ) ;				/*  Extract control name */
		iRetVal = (PBINT) Hstrstrn( lpToken1, (LPSTR) "variables\0" ) ;
		if (iRetVal < 0)
			{
		  	/*  Save control name  */
			strcpy ( lpControl, lpToken1 ) ;
			}

		/*  Copy information into the arguments  */
		strcpy ( lpContext, "Type Definition for " ) ;
		strcat ( lpContext, lpToken1 ) ;
		goto GetLine  ;
		}

	/*  Look for 'on ... .create' definition  */
	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "on \0" ) ;
	if (iRetVal == 0)
		{
		iRetVal = (PBINT) Hstrstrn(lpReturn, (LPSTR) ".create\0") ;
		if ( iRetVal >= 0)
			{
			token				= strtok( lpReturn, sepspace ) ;			/*  Extract 'on' */
			lpToken1			= strtok ( NULL, sepdot ) ;					/*  Extract control name */
			/*  Copy information into the arguments  */
			strcpy ( lpContext, "Create for " ) ;
			strcat ( lpContext, lpToken1 ) ;
			goto GetLine  ;
			}
		iRetVal = (PBINT) Hstrstrn(lpReturn, (LPSTR) ".destroy\0") ;
		if ( iRetVal >= 0)
			{
			token				= strtok( lpReturn, sepspace ) ;			/*  Extract 'on' */
			lpToken1			= strtok ( NULL, sepdot ) ;					/*  Extract control name */
			/*  Copy information into the arguments  */
			strcpy ( lpContext, "Destroy for " ) ;
			strcat ( lpContext, lpToken1 ) ;
			goto GetLine  ;
			}
	   else
			{		  
			lpToken1			= strtok( lpReturn, sepspace ) ;		/*  Extract 'on' */
			lpToken2			= strtok( NULL, sepsemi ) ;				/*  Extract event name */
 			/*  Copy information into the arguments  */
			strcpy ( lpContext, lpToken2 ) ;
			strcat ( lpContext, " event for " ) ;
			strcat ( lpContext, lpControl ) ;
   			}
		}
	
	/*  Look for functions/subroutines */
	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "public\0" ) ;
   	if (iRetVal == 0) { iFunc = 1 ;	}
	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "private\0" ) ;
   	if (iRetVal == 0) { iFunc = 1 ;	}
   	iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "protected\0" ) ;
   	if (iRetVal == 0) { iFunc = 1 ;	}

	if (iFunc == 1)
		{
		iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "function\0" ) ;
		if (iRetVal >= 0) { iFunc = 2 ;	}
		iRetVal = (PBINT) Hstrstrn( lpReturn, (LPSTR) "subroutine\0" ) ;
		if (iRetVal >= 0) { iFunc = 3 ;	}	  
		}

	strcpy ( lpTest, lpReturn ) ;

	if (iFunc == 2)	
		{	
		token		= strtok( lpTest, sepspace ) ;	/*  Extract public/protected */
		token		= strtok( NULL, sepspace ) ;		/*  Extract 'function' */
		token		= strtok ( NULL, sepspace )	;		/*  Extract return type	 */
		lpToken1	= strtok ( NULL, sepparen ) ;		/*  Extract function name */
		strcpy ( lpContext, lpToken1 ) ;
		strcat ( lpContext, " function" ) ;
		}
	else
	if (iFunc == 3 )
		{
		token		= strtok( lpTest, sepspace ) ;	/*  Extract public/protected */
		token		= strtok( NULL, sepspace ) ;			/*  Extract 'subroutine' */
		lpToken1	= strtok ( NULL, sepparen ) ;		/*  Extract function name */
		strcpy ( lpContext, lpToken1 ) ;
		strcat ( lpContext, " subroutine" ) ;
		}

	/*  Now see if search value is in the line  */
	iRetSrch = (PBINT) Hstrstrn( lpReturn, lpSearch ) ;
	if (iRetSrch >= 0)
		{
		Hstrcpy ( lpLine, lpReturn ) ;
		return lOffSet ;
  		}

	if ( lOffSet == -1 )
		{
		return -1 ;
		}

	iStart = 1 ;
	Hstrcpy ( lpLine, lpReturn ) ;
	goto GetLine  ;
}

/* ========================================================================	*/
/*	PBGetLine: Obtains a line from the object source
/*	Added by Jane Cantz on 11/2/96
/* ========================================================================	*/
long WINAPI PBGetLine(HPSTR hpObjBuf, long lStart, LPSTR lpReturn, long lSize)
{
	HPSTR hpTmp ;
	long lCurIndex, lEndPhrase ;
	char chEOL ;
		
	lEndPhrase = -1 ;
	if (lStart == -1) 
		{
		lStart = 1 ;
		}
	if ((lStart - 1) >= lSize)
	{
		return -1 ;
	}
	if (lStart >= lSize)
	{
		return -1 ;
	}

	
	for (lCurIndex = lStart ; (hpObjBuf[lCurIndex] != '\0') ; ++lCurIndex)
	{
		chEOL = hpObjBuf[lCurIndex] ;

		if (hpObjBuf[lCurIndex] == '\n')
		{
			++lCurIndex ;
			lEndPhrase = lCurIndex ;
			
			if (lEndPhrase == -1)
			{
				/*  ERROR_PHRASE Condition, should never happen  */
				return -1 ;
			}
			else
			{
				break ;
			}
		}

 	}
	
	if (lEndPhrase == -1)
	{
		/*  ERROR_PHRASE Condition, should never happen  */
		return -1 ;
	}

	/*  Now delimiting Offsets for the string have been found.
	    Go for copying it to the Phrase buffer.  */
	hpTmp = (HPSTR) &(hpObjBuf[lStart]) ;
	
	if (chEOL == ';')
		{
		if (lEndPhrase - lStart > MAX_CONTEXT_LENGTH)
			{
			/*  Too large, just ignore the phrase, return next phrase  */
			return (PBGetLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
			}
		else if (lEndPhrase - lStart - 1 == 0)
			{
			/*  empty line, so bypass  */
			return (PBGetLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
			}
		else
			{
 			Hstrncpy(lpReturn, hpTmp, (lEndPhrase - lStart - 1)) ;
			}
	
		return lEndPhrase ;
	  	}

	if (lEndPhrase - lStart > MAX_CONTEXT_LENGTH)
	{
		/*  Too large, just ignore the phrase, return next phrase  */
		return (PBGetLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
	}
	else if (lEndPhrase - lStart - 2 == 0)
	{
		/*  empty line, so bypass  */
		return (PBGetLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
	}

	else
	{
		Hstrncpy(lpReturn, hpTmp, (lEndPhrase - lStart - 2)) ;
	}
	
	return lEndPhrase++ ;
}

/* ========================================================================	*/
/*	PBGetDWLine: Obtains a line from the datawindow object source
/*	Added by Jane Cantz on 11/2/96
/* ========================================================================	*/
long WINAPI PBGetDWLine(HPSTR hpObjBuf, long lStart, LPSTR lpReturn, long lSize)
{
	HPSTR hpTmp ;

	long lCurIndex, lEndPhrase ;
	char chEOL ;
	
	lEndPhrase = -1 ;
	if (lStart == -1) 
		{
		lStart = 1 ;
		}
	if ((lStart - 1) >= lSize)
	{
		return -1 ;
	}
	if (lStart >= lSize)
	{
		return -1 ;
	}
 	
	for (lCurIndex = lStart ; (hpObjBuf[lCurIndex] != '\0') ; ++lCurIndex)
	{
		chEOL = hpObjBuf[lCurIndex] ;

		if (hpObjBuf[lCurIndex] == ' ')
		{
			++lCurIndex ;
			lEndPhrase = lCurIndex ;
			
			if (lEndPhrase == -1)
			{
				/*  ERROR_PHRASE Condition, should never happen  */
				return -1 ;
			}
			else
			{
				break ;
			}
		}

 	}
	
	if (lEndPhrase == -1)
	{
		/*  ERROR_PHRASE Condition, should never happen  */
		return -1 ;
	}

	/*  Now delimiting Offsets for the string have been found.
	    Go for copying it to the Phrase buffer.  */
	hpTmp = (HPSTR) &(hpObjBuf[lStart]) ;
	
	if (chEOL == ' ')
		{
		if (lEndPhrase - lStart > MAX_CONTEXT_LENGTH)
			{
			/*  Too large, just ignore the phrase, return next phrase  */
			return (PBGetDWLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
			}
		else if (lEndPhrase - lStart - 1 == 0)
			{
			/*  empty line, so bypass  */
			return (PBGetDWLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
			}
		else
			{
			Hstrncpy(lpReturn, hpTmp, (lEndPhrase - lStart - 1)) ;
			}
	
		return lEndPhrase ;
	  	}

	if (lEndPhrase - lStart > MAX_CONTEXT_LENGTH)
	{
		/*  Too large, just ignore the phrase, return next phrase  */
		return (PBGetDWLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
	}
	else if (lEndPhrase - lStart - 2 == 0)
	{
		/*  empty line, so bypass  */
		return (PBGetDWLine(hpObjBuf, lEndPhrase++, lpReturn, lSize)) ;
	}

	else
	{
		Hstrncpy(lpReturn, hpTmp, (lEndPhrase - lStart - 2)) ;
	}
	
	return lEndPhrase++ ;
}