Beispiel #1
0
// Get one line from a string.
// A line is terminated with either CRLF (DOS/Windows),
// LF (Unix, MacOS X), or CR (old MacOS).
// The end of the string is reached when **startNext == '\0'.
// NULL is returned if the string is not valid UTF8. In this case
// *end points to the first invalid character (or the character before if
// it was a LF), and *startNext to the start of the next (possibly invalid
// too) character.
unsigned char *
getLineFromString(const unsigned char *start, const unsigned char **end,
		const unsigned char **startNext) {
	const unsigned char *ptr = start;
	const unsigned char *lastPtr;
	wchar_t ch;

	// Search for the first newline.
	for (;;) {
		if (*ptr == '\0') {
			*end = ptr;
			*startNext = ptr;
			return (unsigned char *) start;
		}
		lastPtr = ptr;
		ch = getCharFromString(&ptr);
		if (ch == '\0') {
			// Bad string
			*end = lastPtr;
			*startNext = ptr;
			return NULL;
		}
		if (ch == '\n') {
			*end = lastPtr;
			if (*ptr == '\0'){
				// LF at the end of the string.
				*startNext = ptr;
				return (unsigned char *) start;
			}
			ch = getCharFromString(&ptr);
			if (ch == '\0') {
				// Bad string
				return NULL;
			}
			if (ch == '\r') {
				// LFCR
				*startNext = ptr;
			} else {
				// LF
				*startNext = *end;
			}
			return (unsigned char *) start;
		} else if (ch == '\r') {
			*end = lastPtr;
			*startNext = ptr;
			return (unsigned char *) start;
		} // else: a normal character
	}
}
Beispiel #2
0
wchar_t
getCharFromStringN(const unsigned char **ptr, const unsigned char *end) {
	size_t numBytes;

	if (*ptr == end)
		goto err;

	if (**ptr < 0x80) {
		numBytes = 1;
	} else if ((**ptr & 0xe0) == 0xc0) {
		numBytes = 2;
	} else if ((**ptr & 0xf0) == 0xe0) {
		numBytes = 3;
	} else if ((**ptr & 0xf8) == 0xf0) {
		numBytes = 4;
	} else
		goto err;

	if (*ptr + numBytes > end)
		goto err;

	return getCharFromString(ptr);

err:
	*ptr = end;
	return 0;
}
Beispiel #3
0
// TODO: this is not implemented with respect to collating order
int
utf8StringCompare (const unsigned char *str1, const unsigned char *str2)
{
#if 0
	// wchar_t comparing version
	wchar_t ch1;
	wchar_t ch2;

	for (;;)
	{
		int cmp;
		
		ch1 = getCharFromString(&str1);
		ch2 = getCharFromString(&str2);
		if (ch1 == '\0' || ch2 == '\0')
			break;

		cmp = utf8CompareChar (ch1, ch2);
		if (cmp != 0)
			return cmp;
	}

	if (ch1 != '\0')
	{
		// ch2 == '\0'
		// str2 ends, str1 continues
		return 1;
	}
	
	if (ch2 != '\0')
	{
		// ch1 == '\0'
		// str1 ends, str2 continues
		return -1;
	}
	
	// ch1 == '\0' && ch2 == '\0'.
	// Strings match completely.
	return 0;
#else
	// this will do for now
	return strcmp (str1, str2);
#endif
}
Beispiel #4
0
size_t
utf8StringCount(const unsigned char *start) {
	size_t count = 0;
	wchar_t ch;

	for (;;) {
		ch = getCharFromString(&start);
		if (ch == '\0')
			return count;
		count++;
	}
}
Beispiel #5
0
unsigned char *
skipUTF8Chars(const unsigned char *ptr, size_t num) {
	wchar_t ch;
	const unsigned char *oldPtr;

	while (num--) {
		oldPtr = ptr;
		ch = getCharFromString(&ptr);
		if (ch == '\0')
			return (unsigned char *) oldPtr;
	}
	return (unsigned char *) ptr;
}
Beispiel #6
0
// Locates a wide char (ch) in a UTF-8 string (pStr)
// returns the char positions when found
//  -1 when not found
int
utf8StringPos (const unsigned char *pStr, wchar_t ch)
{
	int pos;
 
	for (pos = 0; *pStr != '\0'; ++pos)
	{
		if (getCharFromString (&pStr) == ch)
			return pos;
	}

	if (ch == '\0' && *pStr == '\0')
		return pos;

	return -1;
}
Beispiel #7
0
char
parseIntNumber (std::string str, int& nb)
{
   nb = 0;
   // FIXME This is so ugly it hurts...
   if (getCharFromString(str.c_str(), nb))
   {
      return 'c';
   }
   else if (getShortFromString(str.c_str(), nb))
   {
      return 's';
   }
   else if (getIntFromString(str.c_str(), nb))
   {
      return 'i';
   }
   return '\0';
}
Beispiel #8
0
// See getStringFromWideN() for functionality
//  the only difference is that the source string (start) length is
//  calculated by searching for 0-term
size_t
getWideFromString(wchar_t *wstr, size_t maxcount, const unsigned char *start)
{
	wchar_t *next;

	if (maxcount == 0)
		return 0;

	// always leave room for 0-term
	--maxcount;

	for (next = wstr; maxcount > 0; ++next, --maxcount)
	{
		*next = getCharFromString(&start);
		if (*next == 0)
			break;
	}

	*next = 0; // term

	return next - wstr;
}
Beispiel #9
0
// This function calculates how much of a string can be fitted within
// a specific width, up to a newline or terminating \0.
// pText is the text to be fitted. pText->CharCount will be set to the
// number of characters that fitted.
// startNext will be filled with the start of the first word that
// doesn't fit in one line, or if an entire line fits, to the character
// past the newline, or if the entire string fits, to the end of the
// string.
// maxWidth is the maximum number of pixels that a line may be wide
//   ASSUMPTION: there are no words in the text wider than maxWidth
// maxChars is the maximum number of characters (not bytes) that are to
// be fitted.
// TRUE is returned if a complete line fitted
// FALSE otherwise
BOOLEAN
getLineWithinWidth(TEXT *pText, const char **startNext,
		SIZE maxWidth, COUNT maxChars)
{
	BOOLEAN eol;
			// The end of the line of text has been reached.
	BOOLEAN done;
			// We cannot add any more words.
	RECT rect;
	COUNT oldCount;
	const char *ptr;
	const char *wordStart;
	UniChar ch;
	COUNT charCount;

	//GetContextClipRect (&rect);

	eol = FALSE;	
	done = FALSE;
	oldCount = 1;
	charCount = 0;
	ch = '\0';
	ptr = pText->pStr;
	for (;;)
	{
		wordStart = ptr;

		// Scan one word.
		for (;;)
		{
			if (*ptr == '\0')
			{
				eol = TRUE;
				done = TRUE;
				break;
			}
			ch = getCharFromString (&ptr);
			eol = ch == '\0' || ch == '\n' || ch == '\r';
			done = eol || charCount >= maxChars;
			if (done || ch == ' ')
				break;
			charCount++;
		}

		oldCount = pText->CharCount;
		pText->CharCount = charCount;
		TextRect (pText, &rect, NULL);
		
		if (rect.extent.width >= maxWidth)
		{
			pText->CharCount = oldCount;
			*startNext = wordStart;
			return FALSE;
		}

		if (done)
		{
			*startNext = ptr;
			return eol;
		}
		charCount++;
				// For the space in between words.
	}
}
Beispiel #10
0
// status == -1: draw highlighted player dialog option
// status == -2: draw non-highlighted player dialog option
// status == -4: use current context, and baseline from pTextIn
// status ==  1:  draw alien speech; subtitle cache is used
static COORD
add_text (int status, TEXT *pTextIn)
{
	COUNT maxchars, numchars;
	TEXT locText;
	TEXT *pText;
	SIZE leading;
	const char *pStr;
	SIZE text_width;
	int num_lines = 0;
	static COORD last_baseline;
	BOOLEAN eol;
	CONTEXT OldContext = NULL;
	COUNT computerOn = 0;
	
	BatchGraphics ();

	maxchars = (COUNT)~0;
	if (status == 1)
	{
		if (last_subtitle == pTextIn->pStr)
		{
			// draws cached subtitle
			STAMP s;

			s.origin.x = 0;
			s.origin.y = 0;
			s.frame = TextCacheFrame;
			DrawStamp (&s);
			UnbatchGraphics ();
			return last_baseline;
		}
		else
		{
			// draw to subtitle cache; prepare first
			OldContext = SetContext (TextCacheContext);
			ClearDrawable ();

			last_subtitle = pTextIn->pStr;
		}

		text_width = CommData.AlienTextWidth;
		SetContextFont (CommData.AlienFont);
		GetContextFontLeading (&leading);

		pText = pTextIn;
	}
	else if (GetContextFontLeading (&leading), status <= -4)
	{
		text_width = (SIZE) (SIS_SCREEN_WIDTH - RES_SCALE(8) - (TEXT_X_OFFS << 2)); // JMS_GFX

		pText = pTextIn;
	}
	else
	{
		text_width = (SIZE) (SIS_SCREEN_WIDTH - RES_SCALE(8) - (TEXT_X_OFFS << 2)); // JMS_GFX

		switch (status)
		{
			case -3:
				// Unknown. Never reached; color matches the background color.
				SetContextForeGroundColor (
						BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01));
				break;
			case -2:
				// Not highlighted dialog options.
				SetContextForeGroundColor (COMM_PLAYER_TEXT_NORMAL_COLOR);
				break;
			case -1:
				// Currently highlighted dialog option.
				SetContextForeGroundColor (COMM_PLAYER_TEXT_HIGHLIGHT_COLOR);
				break;
		}

		maxchars = pTextIn->CharCount;
		locText = *pTextIn;
		locText.baseline.x -= RES_SCALE(8) - 4 * RESOLUTION_FACTOR; // JMS_GFX
		locText.CharCount = (COUNT)~0;
		locText.pStr = STR_BULLET;
		font_DrawText (&locText);

		locText = *pTextIn;
		pText = &locText;
		pText->baseline.y -= leading;
	}

	numchars = 0;
	pStr = pText->pStr;

	if (status > 0 && (CommData.AlienTextValign &
			(VALIGN_MIDDLE | VALIGN_BOTTOM)))
	{
		num_lines = _count_lines(pText);
		if (CommData.AlienTextValign == VALIGN_BOTTOM)
			pText->baseline.y -= (leading * num_lines);
		else if (CommData.AlienTextValign == VALIGN_MIDDLE)
			pText->baseline.y -= ((leading * num_lines) / 2);
		if (pText->baseline.y < 0)
			pText->baseline.y = 0;
	}

	do
	{
		pText->pStr = pStr;
		pText->baseline.y += leading;

		eol = getLineWithinWidth (pText, &pStr, text_width, maxchars);

		maxchars -= pText->CharCount;
		if (maxchars != 0)
			--maxchars;
		numchars += pText->CharCount;
		
		if (status <= 0)
		{
			// Player dialog option or (status == -4) other non-alien
			// text.
			if (pText->baseline.y < SIS_SCREEN_HEIGHT)
				font_DrawText (pText);

			if (status < -4 && pText->baseline.y >= -status - 10)
			{
				// Never actually reached. Status is never <-4.
				++pStr;
				break;
			}
		}
		else
		{
			// Alien speech
			if (CommData.AlienConv == ORZ_CONVERSATION)
			{
				// BW : special case for the Orz conversations
				// the character $ is recycled as a marker to
				// switch from and to computer font
				
				const char *ptr;
				RECT rect;
				COORD baselinex = pText->baseline.x;
				COORD width = 0;
				COUNT remChars = pText->CharCount;
			        // Remaining chars until end of line within width
				const char *bakptr;
				COUNT bakChars = remChars;
				COUNT bakcompOn = computerOn;
				FONT bakFont = SetContextFont(ComputerFont);
				
				SetContextFont(bakFont);
				ptr = pText->pStr;
				bakptr = ptr;
				
				// We need to manually center the line because
				// the computer font is larger than the Orzfont
				
				// This loop computes the width of the line
				while (remChars > 0)
					{
						while ((*ptr != '$') && remChars > 0)
							{
								getCharFromString (&ptr);
								remChars--;
							}
						
						pText->CharCount -= remChars;
						TextRect (pText, &rect, NULL);
						
						width += rect.extent.width;
						
						if (*ptr == '$')
							{
								getCharFromString (&ptr);
								remChars--;
								computerOn = 1 - computerOn;
								if (computerOn)
									SetContextFont (ComputerFont);
								else
									SetContextFont (CommData.AlienFont);
							}
						pText->CharCount = remChars;
						pText->pStr = ptr;
					}

				// This to simulate a centered line
				pText->baseline.x = baselinex - (width >> 1);
				pText->align = ALIGN_LEFT;
				
				// Put everything back in place for the
				// actual display 
				remChars = bakChars;
				pText->CharCount = bakChars;
				ptr = bakptr;
				pText->pStr = bakptr;
				computerOn = bakcompOn;
				SetContextFont(bakFont);
				
				// This loop is used to look up for $
				while (remChars > 0)
					{
						while ((*ptr != '$') && remChars > 0)
							{
								getCharFromString (&ptr);
								remChars--;
							}
						
						pText->CharCount -= remChars;
						TextRect (pText, &rect, NULL);
						
						font_DrawTracedText (pText,
								     CommData.AlienTextFColor, CommData.AlienTextBColor);
						
						pText->baseline.x += rect.extent.width;
						
						if (*ptr == '$')
							{
								getCharFromString (&ptr);
								remChars--;
								computerOn = 1 - computerOn;
								if (computerOn)
									SetContextFont (ComputerFont);
								else
									SetContextFont (CommData.AlienFont);
							}
						pText->CharCount = remChars;
						pText->pStr = ptr;
					}
				pText->baseline.x = baselinex;
				pText->align = ALIGN_CENTER;
			}
			else
			{
				// Normal case : other races than Orz
				font_DrawTracedText (pText, CommData.AlienTextFColor, CommData.AlienTextBColor);
			}
		}
	} while (!eol && maxchars);
	pText->pStr = pStr;

	if (status == 1)
	{
		STAMP s;
		
		// We were drawing to cache -- flush to screen
		SetContext (OldContext);
		s.origin.x = s.origin.y = 0;
		s.frame = TextCacheFrame;
		DrawStamp (&s);
		
		last_baseline = pText->baseline.y;
	}

	UnbatchGraphics ();
	return (pText->baseline.y);
}