Common::String FontManager::genLocalizedFontFilename(const Common::String &filename) const { #ifndef USE_TRANSLATION return filename; #else // We will transform the font filename in the following way: // name.bdf // will become: // name-charset.bdf // Note that name should not contain any dot here! // In the first step we look for the dot. In case there is none we will // return the normal filename. Common::String::const_iterator dot = Common::find(filename.begin(), filename.end(), '.'); if (dot == filename.end()) return filename; // Put the translated font filename string back together. Common::String result(filename.begin(), dot); result += '-'; result += TransMan.getCurrentCharset(); result += dot; return result; #endif }
void Display::printString(const Common::String &str) { Common::String::const_iterator c; for (c = str.begin(); c != str.end(); ++c) printChar(*c); updateTextScreen(); }
// returns true if something has been completed // completion has to be delete[]-ed then bool Debugger::tabComplete(const char *input, Common::String &completion) const { // very basic tab completion // for now it just supports command completions // adding completions of command parameters would be nice (but hard) :-) // maybe also give a list of possible command completions? // (but this will require changes to console) if (strchr(input, ' ')) return false; // already finished the first word const uint inputlen = strlen(input); completion.clear(); CommandsMap::const_iterator i, e = _cmds.end(); for (i = _cmds.begin(); i != e; ++i) { if (i->_key.hasPrefix(input)) { uint commandlen = i->_key.size(); if (commandlen == inputlen) { // perfect match, so no tab completion possible return false; } if (commandlen > inputlen) { // possible match // no previous match if (completion.empty()) { completion = i->_key.c_str() + inputlen; } else { // take common prefix of previous match and this command for (uint j = 0; j < completion.size(); j++) { if (inputlen + j >= i->_key.size() || completion[j] != i->_key[inputlen + j]) { completion = Common::String(completion.begin(), completion.begin() + j); // If there is no unambiguous completion, abort if (completion.empty()) return false; break; } } } } } } if (completion.empty()) return false; return true; }
void Display::printAsciiString(const Common::String &str) { Common::String aStr; Common::String::const_iterator it; for (it = str.begin(); it != str.end(); ++it) aStr += APPLECHAR(*it); printString(aStr); }
bool assureDirectoryExists(const Common::String &dir, const char *prefix) { // Check whether the prefix exists if one is supplied. if (prefix) { if (!path_is_valid(prefix)) return false; else if (!path_is_directory(prefix)) return false; } // Obtain absolute path. Common::String path; if (prefix) { path = prefix; path += '/'; path += dir; } else { path = dir; } path = Common::normalizePath(path, '/'); const Common::String::iterator end = path.end(); Common::String::iterator cur = path.begin(); if (*cur == '/') ++cur; do { if (cur + 1 != end) { if (*cur != '/') continue; // It is kind of ugly and against the purpose of Common::String to // insert 0s inside, but this is just for a local string and // simplifies the code a lot. *cur = '\0'; } if (!mkdir_norecurse(path.c_str())) { if (errno == EEXIST) { if (!path_is_valid(path.c_str())) return false; else if (!path_is_directory(path.c_str())) return false; } else return false; } *cur = '/'; } while (cur++ != end); return true; }
void Display::printString(const Common::String &str) { Common::String::const_iterator c; for (c = str.begin(); c != str.end(); ++c) { byte b = *c; if (*c == APPLECHAR('\r')) _cursorPos = (_cursorPos / TEXT_WIDTH + 1) * TEXT_WIDTH; else if (b < 0x80 || b >= 0xa0) { setCharAtCursor(b); ++_cursorPos; } if (_cursorPos == TEXT_BUF_SIZE) scrollUp(); } updateTextScreen(); }
/* Converts CP895 string to 7bit ASCII, so we can show it in the console. */ static Common::String convertToASCII(const Common::String &str) { static const char conversionTable[] = { 'C', 'u', 'e', 'd', 'a', 'D', 'T', 'c', 'e', 'E', 'L', 'I', 'l', 'l', 'A', 'A', /* 0x80-0x8F */ 'E', 'z', 'Z', 'o', 'o', 'O', 'u', 'U', 'y', 'O', 'U', 'S', 'L', 'Y', 'R', 't', /* 0x90-0x9F */ 'a', 'i', 'o', 'u', 'n', 'N', 'U', 'O', 's', 'r', 'r', 'R' /* 0xA0-0xAB */ }; Common::String ret = str; for (Common::String::iterator it = ret.begin(); it != ret.end(); ++it) { const byte cp895Byte = reinterpret_cast<const byte &>(*it); if (cp895Byte >= 0x80 && cp895Byte <= 0xAB) { *it = conversionTable[cp895Byte - 0x80]; } else if (cp895Byte == 0xE1) { // ß *it = 's'; } } return ret; }
Common::Error GagEngine::StateScript() { Common::Error status(Common::kNoError); Common::File file; if(file.open(_script, *_archive)) { // simple script parsing: skim through, find section and execute commands ParserState parse_state(PS_SECTION_SEARCH); Common::String buffer; Common::String command_name; bool done(false); while(!file.eos()) { // add space for multiline command support Common::String line = file.readLine() + ' '; if(file.err()) { status = Common::Error(Common::kReadingFailed, _script + ", readLine()"); break; } bool skip_line(false); for(Common::String::const_iterator it = line.begin(); it != line.end(); ++it) { switch(parse_state) { case PS_SECTION_SEARCH: // section if(*it == '[') { buffer.clear(); parse_state = PS_SECTION_NAME; } break; case PS_SECTION_NAME: // section end if(*it == ']') { #ifdef DEBUG_SKIM_SCRIPT parse_state = PS_SECTION_BODY; #else if(buffer == _section) parse_state = PS_SECTION_BODY; else if(buffer == _END_SECTION) { status = Common::Error(Common::kUnknownError, "[" + _section + "] script section not found"); skip_line = true; done = true; } else parse_state = PS_SECTION_SEARCH; #endif } else buffer += *it; break; case PS_SECTION_BODY: // section if(*it == '[') { #ifdef DEBUG_SKIM_SCRIPT buffer.clear(); parse_state = PS_SECTION_NAME; #else skip_line = true; done = true; #endif } // comment else if(*it == '*') { skip_line = true; } //NOTE: invalid syntax else if(*it == '-' || *it == '/' || (*it >= 'A' && *it <= 'Z')) { #ifndef DEBUG_SKIM_SCRIPT warning("invalid script syntax [file: %s, section: %s, line: \"%s\"], skipped", _script.c_str(), _section.c_str(), line.c_str()); #endif skip_line = true; } // command name else if((*it >= 'a' && *it <= 'z')) { buffer.clear(); buffer += *it; parse_state = PS_COMMAND_NAME; } break; case PS_COMMAND_NAME: // command value if(*it == '=') { command_name = buffer; buffer.clear(); parse_state = PS_COMMAND_VALUE; } else buffer += *it; break; case PS_COMMAND_VALUE: // command value end if(*it == ';') { command_name.trim(); buffer.trim(); #ifndef DEBUG_SKIM_SCRIPT debug("%s=%s;", command_name.c_str(), buffer.c_str()); #endif Common::HashMap<Common::String, Common::Error (GagEngine::*)(const Common::String &)>::const_iterator f = _commandCallbacks.find(command_name); if(f != _commandCallbacks.end()) { status = (this->*f->_value)(buffer); if(status.getCode() != Common::kNoError) { skip_line = true; done = true; } } parse_state = PS_SECTION_BODY; } else buffer += *it; break; } if(skip_line) break; } if(done) break; } } else { status = Common::Error(Common::kReadingFailed, _script + ", open()"); } return status; }
int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const { WordWrapper wrapper(lines); Common::String line; Common::String tmpStr; int lineWidth = 0; int tmpWidth = 0; // The rough idea behind this algorithm is as follows: // We accumulate characters into the string tmpStr. Whenever a full word // has been gathered together this way, we 'commit' it to the line buffer // 'line', i.e. we add tmpStr to the end of line, then clear it. Before // we do that, we check whether it would cause 'line' to exceed maxWidth; // in that case, we first add line to lines, then reset it. // // If a newline character is read, then we also add line to lines and clear it. // // Special care has to be taken to account for 'words' that exceed the width // of a line. If we encounter such a word, we have to wrap it over multiple // lines. uint last = 0; for (Common::String::const_iterator x = str.begin(); x != str.end(); ++x) { const byte c = *x; const int w = getCharWidth(c) + getKerningOffset(last, c); last = c; const bool wouldExceedWidth = (lineWidth + tmpWidth + w > maxWidth); // If this char is a whitespace, then it represents a potential // 'wrap point' where wrapping could take place. Everything that // came before it can now safely be added to the line, as we know // that it will not have to be wrapped. if (Common::isSpace(c)) { line += tmpStr; lineWidth += tmpWidth; tmpStr.clear(); tmpWidth = 0; // If we encounter a line break (\n), or if the new space would // cause the line to overflow: start a new line if (c == '\n' || wouldExceedWidth) { wrapper.add(line, lineWidth); continue; } } // If the max line width would be exceeded by adding this char, // insert a line break. if (wouldExceedWidth) { // Commit what we have so far, *if* we have anything. // If line is empty, then we are looking at a word // which exceeds the maximum line width. if (lineWidth > 0) { wrapper.add(line, lineWidth); // Trim left side while (tmpStr.size() && Common::isSpace(tmpStr[0])) { tmpStr.deleteChar(0); // This is not very fast, but it is the simplest way to // assure we do not mess something up because of kerning. tmpWidth = getStringWidth(tmpStr); } } else { wrapper.add(tmpStr, tmpWidth); } } tmpWidth += w; tmpStr += c; } // If some text is left over, add it as the final line line += tmpStr; lineWidth += tmpWidth; if (lineWidth > 0) { wrapper.add(line, lineWidth); } return wrapper.actualMaxLineWidth; }
void SaveFileWriteStream::writeStringSz(const Common::String &s, int sz) { assert(s.size() < (uint)sz); write(s.begin(), s.size()); padBytes((uint)sz - s.size()); }