void Resource_List::LoadTxt( WideStream &txt ) { // Формат ресурсов: NNN LANG string // // Допускаются директивы: // $include filename language int last_good_id=0; const lem::UCString INCLUDE(L"$include"); const UFString cur_lang( lem::to_unicode( lem::UI::get_UI().GetCurrLang() ) ); const UFString english(L"en"); UCString nnn; std::string lang; UFString string; while( !txt.eof() ) { txt.skip_white(); nnn.clear(); lang.clear(); string.clear(); // read the number identifier (primary key) of the string record. while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u==WEOF ) break; if( nnn.front()==L'#' ) { // Commentary string - read until EOL. while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u == L'\n' || u==L'\r' || u==WEOF ) break; } break; } if( is_uspace(u) ) { txt.unget(u); break; } nnn += u; } if( nnn.empty() ) continue; if( nnn == INCLUDE ) { // Next fields are: 1) filename and 2) language UFString filename, language; filename.reserve(64); language.reserve(4); txt.skip_white(); while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u==WEOF ) break; if( is_uspace(u) || u==L'\n' || u==L'\r' ) { txt.unget(u); break; } filename.Add_Dirty(u); } txt.skip_white(); while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u==WEOF ) break; if( is_uspace(u) || u==L'\n' || u==L'\r' ) { txt.unget(u); break; } language.Add_Dirty(u); } language.calc_hash(); filename.calc_hash(); // Recursively load the file if( load_all_languages || language == cur_lang || language==english ) { // Если задан файл без указания пути, то путь берем из исходного файла lem::Path inc(filename); inc.RemoveLastLeaf(); if( inc.empty() ) { inc = txt.GetName(); inc.RemoveLastLeaf(); inc.ConcateLeaf(lem::Path(filename)); LoadTxt( inc ); } else { LoadTxt( lem::Path(filename) ); } } continue; } int iname = 0; if( lem::to_int( nnn.c_str(), &iname )==false || iname<=0 ) throw E_BaseException( lem::format_str( L"Incorrect format of string resource file: id is not a number [%ls]", nnn.c_str() ).c_str() ); last_good_id = iname; // метка языка txt.skip_white(); while( !txt.eof() ) { wchar_t u = txt.wget(); if( u==WEOF ) break; if( is_uspace(u) ) { txt.unget(u); break; } lang += static_cast<char>(u); } // Ведем список языков, для которых есть локализация ресурсов. // ищем такой язык в справочнике int ilang = FindLang(lang,NULL); int il=0; for( std::vector<std::string>::const_iterator j=langs.begin(); j!=langs.end(); j++, il++ ) if( *j == lang ) { ilang = il; break; } if( ilang==UNKNOWN && !lang.empty() ) { ilang = langs.size(); langs.push_back( lang ); } txt.skip_white(); bool apostrophed=true; // теперь сама строка ресурсов while( !txt.eof() ) { wchar_t u = txt.wget(); if( u==WEOF /*EOF fixed 17.09.2009 */ ) break; if( u==L'\r' || u=='\n' ) { break; } if( u==L'"' && string.empty() ) { // Начало строки в апострофах apostrophed = true; continue; } if( u==L'"' && !string.empty() ) { // Конец строки в апострофах // Если далее идет символ +, то будет продолжение на следующей строке. wchar_t next = txt.wget(); if( next==L'+' ) { // Это продолжение. txt.skip_white(); next = txt.wget(); if( next==WEOF || next==0 ) continue; LEM_CHECKIT_Z( next==L'"' ); continue; } break; } if( u==L'\\' ) { // спецсимволы wchar_t u2 = txt.wget(); if( u2==WEOF ) break; if( u2==L'\r' || u2=='\n' ) break; if( u2==L'r' || u2==L'n' ) u = L'\n'; else if( u2==L'"' ) u = L'"'; else u = u2; } string.Add_Dirty(u); } string.calc_hash(); if( !nnn.empty() && !string.empty() ) { // Сохраняем ресурс. // Ветка ресурса для этого nnn уже есть? string.trim(); string.strip_quotes(); Resource *r = NULL; std::map<int,Resource*>::iterator it = iname_2_res.find(iname); if( it!=iname_2_res.end() ) { r = it->second; } else { r = new Resource; r->name = iname; list.push_back(r); iname_2_res.insert( std::make_pair(iname,r) ); } r->list.push_back( make_pair( ilang, string ) ); } } return; }
// ********************************************************** // Загружаем тэг - все символы между < >. // Открывающая угловая скобка уже считана! // ********************************************************** void Parser::Read_Tag( WideStream *reader, UFString &tag ) const { tag.clear(); int count=0; while( !reader->eof() ) { wchar_t c = reader->wget(); if( c==L'>' ) break; if( !count && c==L'!' ) { // Или комментарий <!-- ... --> // или блок кода <![CDATA[ ... ]]> // или начальный тэг <!DOCTYPE tag.Add_Dirty(c); count++; wchar_t c = reader->wget(); if( c==L'-' ) { // комментарий... tag.Add_Dirty(c); count++; while( !reader->eof() ) { wchar_t c = reader->wget(); if( c==WEOF ) break; if( count>3 && c==L'>' ) { // Комментарий заканчивается на --> if( tag.back()==L'-' && tag[tag.length()-2]==L'-' ) { goto tag_complete; } } tag.Add_Dirty(c); count++; } // Если комментарий не закончен нормально, то значит была ошибка throw Invalid_Format(); } else if( c==L'D' ) { // <!DOCTYPE ...> // загружаем как обычный тэг tag.Add_Dirty(c); count++; continue; } else if( c=='[' ) { // <![CDATA[ продолжаем загружать... tag.Add_Dirty(c); count++; continue; } else { // Неизвестный тэг, для HTML проигнорируем ошибку if( doctype==Parser::HtmlDoc ) { tag.Add_Dirty(c); count++; } else { throw Invalid_Format(); } } } else if( count==7 && c==L'[' && tag==L"![CDATA" ) { // блок кода после <![CDATA[ tag.Add_Dirty(c); count++; while( !reader->eof() ) { wchar_t c = reader->wget(); if( c==WEOF ) break; if( count>8 && c==L'>' ) { // Блок кода заканчивается на ]]> if( tag.back()==L']' && tag[tag.length()-2]==L']' ) { goto tag_complete; } } tag.Add_Dirty(c); count++; } if( doctype!=Parser::HtmlDoc ) throw Invalid_Format(); } if( c==WEOF || reader->eof() ) break; tag.Add_Dirty(c); count++; } tag_complete: tag.calc_hash(); return; }