static char* validate_fname(char* name)
{
	char* fname;
	char* p;
	char* q;
	unsigned code;
	int sz = strlen(name);

	q = fname = malloc(sz + 1);
	p = name;
	while (*p) {
		code = utf8_get_char(&p);
		if (code == 0)
			break;
		if (	(code > 0x7F) ||
			(code == '\\') ||
			(code == '/') ||
			(code == ':') ||
			(code == '*') ||
			(code == '?') ||
			(code == '<') ||
			(code == '>') ||
			(code == '|') ||
			(code == 0))
		{
			*q++ = '_';
		} else {
			*q++ = code;
		}
		if (p - name > sz)
			break;
	}
	*q = 0;
	return fname;
}
Example #2
0
STATIC void uni_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
    print(env, "\"");
    const byte *s = str_data, *top = str_data + str_len;
    while (s < top) {
        unichar ch;
        ch = utf8_get_char(s);
        s = utf8_next_char(s);
        if (ch == '"' || ch == '\\' || ch == '/') {
            print(env, "\\%c", ch);
        } else if (32 <= ch && ch <= 126) {
            print(env, "%c", ch);
        } else if (*s == '\b') {
            print(env, "\\b");
        } else if (*s == '\f') {
            print(env, "\\f");
        } else if (*s == '\n') {
            print(env, "\\n");
        } else if (*s == '\r') {
            print(env, "\\r");
        } else if (*s == '\t') {
            print(env, "\\t");
        } else {
            print(env, "\\u%04x", ch);
        }
    }
    print(env, "\"");
}
Example #3
0
int main(int argc, char* argv[])
{
	int i = 0;
	unsigned short codes[] = {0x9690, 0x5f0f, 0x58f0, 0x660e, 0x4e0e, 0x5185, 0x5efa, 0x51fd, 0x6570};
	const char* str = "隐式声明与内建函数";
	const char* p = str;

	for(i = 0; *p; i++)
	{
		assert(codes[i] == utf8_get_char(p, &p));	
		assert(codes[i] == utf8_get_prev_char(p, NULL));
	}
	assert(utf8_count_char(str, strlen(str)) == 9);
	str = "abc";
	assert(utf8_count_char(str, strlen(str)) == 3);
	str = "abc中国";
	assert(utf8_count_char(str, strlen(str)) == 5);
	
	str = "abc中国";
	assert(utf8_count_char(str, 3) == 3);

	test_normalize_path();

	test_ftk_strs_cat();

	test_atoi_itoa();
	test_atof_ftoa();
	test_ftk_parse_color();
	test_strtol();

	return 0;
}
Example #4
0
static void
utf8towcs(wchar_t *o, const char *src)
{ for( ; *src; )
  { int wc;

    src = utf8_get_char(src, &wc);
    *o++ = wc;
  }
  *o = 0;
}
Example #5
0
int main(int argc, char* argv[])
{
	int i = 0;
	unsigned short codes[] = {0x9690, 0x5f0f, 0x58f0, 0x660e, 0x4e0e, 0x5185, 0x5efa, 0x51fd, 0x6570};
	const char* str = "隐式声明与内建函数";
	const char* p = str;

	for(i = 0; *p; i++)
	{
		assert(codes[i] == utf8_get_char(p, &p));	
	}

	return 0;
}
Example #6
0
unicode_type_t
_PL__utf8_type(const char *in, size_t len)
{ const char *end = &in[len];
  int type = S_ASCII;

  while ( in < end )
  { int chr;
    in = utf8_get_char(in, &chr);

    if (chr > 255) return S_WIDE;
    if (chr > 127) type = S_LATIN;
  }

  return type;
}
Example #7
0
void mp_token_show(const mp_token_t *tok) {
    printf("(%d:%d) kind:%d str:%p len:%d", tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
    if (tok->str != NULL && tok->len > 0) {
        const byte *i = (const byte *)tok->str;
        const byte *j = (const byte *)i + tok->len;
        printf(" ");
        while (i < j) {
            unichar c = utf8_get_char(i);
            i = utf8_next_char(i);
            if (unichar_isprint(c)) {
                printf("%c", c);
            } else {
                printf("?");
            }
        }
    }
    printf("\n");
}
Example #8
0
void mp_lexer_show_token(const mp_lexer_t *lex) {
    printf("(" UINT_FMT ":" UINT_FMT ") kind:%u str:%p len:%zu", lex->tok_line, lex->tok_column, lex->tok_kind, lex->vstr.buf, lex->vstr.len);
    if (lex->vstr.len > 0) {
        const byte *i = (const byte *)lex->vstr.buf;
        const byte *j = (const byte *)i + lex->vstr.len;
        printf(" ");
        while (i < j) {
            unichar c = utf8_get_char(i);
            i = utf8_next_char(i);
            if (unichar_isprint(c)) {
                printf("%c", c);
            } else {
                printf("?");
            }
        }
    }
    printf("\n");
}
Example #9
0
STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) {
    // this escapes characters, but it will be very slow to print (calling print many times)
    bool has_single_quote = false;
    bool has_double_quote = false;
    for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) {
        if (*s == '\'') {
            has_single_quote = true;
        } else if (*s == '"') {
            has_double_quote = true;
        }
    }
    unichar quote_char = '\'';
    if (has_single_quote && !has_double_quote) {
        quote_char = '"';
    }
    mp_printf(print, "%c", quote_char);
    const byte *s = str_data, *top = str_data + str_len;
    while (s < top) {
        unichar ch;
        ch = utf8_get_char(s);
        s = utf8_next_char(s);
        if (ch == quote_char) {
            mp_printf(print, "\\%c", quote_char);
        } else if (ch == '\\') {
            mp_print_str(print, "\\\\");
        } else if (32 <= ch && ch <= 126) {
            mp_printf(print, "%c", ch);
        } else if (ch == '\n') {
            mp_print_str(print, "\\n");
        } else if (ch == '\r') {
            mp_print_str(print, "\\r");
        } else if (ch == '\t') {
            mp_print_str(print, "\\t");
        } else if (ch < 0x100) {
            mp_printf(print, "\\x%02x", ch);
        } else if (ch < 0x10000) {
            mp_printf(print, "\\u%04x", ch);
        } else {
            mp_printf(print, "\\U%08x", ch);
        }
    }
    mp_printf(print, "%c", quote_char);
}
Example #10
0
void Font::LoadFontPageSettings( FontPageSettings &cfg, IniFile &ini, const RString &sTexturePath, const RString &sPageName, RString sChars )
{
	cfg.m_sTexturePath = sTexturePath;

	/* If we have any characters to map, add them. */
	for( unsigned n=0; n<sChars.size(); n++ )
	{
		char c = sChars[n];
		cfg.CharToGlyphNo[c] = n;
	}
	int iNumFramesWide, iNumFramesHigh;
	RageTexture::GetFrameDimensionsFromFileName( sTexturePath, &iNumFramesWide, &iNumFramesHigh );
	int iNumFrames = iNumFramesWide * iNumFramesHigh;
	
	ini.RenameKey("Char Widths", "main");

//	LOG->Trace("Loading font page '%s' settings from page name '%s'",
//		TexturePath.c_str(), sPageName.c_str());
	
	ini.GetValue( sPageName, "DrawExtraPixelsLeft", cfg.m_iDrawExtraPixelsLeft );
	ini.GetValue( sPageName, "DrawExtraPixelsRight", cfg.m_iDrawExtraPixelsRight );
	ini.GetValue( sPageName, "AddToAllWidths", cfg.m_iAddToAllWidths );
	ini.GetValue( sPageName, "ScaleAllWidthsBy", cfg.m_fScaleAllWidthsBy );
	ini.GetValue( sPageName, "LineSpacing", cfg.m_iLineSpacing );
	ini.GetValue( sPageName, "Top", cfg.m_iTop );
	ini.GetValue( sPageName, "Baseline", cfg.m_iBaseline );
	ini.GetValue( sPageName, "DefaultWidth", cfg.m_iDefaultWidth );
	ini.GetValue( sPageName, "AdvanceExtraPixels", cfg.m_iAdvanceExtraPixels );
	ini.GetValue( sPageName, "TextureHints", cfg.m_sTextureHints );

	/* Iterate over all keys. */
	const XNode* pNode = ini.GetChild( sPageName );
	if( pNode )
	{
		FOREACH_CONST_Attr( pNode, pAttr )
		{
			RString sName = pAttr->first;
			const XNodeValue *pValue = pAttr->second;

			sName.MakeUpper();

			/* If val is an integer, it's a width, eg. "10=27". */
			if( IsAnInt(sName) )
			{
				cfg.m_mapGlyphWidths[atoi(sName)] = pValue->GetValue<int>();
				continue;
			}

			/* "map codepoint=frame" maps a char to a frame. */
			if( sName.substr(0, 4) == "MAP " )
			{
				/*
				 * map CODEPOINT=frame. CODEPOINT can be
				 * 1. U+hexval
				 * 2. an alias ("oq")
				 * 3. a character in quotes ("X")
				 *
				 * map 1=2 is the same as
				 * range unicode #1-1=2
				 */
				RString sCodepoint = sName.substr(4); /* "CODEPOINT" */

				wchar_t c;
				if( sCodepoint.substr(0, 2) == "U+" && IsHexVal(sCodepoint.substr(2)) )
					sscanf( sCodepoint.substr(2).c_str(), "%x", &c );
				else if( sCodepoint.size() > 0 &&
						utf8_get_char_len(sCodepoint[0]) == int(sCodepoint.size()) )
				{
					c = utf8_get_char( sCodepoint.c_str() );
					if(c == wchar_t(-1))
						LOG->Warn("Font definition '%s' has an invalid value '%s'.",
							ini.GetPath().c_str(), sName.c_str() );
				}
				else if( !FontCharAliases::GetChar(sCodepoint, c) )
				{
					LOG->Warn("Font definition '%s' has an invalid value '%s'.",
						ini.GetPath().c_str(), sName.c_str() );
					continue;
				}

				cfg.CharToGlyphNo[c] = pValue->GetValue<int>();

				continue;
			}

			if( sName.substr(0, 6) == "RANGE " )
			{
				/*
				 * range CODESET=first_frame or
				 * range CODESET #start-end=first_frame
				 * eg
				 * range CP1252=0       (default for 256-frame fonts)
				 * range ASCII=0        (default for 128-frame fonts)
				 *
				 * (Start and end are in hex.)
				 *
				 * Map two high-bit portions of ISO-8859- to one font:
				 * range ISO-8859-2 #80-FF=0
				 * range ISO-8859-3 #80-FF=128
				 *
				 * Map hiragana to 0-84:
				 * range Unicode #3041-3094=0
				 */
				vector<RString> asMatches;
				static Regex parse("^RANGE ([A-Z0-9\\-]+)( ?#([0-9A-F]+)-([0-9A-F]+))?$");
				bool bMatch = parse.Compare( sName, asMatches );
				
				ASSERT( asMatches.size() == 4 ); /* 4 parens */

				if( !bMatch || asMatches[0].empty() )
					RageException::Throw( "Font definition \"%s\" has an invalid range \"%s\": parse error.",
						ini.GetPath().c_str(), sName.c_str() );
				
				/* We must have either 1 match (just the codeset) or 4 (the whole thing). */

				int iCount = -1;
				int iFirst = 0;
				if( !asMatches[2].empty() )
				{
					sscanf( asMatches[2].c_str(), "%x", &iFirst );
					int iLast;
					sscanf( asMatches[3].c_str(), "%x", &iLast );
					if( iLast < iFirst )
						RageException::Throw( "Font definition \"%s\" has an invalid range \"%s\": %i < %i.",
							ini.GetPath().c_str(), sName.c_str(), iLast, iFirst );

					iCount = iLast - iFirst + 1;
				}

				RString sRet = cfg.MapRange( asMatches[0], iFirst, pValue->GetValue<int>(), iCount );
				if( !sRet.empty() )
					RageException::Throw( "Font definition \"%s\" has an invalid range \"%s\": %s.",
						ini.GetPath().c_str(), sName.c_str(), sRet.c_str() );

				continue;
			}

			if( sName.substr(0, 5) == "LINE " )
			{
				/* line ROW=CHAR1CHAR2CHAR3CHAR4
				 * eg.
				 * line 0=ABCDEFGH
				 *
				 * This lets us assign characters very compactly and readably. */

				RString sRowStr = sName.substr(5);
				TrimLeft( sRowStr );

				ASSERT( IsAnInt(sRowStr) );
				const int iRow = atoi( sRowStr.c_str() );
				const int iFirstFrame = iRow * iNumFramesWide;

				if( iRow > iNumFramesHigh )
					RageException::Throw( "The font definition \"%s\" tries to assign line %i, but the font is only %i characters high.",
						ini.GetPath().c_str(), iFirstFrame, iNumFramesHigh );

				/* Decode the string. */
				const wstring wdata( RStringToWstring(pValue->GetValue<RString>()) );

				if( int(wdata.size()) > iNumFramesWide )
					RageException::Throw( "The font definition \"%s\" assigns %i characters to row %i (\"%ls\"), but the font is only %i characters wide.",
						ini.GetPath().c_str(), (int)wdata.size(), iRow, wdata.c_str(), iNumFramesWide );

				for( unsigned i = 0; i < wdata.size(); ++i )
					cfg.CharToGlyphNo[wdata[i]] = iFirstFrame+i;
			}
		}
	}
Example #11
0
void TitleSubst::Load(const CString &filename, const CString &section)
{
	RageFile f;
	if( !f.Open(filename) )
	{
		LOG->Trace("Error opening %s: %s", filename.c_str(), f.GetError().c_str() );
		return;
	}
	
	CString CurrentSection;
	TitleTrans tr;
	
	while (!f.AtEOF())
	{
		CString line;
		int ret = f.GetLine( line );
		if( ret == 0 )
			break;
		if( ret < 0 )
		{
			LOG->Trace("Error reading %s: %s", filename.c_str(), f.GetError().c_str() );
			break;
		}

		if(line.size() > 0 && utf8_get_char(line.c_str()) == 0xFEFF)
		{
			/* Annoying header that Windows puts on UTF-8 plaintext
			 * files; remove it. */
			line.erase(0, utf8_get_char_len(line[0]));
		}

		TrimLeft(line);
		TrimRight(line);

		if(line.size() == 0) continue; /* blank */
		if(line[0] == '#') continue; /* comment */

		if(!line.CompareNoCase("DontTransliterate"))
		{
			tr.translit = false;
			continue;
		}

		size_t pos = line.find_first_of(':');
		if(pos != string::npos)
		{
			/* x: y */
			CString id = line.substr(0, pos);
			CString txt = line.substr(pos+1);
			TrimLeft(txt);

			/* Surround each regex with ^(...)$, to force all comparisons to default
			 * to being a full-line match.  (Add ".*" manually if this isn't wanted.) */
			if(!id.CompareNoCase("TitleFrom")) tr.TitleFrom = "^(" + txt + ")$";
			else if(!id.CompareNoCase("ArtistFrom")) tr.ArtistFrom = "^(" + txt + ")$";
			else if(!id.CompareNoCase("SubtitleFrom")) tr.SubFrom = "^(" + txt + ")$";
			else if(!id.CompareNoCase("TitleTo")) tr.Dest.Title = txt;
			else if(!id.CompareNoCase("ArtistTo")) tr.Dest.Artist = txt;
			else if(!id.CompareNoCase("SubtitleTo")) tr.Dest.Subtitle = txt;
			else if(!id.CompareNoCase("TitleTransTo")) tr.Dest.TitleTranslit = txt;
			else if(!id.CompareNoCase("ArtistTransTo")) tr.Dest.ArtistTranslit = txt;
			else if(!id.CompareNoCase("SubtitleTransTo")) tr.Dest.SubtitleTranslit = txt;
			else
				LOG->Warn( "Unknown TitleSubst tag: \"%s\"", id.c_str() );
		}

		/* Add the translation if this is a terminator (*) or section
		 * marker ([foo]). */
		if(line[0] == '*' || line[0] == '[')
		{
			if(!CurrentSection.CompareNoCase(section))
				AddTrans(tr);
			
			/* Reset. */
			tr = TitleTrans();
		}

		if(line[0] == '[' && line[line.size()-1] == ']')
		{
			CurrentSection = line.substr(1, line.size()-2);
		}
	}
}
Example #12
0
static void wordwrap(TextareaWidget *peer, char *text, int visible_lines, Uint16 scrollbar_width, bool has_scrollbar) {
	// maximum text width
	int width = peer->w.bounds.w - peer->w.padding.left - peer->w.padding.right;

	// lines points to the start of each line
	int max_lines = 100;
	unsigned int *lines = malloc(sizeof(int) * max_lines);
	int num_lines = 0;

	char *ptr = text;
	char *line_start = ptr;
	char *word_break = NULL;
	Uint16 line_width = 0;

	/* optimization, don't wrap text with width = 0 */
	if (width <= 0) {
		lines[0] = 0;
		lines[1] = strlen(ptr);

		if (peer->lines) {
			free(peer->lines);
		}

		peer->num_lines = 1;
		peer->lines = realloc(lines, sizeof(int) * (1 + 1));

		return;
	}


	peer->has_scrollbar = has_scrollbar;
	if (has_scrollbar && !peer->is_header_widget) {
		width -= scrollbar_width;
	}

	lines[num_lines++] = (ptr - text);

	while (*ptr) {
		char c;
		char *next;
		Uint32 code = utf8_get_char(ptr, (const char **)&next);

		switch (code) {
		case '\n':
			/* Line break */
			ptr = next;
			word_break = NULL;

			if (max_lines == num_lines) {
				max_lines += 100;
				lines = realloc(lines, sizeof(int) * max_lines);
			}

			line_start = ptr;
			lines[num_lines++] = (ptr - text);
			line_width = 0;
			continue;

		case '.':
		    /* Word break, but exclude urls */
		    if (utf8_get_char(next, NULL) != ' ') {
			break;
		    }

		case ' ':
		case ',':
		case '-':
			/* Word break */
			word_break = next;
			break;
		}

		// Calculate width of string to char
		c = *next;
		*next = '\0';
		line_width += jive_font_width(peer->font, (char *)ptr);
		*next = c;

		// Line is less than widget width
		if (line_width < width) {
			ptr = next;
			continue;
		}

		if (max_lines == num_lines) {
			max_lines += 100;
			lines = realloc(lines, sizeof(int) * max_lines);
		}

		// Next line
		line_width = 0;

		if (!has_scrollbar && num_lines > visible_lines && !(peer->is_header_widget || peer->hide_scrollbar)) {
			free(lines);
			return wordwrap(peer, text, visible_lines, scrollbar_width, true);
		}

		if (word_break) {
			ptr = word_break;
			word_break = NULL;
		}

		/* trim extra \n caused by line breaks */
		code = utf8_get_char(ptr, (const char **)&next);
		if (code == '\n') {
			ptr = next;
			code = utf8_get_char(ptr, (const char **)&next);
		}

		/* trim leading space on line break */
	  	while (code != 0 && code == ' ') {
			ptr = next;
			code = utf8_get_char(ptr, (const char **)&next);
		}

		line_start = ptr;
		lines[num_lines++] = (ptr - text);
	}
	lines[num_lines] = (ptr - text);

	if (!has_scrollbar && num_lines > visible_lines && !(peer->is_header_widget || peer->hide_scrollbar)) {
		free(lines);
		return wordwrap(peer, text, visible_lines, scrollbar_width, true);
	}

	if (peer->lines) {
		free(peer->lines);
	}
	peer->num_lines = num_lines;
	peer->lines = realloc(lines, sizeof(int) * (num_lines + 1));
}
/** ColorBitmapText ***********************************************************/
void ColorBitmapText::SetText( const RString& _sText, const RString& _sAlternateText, int iWrapWidthPixels )
{
	ASSERT( m_pFont != NULL );

	RString sNewText = StringWillUseAlternate(_sText,_sAlternateText) ? _sAlternateText : _sText;

	if( iWrapWidthPixels == -1 )	// wrap not specified
		iWrapWidthPixels = m_iWrapWidthPixels;

	if( m_sText == sNewText && iWrapWidthPixels==m_iWrapWidthPixels )
		return;
	m_sText = sNewText;
	m_iWrapWidthPixels = iWrapWidthPixels;

	// Set up the first color.
	m_vColors.clear();
	ColorChange change;
	change.c = RageColor (1, 1, 1, 1);
	change.l = 0;
	m_vColors.push_back( change );

	m_wTextLines.clear();

	RString sCurrentLine = "";
	int		iLineWidth = 0;

	RString sCurrentWord = "";
	int		iWordWidth = 0;
	int		iGlyphsSoFar = 0;

	for( unsigned i = 0; i < m_sText.length(); i++ )
	{
		int iCharsLeft = m_sText.length() - i - 1;

		// First: Check for the special (color) case.

		if( m_sText.length() > 8 && i < m_sText.length() - 9 )
		{
			RString FirstThree = m_sText.substr( i, 3 );
			if( FirstThree.CompareNoCase("|c0") == 0 && iCharsLeft > 8 )
			{
				ColorChange cChange;
				unsigned int r, g, b;
				sscanf( m_sText.substr( i, 9 ).c_str(), "|%*c0%2x%2x%2x", &r, &g, &b );
				cChange.c = RageColor( r/255.f, g/255.f, b/255.f, 1.f );
				cChange.l = iGlyphsSoFar;
				if( iGlyphsSoFar == 0 )
					m_vColors[0] = cChange;
				else
					m_vColors.push_back( cChange );
				i+=8;
				continue;
			}
		}

		int iCharLength = min( utf8_get_char_len(m_sText[i]), iCharsLeft + 1 );
		RString curCharStr = m_sText.substr( i, iCharLength );
		wchar_t curChar = utf8_get_char( curCharStr );
		i += iCharLength - 1;
		int iCharWidth = m_pFont->GetLineWidthInSourcePixels( wstring() + curChar );

		switch( curChar )
		{
		case L' ':
			if( /* iLineWidth == 0 &&*/ iWordWidth == 0 )
				break;
			sCurrentLine += sCurrentWord + " ";
			iLineWidth += iWordWidth + iCharWidth;
			sCurrentWord = "";
			iWordWidth = 0;
			iGlyphsSoFar++;
			break;
		case L'\n':
			if( iLineWidth + iWordWidth > iWrapWidthPixels )
			{
				SimpleAddLine( sCurrentLine, iLineWidth );
				if( iWordWidth > 0 )
					iLineWidth = iWordWidth +	//Add the width of a space
						m_pFont->GetLineWidthInSourcePixels( L" " );
				sCurrentLine = sCurrentWord + " ";
				iWordWidth = 0;
				sCurrentWord = "";
				iGlyphsSoFar++;
			} 
			else
			{
				SimpleAddLine( sCurrentLine + sCurrentWord, iLineWidth + iWordWidth );
				sCurrentLine = "";	iLineWidth = 0;
				sCurrentWord = "";	iWordWidth = 0;
			}
			break;
		default:
			if( iWordWidth + iCharWidth > iWrapWidthPixels && iLineWidth == 0 )
			{
				SimpleAddLine( sCurrentWord, iWordWidth );
				sCurrentWord = curCharStr;  iWordWidth = iCharWidth;
			}
			else if( iWordWidth + iLineWidth + iCharWidth > iWrapWidthPixels )
			{
				SimpleAddLine( sCurrentLine, iLineWidth );
				sCurrentLine = ""; 
				iLineWidth = 0;
				sCurrentWord += curCharStr;
				iWordWidth += iCharWidth;
			}
			else
			{
				sCurrentWord += curCharStr;
				iWordWidth += iCharWidth;
			}
			iGlyphsSoFar++;
			break;
		}
	}

	if( iWordWidth > 0 )
	{
		sCurrentLine += sCurrentWord;
		iLineWidth += iWordWidth;
	}

	if( iLineWidth > 0 )
		SimpleAddLine( sCurrentLine, iLineWidth );

	BuildChars();
	UpdateBaseZoom();
}