Beispiel #1
0
//=============================================================================
// Scanner::GetNextString
// 
// Return the next string of characters pointed at by position, where each
// character comforms to the classification determined by includeMask
// and does not conform to excludeMask and is not equal to the delimiter.
// Return the next character in the input stream in nextChar.  The 
// caller can reference this to see if the delimiter was reached.
// If a string is returned then position is advanced accordingly.
//=============================================================================
String Scanner::GetNextStringDelimited(ScannerPosition& position,
                                       CharTypeFacet::Mask includeMask,
                                       CharTypeFacet::Mask excludeMask,
                                       CharType delimiter,
                                       Character& nextChar,
									   size_t maxSize)
{
	String strRet;
	size_t count = 0;
	while (true)
	{
		nextChar = PeekNextCharacter(position);
		if ( (CharTypeFacet::IsCharType(nextChar, includeMask) || includeMask == CharTypeFacet::Any)
		     && !CharTypeFacet::IsCharType(nextChar, excludeMask)
		     && nextChar != delimiter 
			 && !nextChar.isEOF())
		{
			GetNextCharacter(position).appendToString(strRet);
			
			if(maxSize && count++ > maxSize)
				break;
		}
		else
			break;
	}
	return strRet;
}
///---------------------------------------------------------------------------------
///
///---------------------------------------------------------------------------------
void GetNextString( char** out_string, char** line )
{
    char *pos = *line;
    char *out = *out_string;

    // nothing to do, doesn't start with a quote;
    if (*pos != QUOTE) {
        return;
    }

    ++pos;
    while ((*pos != NULL) && (*pos != QUOTE)) {
        char nextChar = GetNextCharacter( &pos );
        *out = nextChar;
        ++out;
        ++pos;
    }

    if ((*pos) == QUOTE) {
        ++pos;
    }

    *out_string = out;
    *line = pos;
}
Beispiel #3
0
static void GetNextString(char **out_stream, char **stream)
{
	char *s = *stream;
	char *out = *out_stream;

	// nothing to do, doesn't start with a quote;
	if (*s != QUOTE) {
		return;
	}

	++s;
	while ((*s != NULL) && (*s != QUOTE)) {
		char c = GetNextCharacter(&s);
		*out = c;
		++out;
		++s;
	}

	if ((*s) == QUOTE) {
		++s;
	}

	*out_stream = out;
	*stream = s;
}
Beispiel #4
0
//==============================================================================
// Scanner::Skip
//
// Skip n UCS4 Characters
//==============================================================================
void Scanner::Skip(ScannerPosition& position, size_t n)
{
	for(size_t i=0; i<n; i++)
	{
		GetNextCharacter(position);
	}
}
void C4MenuItem::DoTextProgress(int32_t &riByVal)
{
	// any progress to be done?
	if (TextDisplayProgress<0) return;
	// if this is an option or empty text, show it immediately
	if (IsSelectable || !*Caption) { TextDisplayProgress=-1; return; }
	// normal text: move forward in unbroken message, ignoring markup
	StdStrBuf sText(Caption);
	C4Markup MarkupChecker(false);
	const char *szPos = sText.getPtr(std::min<int>(TextDisplayProgress, sText.getLength()));
	while (riByVal && *szPos)
	{
		MarkupChecker.SkipTags(&szPos);
		if (!*szPos) break;
		--riByVal;

		// Advance one UTF-8 character
		uint32_t c = GetNextCharacter(&szPos);
		// Treat embedded images {{XXX}} as one entity
		if(c == '{' && *szPos == '{')
		{
			int32_t end = SCharPos('}', szPos);
			if(end > 0 && szPos[end+1] == '}')
				szPos += end + 2;
		}
	}
	if (!*szPos)
		TextDisplayProgress=-1;
	else
		TextDisplayProgress = szPos - Caption;
}
Beispiel #6
0
//==============================================================================
// Scanner::SkipToDelimiter
//
//==============================================================================
CharType Scanner::SkipToDelimiter(ScannerPosition& position,
                                  CharType delim, CharTypeFacet::Mask includeMask)
{
	Character x; 
	while( (x = PeekNextCharacter(position)) != delim && CharTypeFacet::IsCharType(x, includeMask) && !x.isEOF())
	{
		GetNextCharacter(position);
	}
	return x.first();
}
Beispiel #7
0
//=============================================================================
// Scanner::skipWhiteSpace
// 
//=============================================================================
size_t Scanner::SkipWhiteSpace(ScannerPosition& position)
{
	size_t skipCount(0);

	while (CharTypeFacet::IsWhiteSpace(PeekNextCharacter(position)))
	{
		GetNextCharacter(position);
		skipCount++;
	}
	return skipCount;
}
Beispiel #8
0
//=============================================================================
// Scanner::SkipNextCharConstant
// 
// Called by the  parser to test the input stream against a given character.
// If there is a match, then the input position is incremented and we
// return true, otherwise position remains where it is and we return false.
//=============================================================================
bool Scanner::SkipNextCharConstant(ScannerPosition& position, CharType x)
{
	if(PeekNextCharacter(position) == x)
	{
		GetNextCharacter(position);
		return true;
	}
	else
	{
		return false;
	}
}
Beispiel #9
0
//=============================================================================
// Scanner::SkipNextStringConstant
// 
// Called by the  parser to test the input stream against a given string.
// If there is a match, then the input position is incremented and we
// return true, otherwise position remains where it is and we return false.
//
// Note: Zero length string is fine!
//=============================================================================
bool Scanner::SkipNextStringConstant(ScannerPosition& position, const String& str)
{
	ScannerPosition myPosition = position;
	
	for(size_t i=0; i<str.size(); i++)
	{
		if(GetNextCharacter(myPosition) != str[i])
			return false;
	}

	// all the string's characters matched the input stream, so advance position
	// and return true.
	position = myPosition;
	return true;
}
Beispiel #10
0
//=============================================================================
// Scanner::PeekNextStringConstant
// 
// Simply test if the next n characters in the input stream match exactly
// the characters of the string str.
//=============================================================================
bool Scanner::PeekNextStringConstant(ScannerPosition& position, const String& str)
{
	QC_DBG_ASSERT(!str.empty());
	ScannerPosition myPosition = position;
	
	for(size_t i=0; i<str.size(); i++)
	{
		if(GetNextCharacter(myPosition) != str[i])
			return false;
	}

	// all the string's characters matched the input stream, so 
	// return true.
	return true;
}
Beispiel #11
0
//=============================================================================
// Scanner::SkipNextStringConstant
// 
// Called by the  parser to test the input stream against a given string.
// If there is a match, then the input position is incremented and we
// return true, otherwise position remains where it is and we return false.
//
// Note: Overridden for const char*
//=============================================================================
bool Scanner::SkipNextStringConstant(ScannerPosition& position, const char* pStr)
{
	QC_DBG_ASSERT(pStr!=0);
	ScannerPosition myPosition = position;
	size_t stringLen = strlen(pStr);
	
	for(size_t i=0; i<stringLen; i++)
	{
		if(GetNextCharacter(myPosition) != pStr[i])
			return false;
	}

	// all the string's characters matched the input stream, so advance position
	// and return true.
	position = myPosition;
	return true;
}
Beispiel #12
0
//=============================================================================
// Scanner::SkipToDelimiters
// 
// Skip the input position up to (but not including) any one of the passed
// delimiter strings or EOF - whatever comes first.
//
// Return the index number of the string found, or -1
//
// Note the delims parameter is an array of char *s.  We do not pass CharType
// for the simple reason that all delimiters will appear in the ascii range.
//=============================================================================
int Scanner::SkipToDelimiters(ScannerPosition& position, size_t numDelimiters,
                              const char* delims[])
{
	Character nextChar; 
	while( (nextChar=PeekNextCharacter(position)).isEOF() != true)
	{
		for(size_t i=0; i<numDelimiters; i++)
		{
			if(PeekNextStringConstant(position, delims[i]))
			{
				return (int)i;
			}
		}
		GetNextCharacter(position);
	}
	return -1;
}
Beispiel #13
0
//==============================================================================
// Scanner::GetNextContigHexString
//
//==============================================================================
String Scanner::GetNextContigHexString(ScannerPosition& position, Character& nextChar)
{
	String strRet;

	while (true)
	{
		nextChar = PeekNextCharacter(position);

		if(nextChar.isHexDigit())
		{
			GetNextCharacter(position).appendToString(strRet);
		}
		else
		{
			break;
		}
	}

	return strRet;

}
Beispiel #14
0
//=============================================================================
// Scanner::SkipToDelimiter
// 
// Skip the input position up to (but not including) delimiter or EOF, 
// whatever comes first.
//
// Return the next character in the iunput stream.
//=============================================================================
CharType Scanner::SkipToDelimiter(ScannerPosition& position,
                                  const String& delim, CharTypeFacet::Mask includeMask)
{
	QC_DBG_ASSERT(!delim.empty());
	const CharType firstDelimChar = delim[0]; 

	CharType nextChar;
	while((nextChar = SkipToDelimiter(position, firstDelimChar, includeMask)) == firstDelimChar)
	{
		if(PeekNextStringConstant(position, delim))
		{
			break;
		}
		else
		{
			GetNextCharacter(position);
		}
	}

	return nextChar;
}
Beispiel #15
0
//=============================================================================
// Scanner::GetNextStringDelimited
// 
// Return the next string of characters pointed at by position, where each
// character comforms to the classification determined by includeMask
// and does not conform to excludeMask and is not equal to the delimiter.
//
// Return the nexr char in the input stream in nextChar.
// If a string is returned then position is advanced accordingly.
//
// Note: For convenience this function is implemented using
// the character version of GetNextStringDelimited.  This could 
// pose a performance problem if it was used extensively.
//=============================================================================
String Scanner::GetNextStringDelimited(ScannerPosition& position,
	                                   CharTypeFacet::Mask includeMask,
	                                   CharTypeFacet::Mask excludeMask,
	                                   const String& delimiter,
	                                   Character& nextChar)
{
	String strRet;
	QC_DBG_ASSERT(!delimiter.empty());
	const CharType cDelim = delimiter.at(0);
	while (true)
	{
		//
		// obtain string up to first character of the delimiter string
		//
		strRet += GetNextStringDelimited(position,
	                                     includeMask,
	                                     excludeMask,
	                                     cDelim,
	                                     nextChar);

		if(nextChar == cDelim)
		{
			if(PeekNextStringConstant(position, delimiter))
			{
				break;
			}
			else
			{
				GetNextCharacter(position).appendToString(strRet);
			}
		}
		else
		{
			// either at EOF or an illegal character!
			break;
		}
	}

	return strRet;
}
Beispiel #16
0
//==============================================================================
// Scanner::GetNextContigDecimalString
//
//==============================================================================
String Scanner::GetNextContigDecimalString(ScannerPosition& position,
                                           bool /*bAllowDecimalPoint*/,
                                           Character& nextChar)
{
	String strRet;

	while (true)
	{
		nextChar = PeekNextCharacter(position);

		if(nextChar.isDigit())
		{
			GetNextCharacter(position).appendToString(strRet);
		}
		else
		{
			break;
		}
	}

	return strRet;
}
///---------------------------------------------------------------------------------
///
///---------------------------------------------------------------------------------
char* GetNextToken( char** line )
{
    char *pos = *line;
    char *token = nullptr;

    // get up the first real character
    while (IsWhitespace( *pos )) {
        ++pos;
    }

    if (*pos != NULL) {
        token = pos;
        char *out = pos;

        if (*pos == QUOTE) {
            GetNextString( &out, &pos );
        }
        else {
            while (!IsWhitespace( *pos ) && (*pos != NULL)) {
                char nextChar = GetNextCharacter( &pos );
                *out = nextChar;
                ++out;
                ++pos;
            }
        }

        // move past the possible "last position" we left on
        // since we're NULLing it out for our token
        if (*pos != NULL) {
            ++pos;
        }
        *out = NULL;
    }

    *line = pos;
    return token;
}
Beispiel #18
0
static char* GetNextToken(char **stream)
{
	char *s = *stream;
	char *token = nullptr;
	// get up the first real character
	while (IsWhitespace(*s)) {
		++s;
	}

	if (*s != NULL) {
		token = s;
		char *out = s;

		if (*s == QUOTE) {
			GetNextString(&out, &s);
		}
		else {
			while (!IsWhitespace(*s) && (*s != NULL)) {
				char c = GetNextCharacter(&s);
				*out = c;
				++out;
				++s;
			}
		}

		// move past the possible "last position" we left on
		// since we're NULLing it out for our token
		if (*s != NULL) {
			++s;
		}
		*out = NULL;
	}

	*stream = s;
	return token;
}
Beispiel #19
0
BOOLEAN
DoTextEntry (PTEXTENTRY_STATE pTES)
{
	wchar_t ch;
	UNICODE *pStr;
	UNICODE *CacheInsPt;
	int CacheCursorPos;
	int len;
	BOOLEAN changed = FALSE;

	if (GLOBAL (CurrentActivity) & CHECK_ABORT)
		return (FALSE);

	if (!pTES->Initialized)
	{	// init basic vars
		int lwlen;

		pTES->InputFunc = DoTextEntry;
		pTES->Success = FALSE;
		pTES->Initialized = TRUE;
		pTES->JoystickMode = FALSE;
		pTES->UpperRegister = TRUE;
	
		// init insertion point
		if ((size_t)pTES->CursorPos > utf8StringCount (pTES->BaseStr))
			pTES->CursorPos = utf8StringCount (pTES->BaseStr);
		pTES->InsPt = skipUTF8Chars (pTES->BaseStr, pTES->CursorPos);

		// load joystick alphabet
		pTES->JoyAlphaString = CaptureStringTable (
				LoadStringTable (JOYSTICK_ALPHA_STRTAB));
		pTES->JoyAlpha = LoadJoystickAlpha (
				SetAbsStringTableIndex (pTES->JoyAlphaString, 0),
				&pTES->JoyAlphaLength);
		pTES->JoyUpper = LoadJoystickAlpha (
				SetAbsStringTableIndex (pTES->JoyAlphaString, 1),
				&pTES->JoyRegLength);
		pTES->JoyLower = LoadJoystickAlpha (
				SetAbsStringTableIndex (pTES->JoyAlphaString, 2),
				&lwlen);
		if (lwlen != pTES->JoyRegLength)
		{
			if (lwlen < pTES->JoyRegLength)
				pTES->JoyRegLength = lwlen;
			log_add (log_Warning, "Warning: Joystick upper-lower registers"
					" size mismatch; using the smallest subset (%d)",
					pTES->JoyRegLength);
		}

		pTES->CacheStr = HMalloc (pTES->MaxSize * sizeof (*pTES->CacheStr));
		
		DoInput (pTES, TRUE);

		if (pTES->CacheStr)
			HFree (pTES->CacheStr);
		if (pTES->JoyLower)
			HFree (pTES->JoyLower);
		if (pTES->JoyUpper)
			HFree (pTES->JoyUpper);
		if (pTES->JoyAlpha)
			HFree (pTES->JoyAlpha);
		DestroyStringTable ( ReleaseStringTable (pTES->JoyAlphaString));

		return pTES->Success;
	}

	pStr = pTES->InsPt;
	len = strlen (pStr);
	// save a copy of string
	CacheInsPt = pTES->InsPt;
	CacheCursorPos = pTES->CursorPos;
	memcpy (pTES->CacheStr, pTES->BaseStr, pTES->MaxSize);

	// process the pending character buffer
	ch = GetNextCharacter ();
	if (!ch && PulsedInputState.menu[KEY_MENU_ANY])
	{	// keyboard repeat, but only when buffer empty
		ch = GetLastCharacter ();
	}
	while (ch)
	{
		UNICODE chbuf[8];
		int chsize;

		pTES->JoystickMode = FALSE;

		chsize = getStringFromChar (chbuf, sizeof (chbuf), ch);
		if (isWidePrintChar (ch) && chsize > 0)
		{
			if (pStr + len - pTES->BaseStr + chsize < pTES->MaxSize)
			{	// insert character, when fits
				memmove (pStr + chsize, pStr, len + 1);
				memcpy (pStr, chbuf, chsize);
				pStr += chsize;
				++pTES->CursorPos;
				changed = TRUE;
			}
			else
			{	// does not fit
				PlayMenuSound (MENU_SOUND_FAILURE);
			}
		}
		ch = GetNextCharacter ();
	}

	if (PulsedInputState.menu[KEY_MENU_DELETE])
	{
		if (len)
		{
			joy_char_t ch;
			
			ReadOneChar (&ch, pStr);
			memmove (pStr, pStr + ch.len, len - ch.len + 1);
			len -= ch.len;
			changed = TRUE;
		}
	}
	else if (PulsedInputState.menu[KEY_MENU_BACKSPACE])
	{
		if (pStr > pTES->BaseStr)
		{
			UNICODE *prev = skipUTF8Chars (pTES->BaseStr,
					pTES->CursorPos - 1);
			
			memmove (prev, pStr, len + 1);
			pStr = prev;
			--pTES->CursorPos;
			changed = TRUE;
		}
	}
	else if (PulsedInputState.menu[KEY_MENU_LEFT])
	{
		if (pStr > pTES->BaseStr)
		{
			UNICODE *prev = skipUTF8Chars (pTES->BaseStr,
					pTES->CursorPos - 1);

			pStr = prev;
			len += (prev - pStr);
			--pTES->CursorPos;
			changed = TRUE;
		}
	}
	else if (PulsedInputState.menu[KEY_MENU_RIGHT])
	{
		if (len > 0)
		{
			joy_char_t ch;
			
			ReadOneChar (&ch, pStr);
			pStr += ch.len;
			len -= ch.len;
			++pTES->CursorPos;
			changed = TRUE;
		}
	}
	else if (PulsedInputState.menu[KEY_MENU_HOME])
	{
		if (pStr > pTES->BaseStr)
		{
			pStr = pTES->BaseStr;
			len = strlen (pStr);
			pTES->CursorPos = 0;
			changed = TRUE;
		}
	}
	else if (PulsedInputState.menu[KEY_MENU_END])
	{
		if (len > 0)
		{
			pTES->CursorPos += utf8StringCount (pStr);
			pStr += len;
			len = 0;
			changed = TRUE;
		}
	}
	
	if (pTES->JoyAlpha && (
			PulsedInputState.menu[KEY_MENU_UP] ||
			PulsedInputState.menu[KEY_MENU_DOWN] ||
			PulsedInputState.menu[KEY_MENU_PAGE_UP] ||
			PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) )
	{	// do joystick text
		joy_char_t ch;
		joy_char_t newch;
		joy_char_t cmpch;
		int i;

		pTES->JoystickMode = TRUE;

		if (len)
			ReadOneChar (&ch, pStr);
		else
			ch = pTES->JoyAlpha[0];
		
		newch = ch;
		JoyCharToUpper (&cmpch, &ch, pTES);

		// find current char in the alphabet
		i = JoyCharFindIn (&cmpch, pTES->JoyAlpha, pTES->JoyAlphaLength);

		if (PulsedInputState.menu[KEY_MENU_UP])
		{
			--i;
			if (i < 0)
				i = pTES->JoyAlphaLength - 1;
			newch = pTES->JoyAlpha[i];
		}
		else if (PulsedInputState.menu[KEY_MENU_DOWN])
		{
			++i;
			if (i >= pTES->JoyAlphaLength)
				i = 0;
			newch = pTES->JoyAlpha[i];
		}

		if (PulsedInputState.menu[KEY_MENU_PAGE_UP] ||
				PulsedInputState.menu[KEY_MENU_PAGE_DOWN])
		{
			if (len)
			{	// single char change
				if (JoyCharIsLower (&newch, pTES))
					JoyCharToUpper (&newch, &newch, pTES);
				else
					JoyCharToLower (&newch, &newch, pTES);
			}
			else
			{	// register change
				pTES->UpperRegister = !pTES->UpperRegister;
			}
		}
		else
		{	// check register
			if (pTES->UpperRegister)
				JoyCharToUpper (&newch, &newch, pTES);
			else
				JoyCharToLower (&newch, &newch, pTES);
		}

		if (strcmp (newch.enc, ch.enc) != 0)
		{	// new char is different, put it in
			if (len)
			{	// change current -- this is messy with utf8
				int l = len - ch.len;
				if (pStr + l - pTES->BaseStr + newch.len < pTES->MaxSize)
				{
					// adjust other chars if necessary
					if (newch.len != ch.len)
						memmove (pStr + newch.len, pStr + ch.len, l + 1);

					memcpy (pStr, newch.enc, newch.len);
					len = l + newch.len;
					changed = TRUE;
				}
			}
			else
			{	// append
				if (pStr + len - pTES->BaseStr + newch.len < pTES->MaxSize)
				{
					memcpy (pStr, newch.enc, newch.len);
					pStr[newch.len] = '\0';
					len += newch.len;
					changed = TRUE;
				}
				else
				{	// does not fit
					PlayMenuSound (MENU_SOUND_FAILURE);
				}
			}
		}
	}
	
	if (PulsedInputState.menu[KEY_MENU_SELECT])
	{	// done entering
		pTES->Success = TRUE;
		return FALSE;
	}
	else if (PulsedInputState.menu[KEY_MENU_EDIT_CANCEL])
	{	// canceled entering
		pTES->Success = FALSE;
		return FALSE;
	}

	pTES->InsPt = pStr;

	if (changed && pTES->ChangeCallback)
	{
		if (!pTES->ChangeCallback (pTES))
		{	// changes not accepted - revert
			memcpy (pTES->BaseStr, pTES->CacheStr, pTES->MaxSize);
			pTES->InsPt = CacheInsPt;
			pTES->CursorPos = CacheCursorPos;

			PlayMenuSound (MENU_SOUND_FAILURE);
		}
	}
		
	if (pTES->FrameCallback)
		return pTES->FrameCallback (pTES);

	return TRUE;
}
Beispiel #20
0
//=============================================================================
// Scanner::GetNextCharacterImpl
// 
// Return the next character pointed at by position and advance position.
//
// Note: Notice the similarity to PeekNextChar - basically doing the same
//       job without advancing the position.  Would like to use common 
//       routine - but without the expense of run-time performance.
//=============================================================================
Character Scanner::GetNextCharacterImpl(ScannerPosition& position)
{
	Character ret = Character::EndOfFileCharacter;

	//
	// Because position.m_rpBuffer is dereferenced several times, it aids 
	// performance to take a local copy.
	//
	Buffer* pBuffer = position.m_rpBuffer.get();

	// 
	// If we have reached the end of the available portion of the buffer
	// then try and read some more.
	// 
	// The result of this is that there should be at least one character
	// more to read or the buffer is at the end of the Entity, or the
	// burrfer is full and we need to move to the next one.
	//
	if (position.m_bufferOffset == pBuffer->m_used)
	{
		pBuffer->read();
	}

	//
	// If there is unread data in the buffer, then that's easy
	// take the Char sequence and increment position by its length
	//
	const size_t charAvailable = (pBuffer->m_used - position.m_bufferOffset);
	if(charAvailable)
	{
		ret = Character(pBuffer->m_pData+position.m_bufferOffset, charAvailable);
		position.m_bufferOffset+=ret.length();
	}
	else if(!pBuffer->m_bEOF)
	{
		// Otherwise, if the current buffer is not the last in line (eof)
		// we want to Get the next buffer.  It is likely that this involves
		// creating (and chaining) a new buffer - but it might not if we have
		// been here before courtesy of a different streamPosition object.
		// Whatever, the result will be that we can chain forward using the
		// rcpNext member.

		Buffer* pNextBuffer = pBuffer->m_rpNext.get();
		
		// Advance position to the Next buffer
		position.m_rpBuffer = pNextBuffer;
		position.m_bufferOffset = 0;

		if(pNextBuffer->m_used)
		{
			// Take the available Char sequence and increment position by its length
			ret = Character(pNextBuffer->m_pData, pNextBuffer->m_used);
			position.m_bufferOffset+=ret.length();
		}
	}


	//
	// If the ScannerPosition allows us to process the next position in the
	// chain then we will do so.
	//
	if(ret.isEOF() && position.m_pNext)
	{
		switch (position.m_eofAction)
		{
		case ScannerPosition::space:
			position.m_eofAction = ScannerPosition::skip;
			return chSpace;
		case ScannerPosition::skip:
			position = ScannerPosition(*position.m_pNext);
			return GetNextCharacter(position);
		case ScannerPosition::softEOF:
			break;
		default:
			QC_DBG_ASSERT(false);
		}
	}
	else
	{
		//
		// Update the StreamPosition to reflect the latest gotten Char
		// Note that the space generated above does not increment the StreamPosition
		if(!ret.isEOF())
		{
			position.m_streamPosition.incrementByChar(ret);
		}
	}

	return ret;
}