Пример #1
0
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
}
Пример #2
0
void Display::printString(const Common::String &str) {
	Common::String::const_iterator c;
	for (c = str.begin(); c != str.end(); ++c)
		printChar(*c);

	updateTextScreen();
}
Пример #3
0
// 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;
}
Пример #4
0
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);
}
Пример #5
0
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;
}
Пример #6
0
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();
}
Пример #7
0
/* 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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
void SaveFileWriteStream::writeStringSz(const Common::String &s, int sz) {
	assert(s.size() < (uint)sz);
	write(s.begin(), s.size());
	padBytes((uint)sz - s.size());
}