void GIFFChunk::set_name(GUTF8String name) { DEBUG_MSG("GIFFChunk::set_name(): name='" << name << "'\n"); DEBUG_MAKE_INDENT(3); const int colon=name.search(':'); if(colon>=0) { type=name.substr(0,colon); name=name.substr(colon+1,(unsigned int)-1); if(name.search(':')>=0) G_THROW( ERR_MSG("GIFFManager.one_colon") ); } DEBUG_MSG("auto-setting type to '" << type << "'\n"); if (name.contains(".[]")>=0) G_THROW( ERR_MSG("GIFFManager.bad_char") ); strncpy(GIFFChunk::name, (const char *)name, 4); GIFFChunk::name[4]=0; for(int i=strlen(GIFFChunk::name);i<4;i++) GIFFChunk::name[i]=' '; }
GURL getDjViewDataFile(const char *fname) { GList<GURL> paths = DjVuMessage::GetProfilePaths(); GUTF8String file = fname; // end hack alert static const char *osi = "/osi/"; static const char *djview3 = "/djview3/"; for (GPosition pos=paths; pos; ++pos) { GURL url = GURL(file, paths[pos]); GUTF8String urls = (const char*)url; int pos = urls.search(osi); if (pos >= 0) { GUTF8String urlx; urlx += urls.substr(0, pos); urlx += djview3; urlx += urls.substr(pos+strlen(osi), -1); GURL url = GURL::UTF8(urlx); if (url.is_file()) return url; } } // end hack alert for (GPosition pos=paths; pos; ++pos) { GURL url = GURL(file, paths[pos]); if(url.is_file()) return url; } return GURL(); }
static int CountLines(const GUTF8String &str) { int retval=0; static const unsigned long lf='\n'; for(int pos=0;(pos=str.search(lf,pos)+1)>0;++retval) EMPTY_LOOP; return retval; }
GUTF8String GIFFChunk::decode_name(const GUTF8String &name, int &number) { DEBUG_MSG("GIFFChunk::decode_name(): Checking brackets in name '" << name << "'\n"); DEBUG_MAKE_INDENT(3); if (name.search('.')>=0) G_THROW( ERR_MSG("GIFFManager.no_dots") ); number=0; const int obracket=name.search('['); GUTF8String short_name; if (obracket >= 0) { const int cbracket=name.search(']',obracket+1); if (cbracket < 0) G_THROW( ERR_MSG("GIFFManager.unmatched") ); if (name.length() > (unsigned int)(cbracket+1)) G_THROW( ERR_MSG("GIFFManager.garbage") ); // number =atoi((const char *)name.substr(obracket+1,cbracket-obracket-1)); number= name.substr(obracket+1,cbracket-obracket-1).toInt(); short_name=name.substr(0,obracket); }else { short_name=name; } const int colon=short_name.search(':'); if (colon>=0) short_name=short_name.substr(colon+1,(unsigned int)-1); for(int i=short_name.length();i<4;i++) short_name.setat(i, ' '); DEBUG_MSG("short_name='" << short_name << "'\n"); DEBUG_MSG("number=" << number << "\n"); return short_name; }
void GIFFManager::del_chunk(GUTF8String name) // "name" should be fully qualified, that is contain dots. // It may also end with [] to set the chunk order number { DEBUG_MSG("GIFFManager::del_chunk(): Deleting chunk '" << name << "'\n"); DEBUG_MAKE_INDENT(3); if (!name.length()) G_THROW( ERR_MSG("GIFFManager.del_empty") ); if (name[0]=='.') { const int next_dot=name.search('.',1); if (next_dot < 0) { if (top_level->check_name(name.substr(1,(unsigned int)-1))) { DEBUG_MSG("Removing top level chunk..\n"); top_level=GIFFChunk::create(); return; } G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+name.substr(1,(unsigned int)-1)); } const GUTF8String top_name=name.substr(1,next_dot-1); if (!top_level->check_name(top_name)) G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+top_name); name=name.substr(next_dot+1,(unsigned int)-1); } GP<GIFFChunk> cur_sec=top_level; const char * start, * end=(const char *)name-1; do { for(start=++end;*end&&(*end!='.');end++) EMPTY_LOOP; if (end>start && *end=='.') cur_sec=cur_sec->get_chunk(GUTF8String(start, end-start)); if (!cur_sec) G_THROW( ERR_MSG("GIFFManager.cant_find") "\t"+GUTF8String(name)); } while(*end); if (!start[0]) { G_THROW(GUTF8String( ERR_MSG("GIFFManager.malformed") "\t")+name); } cur_sec->del_chunk(start); }
void DjVmDir0::add_file( const GUTF8String &name, bool iff_file, int offset, int size) { DEBUG_MSG("DjVmDir0::add_file(): name='" << name << "', iff=" << iff_file << ", offset=" << offset << "\n"); if (name.search('/') >= 0) G_THROW( ERR_MSG("DjVmDir0.no_slash") ); GP<FileRec> file=new FileRec(name, iff_file, offset, size); name2file[name]=file; num2file.resize(num2file.size()); num2file[num2file.size()-1]=file; }
bool GIFFChunk::check_name(GUTF8String name) { GUTF8String type; const int colon=name.search(':'); if(colon>=0) { type=name.substr(0,colon); name=name.substr(colon+1,(unsigned int)-1); } const GUTF8String sname=(name.substr(0,4)+" ").substr(0,4); DEBUG_MSG("GIFFChunk::check_name(): type='" << type << "' name='" << sname << "'\n"); return (type==GIFFChunk::type || (!type.length() && GIFFChunk::type=="FORM")) && sname==GIFFChunk::name; }
// Looks up the msgID in the file of messages and returns a pointer to // the beginning of the translated message, if found; and an empty string // otherwise. void DjVuMessageLite::LookUpID( const GUTF8String &xmsgID, GUTF8String &message_text, GUTF8String &message_number ) const { if(!Map.isempty()) { GUTF8String msgID = xmsgID; #if HAS_CTRL_C_IN_ERR_MSG int start = 0; while (msgID[start] == '\003') start ++; if (start > 0) msgID = msgID.substr(start, msgID.length() - start); #endif GPosition pos=Map.contains(msgID); if(pos) { const GP<lt_XMLTags> tag=Map[pos]; GPosition valuepos=tag->get_args().contains(valuestring); if(valuepos) { message_text=tag->get_args()[valuepos]; }else { const GUTF8String raw(tag->get_raw()); const int start_line=raw.search((unsigned long)'\n',0); const int start_text=raw.nextNonSpace(0); const int end_text=raw.firstEndSpace(0); if(start_line<0 || start_text<0 || start_text < start_line) { message_text=raw.substr(0,end_text).fromEscaped(); }else { message_text=raw.substr(start_line+1,end_text-start_line-1).fromEscaped(); } } GPosition numberpos=tag->get_args().contains(numberstring); if(numberpos) { message_number=tag->get_args()[numberpos]; } } } }
GP<GIFFChunk> GIFFManager::get_chunk(GUTF8String name, int * pos_num) // "name" should be fully qualified, that is contain dots. // It may also end with [] to set the chunk order number { DEBUG_MSG("GIFFManager::get_chunk(): Returning chunk '" << name << "'\n"); DEBUG_MAKE_INDENT(3); if (!name.length()) G_THROW( ERR_MSG("GIFFManager.get_empty") ); if (name[0]=='.') { const int next_dot=name.search('.',1); if (next_dot < 0) { if (top_level->check_name(name.substr(1,(unsigned int)-1))) { DEBUG_MSG("Removing top level chunk..\n"); return top_level; } G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+name.substr(1,(unsigned int)-1)); } const GUTF8String top_name=name.substr(1,next_dot-1); if (!top_level->check_name(top_name)) G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+top_name); name=name.substr(next_dot+1,(unsigned int)-1); } GP<GIFFChunk> cur_sec=top_level; const char * start, * end=(const char *) name-1; do { for(start=++end;*end&&(*end!='.');end++) EMPTY_LOOP; if (end>start) cur_sec=cur_sec->get_chunk(GUTF8String(start, end-start), pos_num); if (!cur_sec) break; } while(*end); return cur_sec; }
// Expands message lists by looking up the message IDs and inserting // arguments into the retrieved messages. // N.B. The resulting string may be encoded in UTF-8 format (ISO 10646-1 Annex R) // and SHOULD NOT BE ASSUMED TO BE ASCII. GUTF8String DjVuMessageLite::LookUp( const GUTF8String & MessageList ) const { // DEBUG_MSG( "========== DjVuMessageLite::LookUp ==========\n" << // MessageList << // "\n========== DjVuMessageLite::LookUp ==========\n" ); GUTF8String result; // Result string; begins empty if(errors.length()) { const GUTF8String err1(errors); (const_cast<GUTF8String &>(errors)).empty(); result=LookUp(err1)+"\n"; } int start = 0; // Beginning of next message int end = MessageList.length(); // End of the message string // Isolate single messages and process them while( start < end ) { if( MessageList[start] == '\n' ) { result += MessageList[start++]; // move the newline to the result // and advance to the next message } else { // Find the end of the next message and process it int next_ending = MessageList.search((unsigned long)'\n', start); if( next_ending < 0 ) next_ending = end; result += LookUpSingle( MessageList.substr(start, next_ending-start) ); // Advance to the next message start = next_ending; } } // All done return result; }
void GIFFManager::add_chunk(GUTF8String parent_name, const GP<GIFFChunk> & chunk, int pos) // parent_name is the fully qualified name of the PARENT // IT MAY BE EMPTY // All the required chunks will be created // pos=-1 means to append the chunk { DEBUG_MSG("GIFFManager::add_chunk(): Adding chunk to name='" << parent_name << "'\n"); DEBUG_MAKE_INDENT(3); if (!top_level->get_name().length()) { if ((!parent_name.length())||(parent_name[0]!='.')) G_THROW( ERR_MSG("GIFFManager.no_top_name") ); if (parent_name.length() < 2) { // 'chunk' is actually the new top-level chunk DEBUG_MSG("since parent_name=='.', making the chunk top-level\n"); if (!chunk->is_container()) G_THROW( ERR_MSG("GIFFManager.no_top_cont") ); top_level=chunk; return; } DEBUG_MSG("Setting the name of the top-level chunk\n"); const int next_dot=parent_name.search('.',1); if(next_dot>=0) { top_level->set_name(parent_name.substr(1,next_dot-1)); }else { top_level->set_name(parent_name.substr(1,(unsigned int)-1)); } } DEBUG_MSG("top level chunk name='" << top_level->get_name() << "'\n"); if (parent_name.length() && parent_name[0] == '.') { int next_dot=parent_name.search('.',1); if(next_dot<0) { next_dot=parent_name.length(); } GUTF8String top_name=parent_name.substr(1,next_dot-1); if (!top_level->check_name(top_name)) G_THROW( ERR_MSG("GIFFManager.wrong_name") "\t"+top_name); parent_name=parent_name.substr(next_dot,(unsigned int)-1); } GP<GIFFChunk> cur_sec=top_level; const char * start, * end=(const char *)parent_name-1; do { for(start=++end;*end&&(*end!='.');end++) EMPTY_LOOP; if (end>start) { GUTF8String name(start,end-start); GUTF8String short_name; int number=0; const int obracket=name.search('['); if (obracket >= 0) { const int cbracket=name.search(']',obracket+1); if (cbracket < 0) G_THROW( ERR_MSG("GIFFManager.unmatched") ); // number=atoi((const char *)name.substr(obracket+1,cbracket-obracket-1)); number = name.substr(obracket+1,cbracket-obracket-1).toInt(); short_name=name.substr(0,obracket); }else { short_name=name; } for(int i=cur_sec->get_chunks_number(short_name);i<number+1;i++) cur_sec->add_chunk(GIFFChunk::create(short_name)); cur_sec=cur_sec->get_chunk(name); if (!cur_sec) G_THROW( ERR_MSG("GIFFManager.unknown") "\t"+name); } } while(*end); cur_sec->add_chunk(chunk, pos); }
// Insert a string into the message text. Will insert into any field // description. Except for an ArgId of zero (message number), if the ArgId // is not found, the routine adds a line with the parameter so information // will not be lost. void DjVuMessageLite::InsertArg( GUTF8String &message, const int ArgId, const GUTF8String &arg ) const { // argument target string const GUTF8String target= "%"+GUTF8String(ArgId)+"!"; // location of target string int format_start = message.search( (const char *)target ); if( format_start >= 0 ) { do { const int n=format_start+target.length()+1; const int format_end=message.search((unsigned long)'!',n); if(format_end > format_start) { const int len=1+format_end-n; if(len && isascii(message[n-1])) { GUTF8String narg; GUTF8String format="%"+message.substr(n-1,len); switch(format[len]) { case 'd': case 'i': narg.format((const char *)format,arg.toInt()); break; case 'u': case 'o': case 'x': case 'X': narg.format((const char *)format,(unsigned int)arg.toInt()); break; case 'f': case 'g': case 'e': { int endpos; narg.format((const char *)format, arg.toDouble(0,endpos)); if( endpos < 0 ) narg = arg; } break; default: narg.format((const char *)format,(const char *)arg); break; } message = message.substr( 0, format_start )+narg +message.substr( format_end+1, -1 ); }else { message = message.substr( 0, format_start )+arg +message.substr( format_end+1, -1 ); } } format_start=message.search((const char*)target, format_start+arg.length()); } while(format_start >= 0); } else { // Not found, fake it if( ArgId != 0 ) { message += "\n"+LookUpSingle(uparameter+("\t"+arg)); } } }
GList<GURL> DjVuMessage::GetProfilePaths(void) { static bool first=true; static GList<GURL> realpaths; if(first) { first=false; GMap<GUTF8String,void *> pathsmap; GList<GURL> paths; GURL path; const GUTF8String envp(GOS::getenv(DjVuEnv)); if(envp.length()) appendPath(GURL::Filename::UTF8(envp),pathsmap,paths); #if defined(WIN32) || defined(UNIX) GURL mpath(GetModulePath()); if(!mpath.is_empty() && mpath.is_dir()) { #if defined(UNIX) && !defined(AUTOCONF) && !defined(NDEBUG) appendPath(GURL::UTF8(DebugModuleDjVuDir,mpath),pathsmap,paths); #endif appendPath(mpath,pathsmap,paths); mpath=mpath.base(); appendPath(GURL::UTF8(ModuleDjVuDir,mpath),pathsmap,paths); mpath=mpath.base(); appendPath(GURL::UTF8(ModuleDjVuDir,mpath),pathsmap,paths); } #endif #if defined(AUTOCONF) GURL dpath = GURL::Filename::UTF8(DjVuDataDir); appendPath(dpath,pathsmap,paths); #endif #ifdef WIN32 appendPath(RegOpenReadConfig(HKEY_CURRENT_USER),pathsmap,paths); appendPath(RegOpenReadConfig(HKEY_LOCAL_MACHINE),pathsmap,paths); #else GUTF8String home=GOS::getenv("HOME"); # if HAVE_GETPWUID if (! home.length()) { struct passwd *pw=0; if ((pw = getpwuid(getuid()))) home=GNativeString(pw->pw_dir); } # endif if (home.length()) { GURL hpath = GURL::UTF8(LocalDjVuDir,GURL::Filename::UTF8(home)); appendPath(hpath,pathsmap,paths); } #endif #ifdef LT_DEFAULT_PREFIX appendPath(GURL::Filename::UTF8(DjVuPrefixDir),pathsmap,paths); #endif appendPath(GURL::Filename::UTF8(RootDjVuDir),pathsmap,paths); pathsmap.empty(); GPosition pos; GList< GMap<GUTF8String,GP<lt_XMLTags> > > localemaps; for(pos=paths;pos;++pos) { path=GURL::UTF8(LanguageFile,paths[pos]); if(path.is_file()) { const GP<lt_XMLTags> xml(lt_XMLTags::create(ByteStream::create(path,"rb"))); const GPList<lt_XMLTags> Body(xml->get_Tags(bodystring)); GPosition pos=Body; if(!pos || (pos != Body.lastpos())) { G_THROW( ERR_MSG("XMLAnno.extra_body") ); } const GP<lt_XMLTags> GBody(Body[pos]); if(!GBody) { G_THROW( ERR_MSG("XMLAnno.no_body") ); } GMap<GUTF8String,GP<lt_XMLTags> > localemap; lt_XMLTags::get_Maps(languagestring,localestring,Body,localemap); localemaps.append(localemap); } } GList<GURL> localepaths; GList<GURL> osilocalepaths; // Need to do it the right way! GUTF8String defaultlocale = getenv("LANGUAGE"); if (! defaultlocale) { const GUTF8String oldlocale(setlocale(LC_MESSAGES,0)); defaultlocale = setlocale(LC_MESSAGES,""); setlocale(LC_MESSAGES,(const char *)oldlocale); } // Unfathomable search. for(int loop=0; loop<2; loop++) { static const char sepchars[]=" _.@"; const char *p=sepchars+sizeof(sepchars)-1; do { int sepcharpos=p[0]?defaultlocale.search(p[0]):defaultlocale.length(); if(sepcharpos > 0) { const GUTF8String sublocale(defaultlocale,sepcharpos); const GUTF8String downcasesublocale("downcase^"+sublocale.downcase()); for(pos=localemaps;pos;++pos) { const GMap<GUTF8String,GP<lt_XMLTags> > &localemap=localemaps[pos]; GPosition pos=localemap.contains(sublocale); if(!pos) pos=localemap.contains(downcasesublocale); if(pos) { const GMap<GUTF8String,GUTF8String>&args = localemap[pos]->get_args(); pos = args.contains(srcstring); if (pos) { const GUTF8String src(args[pos]); for(pos=paths;pos;++pos) { path=GURL::UTF8(src,paths[pos]); if(path.is_dir()) localepaths.append(path); path=GURL::UTF8(GUTF8String(opensourcedir)+"/"+src,paths[pos]); if(path.is_dir()) osilocalepaths.append(path); } } // We don't need to check anymore language files. p=sepchars; break; } } if(!pos) { for(pos=paths;pos;++pos) { path=GURL::UTF8(sublocale,paths[pos]); if(path.is_dir()) { localepaths.append(path); } path=GURL::UTF8(GUTF8String(opensourcedir)+"/"+sublocale,paths[pos]); if(path.is_dir()) { osilocalepaths.append(path); } } } } } while(p-- != sepchars); if((GPosition) localepaths) break; defaultlocale="C"; } for(pos=localepaths;pos;++pos) appendPath(localepaths[pos],pathsmap,realpaths); for(pos=paths;pos;++pos) appendPath(paths[pos],pathsmap,realpaths); for(pos=osilocalepaths;pos;++pos) appendPath(osilocalepaths[pos],pathsmap,realpaths); for(pos=paths;pos;++pos) { path=GURL::UTF8(opensourcedir,paths[pos]); appendPath(path,pathsmap,realpaths); } } return realpaths; }