AmigaOSFilesystemNode::AmigaOSFilesystemNode(const Common::String &p) { ENTER(); int offset = p.size(); //assert(offset > 0); if (offset <= 0) { debug(6, "Bad offset"); return; } _sPath = p; _sDisplayName = ::lastPathComponent(_sPath); _pFileLock = 0; _bIsDirectory = false; _bIsValid = false; // Check whether the node exists and if it's a directory struct ExamineData * pExd = IDOS->ExamineObjectTags(EX_StringNameInput,_sPath.c_str(),TAG_END); if (pExd) { _nProt = pExd->Protection; if (EXD_IS_DIRECTORY(pExd)) { _bIsDirectory = true; _pFileLock = IDOS->Lock((CONST_STRPTR)_sPath.c_str(), SHARED_LOCK); _bIsValid = (_pFileLock != 0); // Add a trailing slash if needed const char c = _sPath.lastChar(); if (c != '/' && c != ':') _sPath += '/'; } else { //_bIsDirectory = false; _bIsValid = true; } IDOS->FreeDosObject(DOS_EXAMINEDATA, pExd); } LEAVE(); }
void IdCreateDirectoryRequest::start() { //cleanup _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); _workingRequest = nullptr; _ignoreCallback = false; //the only exception when we create parent folder - is when it's ScummVM/ base folder Common::String prefix = _requestedParentPath; if (prefix.size() > 7) prefix.erase(7); if (prefix.equalsIgnoreCase("ScummVM")) { Storage::BoolCallback callback = new Common::Callback<IdCreateDirectoryRequest, Storage::BoolResponse>(this, &IdCreateDirectoryRequest::createdBaseDirectoryCallback); Networking::ErrorCallback failureCallback = new Common::Callback<IdCreateDirectoryRequest, Networking::ErrorResponse>(this, &IdCreateDirectoryRequest::createdBaseDirectoryErrorCallback); _workingRequest = _storage->createDirectory("ScummVM", callback, failureCallback); return; } resolveId(); }
bool MessageState::stringHex(Common::String &outStr, const Common::String &inStr, uint &index) { // Hex escape sequences of the form \nn, where n is a hex digit if (inStr[index] != '\\') return false; // Check for enough room for a hex escape sequence if (index + 2 >= inStr.size()) return false; int digit1 = hexDigitToInt(inStr[index + 1]); int digit2 = hexDigitToInt(inStr[index + 2]); // Check for hex if ((digit1 == -1) || (digit2 == -1)) return false; outStr += digit1 * 16 + digit2; index += 3; return true; }
AbstractFSNode *WindowsFilesystemNode::getParent() const { assert(_isValid || _isPseudoRoot); if (_isPseudoRoot) return 0; WindowsFilesystemNode *p = new WindowsFilesystemNode(); if (_path.size() > 3) { const char *start = _path.c_str(); const char *end = lastPathComponent(_path, '\\'); p = new WindowsFilesystemNode(); p->_path = Common::String(start, end - start); p->_isValid = true; p->_isDirectory = true; p->_displayName = lastPathComponent(p->_path, '\\'); p->_isPseudoRoot = false; } return p; }
void BoxStorage::loadKeyAndSecret() { #ifdef ENABLE_RELEASE KEY = RELEASE_BOX_KEY; SECRET = RELEASE_BOX_SECRET; #else Common::String k = ConfMan.get("BOX_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); KEY[k.size()] = 0; k = ConfMan.get("BOX_SECRET", ConfMan.kCloudDomain); SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; #endif }
void MessageState::outputString(reg_t buf, const Common::String &str) { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { if (_segMan->getSegmentType(buf.getSegment()) == SEG_TYPE_STRING) { SciString *sciString = _segMan->lookupString(buf); sciString->setSize(str.size() + 1); for (uint32 i = 0; i < str.size(); i++) sciString->setValue(i, str.c_str()[i]); sciString->setValue(str.size(), 0); } else if (_segMan->getSegmentType(buf.getSegment()) == SEG_TYPE_ARRAY) { // Happens in the intro of LSL6, we are asked to write the string // into an array SciArray<reg_t> *sciString = _segMan->lookupArray(buf); sciString->setSize(str.size() + 1); for (uint32 i = 0; i < str.size(); i++) sciString->setValue(i, make_reg(0, str.c_str()[i])); sciString->setValue(str.size(), NULL_REG); } } else { #endif SegmentRef buffer_r = _segMan->dereference(buf); if ((unsigned)buffer_r.maxSize >= str.size() + 1) { _segMan->strcpy(buf, str.c_str()); } else { // LSL6 sets an exit text here, but the buffer size allocated // is too small. Don't display a warning in this case, as we // don't use the exit text anyway - bug report #3035533 if (g_sci->getGameId() == GID_LSL6 && str.hasPrefix("\r\n(c) 1993 Sierra On-Line, Inc")) { // LSL6 buggy exit text, don't show warning } else { warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str()); } // Set buffer to empty string if possible if (buffer_r.maxSize > 0) _segMan->strcpy(buf, ""); } #ifdef ENABLE_SCI32 } #endif }
Common::String lastPathComponent(const Common::String &path, const char sep) { const char *str = path.c_str(); const char *last = str + path.size(); // Skip over trailing slashes while (last > str && *(last-1) == sep) --last; // Path consisted of only slashes -> return empty string if (last == str) return Common::String(); // Now scan the whole component const char *first = last - 1; while (first >= str && *first != sep) --first; if (*first == sep) first++; return Common::String(first, last); }
void GoogleDriveUploadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; //not resolved => error or no such file if (error.response.contains("no such file found in its parent directory")) { //parent's id after the '\n' Common::String parentId = error.response; for (uint32 i = 0; i < parentId.size(); ++i) if (parentId[i] == '\n') { parentId.erase(0, i + 1); break; } _parentId = parentId; startUpload(); return; } finishError(error); }
DSFileSystemNode::DSFileSystemNode(const Common::String& path) { // consolePrintf("--%s ",path.c_str()); int lastSlash = 3; for (int r = 0; r < (int) path.size() - 1; r++) { if (path[r] == '\\') { lastSlash = r; } } _displayName = Common::String(path.c_str() + lastSlash + 1); _path = path; // _isValid = true; // _isDirectory = false; const char *pathStr = path.c_str(); if (path.hasPrefix("ds:/")) { pathStr += 4; } if (*pathStr == '\0') { _isValid = true; _isDirectory = true; return; } _zipFile->setAllFilesVisible(true); if (_zipFile->findFile(pathStr)) { _isValid = true; _isDirectory = _zipFile->isDirectory(); } else { _isValid = false; _isDirectory = false; } _zipFile->setAllFilesVisible(false); // consolePrintf("%s - Found: %d, Dir: %d\n", pathStr, _isValid, _isDirectory); }
int16 Text::count() { EncryptedStream tf(_vm, _fileName); if (tf.err()) return -1; Common::String line; char tmpStr[kLineMax + 1]; int counter = 0; for (line = tf.readLine(); !tf.eos(); line = tf.readLine()) { char *s; assert(line.size() <= 513); strcpy(tmpStr, line.c_str()); if ((s = strtok(tmpStr, " =,;/\t\n")) == NULL) continue; if (!Common::isDigit(*s)) continue; counter++; } return counter; }
void LabEngine::doWestPaper() { TextFont *paperFont = _resource->getFont("F:News22.fon"); Common::String paperText = _resource->getText("Lab:Rooms/Date"); Common::Rect textRect = Common::Rect(_utils->vgaScaleX(57), _utils->vgaScaleY(77) + _utils->svgaCord(2), _utils->vgaScaleX(262), _utils->vgaScaleY(91)); _graphics->flowText(paperFont, 0, 0, 0, false, true, false, true, textRect, paperText.c_str()); _graphics->freeFont(&paperFont); paperFont = _resource->getFont("F:News32.fon"); paperText = _resource->getText("Lab:Rooms/Headline"); int fileLen = paperText.size() - 1; textRect = Common::Rect(_utils->vgaScaleX(57), _utils->vgaScaleY(86) - _utils->svgaCord(2), _utils->vgaScaleX(262), _utils->vgaScaleY(118)); int charsPrinted = _graphics->flowText(paperFont, -8, 0, 0, false, true, false, true, textRect, paperText.c_str()); uint16 y; if (charsPrinted < fileLen) { y = 130 - _utils->svgaCord(5); textRect = Common::Rect(_utils->vgaScaleX(57), _utils->vgaScaleY(86) - _utils->svgaCord(2), _utils->vgaScaleX(262), _utils->vgaScaleY(132)); _graphics->flowText(paperFont, -8 - _utils->svgaCord(1), 0, 0, false, true, false, true, textRect, paperText.c_str()); } else y = 115 - _utils->svgaCord(5); _graphics->freeFont(&paperFont); paperFont = _resource->getFont("F:Note.fon"); paperText = _resource->getText("Lab:Rooms/Col1"); _graphics->flowText(paperFont, -4, 0, 0, false, false, false, true, _utils->vgaRectScale(45, y, 158, 148), paperText.c_str()); paperText = _resource->getText("Lab:Rooms/Col2"); _graphics->flowText(paperFont, -4, 0, 0, false, false, false, true, _utils->vgaRectScale(162, y, 275, 148), paperText.c_str()); _graphics->freeFont(&paperFont); _graphics->setPalette(_anim->_diffPalette, 256); }
bool SaveManager::scummVMSaveLoadDialog(bool isSave) { GUI::SaveLoadChooser *dialog; Common::String desc; int slot; if (isSave) { dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); slot = dialog->runModalWithCurrentTarget(); desc = dialog->getResultString(); if (desc.empty()) { // create our own description for the saved game, the user didnt enter it desc = dialog->createDefaultSaveDescription(slot); } if (desc.size() > 28) desc = Common::String(desc.c_str(), 28); } else { dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); slot = dialog->runModalWithCurrentTarget(); } delete dialog; if (slot < 0) return false; if (isSave) { saveGame(slot, desc, false); return true; } else { Common::ErrorCode result = loadGame(slot).getCode(); return (result == Common::kNoError); } }
// we need to have a separate status drawing code // In KQ4 the IV char is actually 0xA, which would otherwise get considered as linebreak and not printed void GfxText16::DrawStatus(const Common::String &str) { uint16 curChar, charWidth; const byte *text = (const byte *)str.c_str(); uint16 textLen = str.size(); Common::Rect rect; GetFont(); if (!_font) return; rect.top = _ports->_curPort->curTop; rect.bottom = rect.top + _ports->_curPort->fontHeight; while (textLen--) { curChar = *text++; switch (curChar) { case 0: break; default: charWidth = _font->getCharWidth(curChar); _font->draw(curChar, _ports->_curPort->top + _ports->_curPort->curTop, _ports->_curPort->left + _ports->_curPort->curLeft, _ports->_curPort->penClr, _ports->_curPort->greyedOutput); _ports->_curPort->curLeft += charWidth; } } }
Common::String DefinitionRegistry::stringToCamelCase(const Common::String &input) { Common::String clean = input; // First replace all non alphanumerical characters with spaces for (uint i = 0; i < clean.size(); i++) { if (!Common::isAlnum(clean[i])) { clean.setChar(' ', i); } } // Then turn the string into camel case Common::String output; Common::StringTokenizer tokens = Common::StringTokenizer(clean); while (!tokens.empty()) { Common::String token = tokens.nextToken(); char upperFirstLetter = toupper(token[0]); token.setChar(upperFirstLetter, 0); output += token; } return output; }
void GoogleDriveUploadRequest::startUpload() { Common::String name = _savePath; for (uint32 i = name.size(); i > 0; --i) { if (name[i - 1] == '/' || name[i - 1] == '\\') { name.erase(0, i); break; } } Common::String url = GOOGLEDRIVE_API_FILES; if (_resolvedId != "") url += "/" + ConnMan.urlEncode(_resolvedId); url += "?uploadType=resumable&fields=id,mimeType,modifiedTime,name,size"; Networking::JsonCallback callback = new Common::Callback<GoogleDriveUploadRequest, Networking::JsonResponse>(this, &GoogleDriveUploadRequest::startUploadCallback); Networking::ErrorCallback failureCallback = new Common::Callback<GoogleDriveUploadRequest, Networking::ErrorResponse>(this, &GoogleDriveUploadRequest::startUploadErrorCallback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _storage->accessToken()); request->addHeader("Content-Type: application/json"); if (_resolvedId != "") request->usePatch(); Common::JSONObject jsonRequestParameters; if (_resolvedId != "") { jsonRequestParameters.setVal("id", new Common::JSONValue(_resolvedId)); } else { Common::JSONArray parentsArray; parentsArray.push_back(new Common::JSONValue(_parentId)); jsonRequestParameters.setVal("parents", new Common::JSONValue(parentsArray)); } jsonRequestParameters.setVal("name", new Common::JSONValue(name)); Common::JSONValue value(jsonRequestParameters); request->addPostField(Common::JSON::stringify(&value)); _workingRequest = ConnMan.addRequest(request); }
void Inter_Geisha::oGeisha_checkData(OpFuncParams ¶ms) { Common::String file = _vm->_game->_script->evalString(); int16 varOff = _vm->_game->_script->readVarIndex(); file.toLowercase(); if (file.hasSuffix(".0ot")) file.setChar('t', file.size() - 3); bool exists = false; SaveLoad::SaveMode mode = _vm->_saveLoad->getSaveMode(file.c_str()); if (mode == SaveLoad::kSaveModeNone) { exists = _vm->_dataIO->hasFile(file); if (!exists) warning("File \"%s\" not found", file.c_str()); } else if (mode == SaveLoad::kSaveModeSave) exists = _vm->_saveLoad->getSize(file.c_str()) >= 0; else if (mode == SaveLoad::kSaveModeExists) exists = true; WRITE_VAR_OFFSET(varOff, exists ? 50 : (uint32)-1); }
void TinyGLRenderer::draw2DText(const Common::String &text, const Common::Point &position) { TinyGLTexture *glFont = static_cast<TinyGLTexture *>(_font); // The font only has uppercase letters Common::String textToDraw = text; textToDraw.toUppercase(); tglEnable(TGL_BLEND); tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA); tglEnable(TGL_TEXTURE_2D); tglDepthMask(TGL_FALSE); tglColor3f(1.0f, 1.0f, 1.0f); tglBindTexture(TGL_TEXTURE_2D, glFont->id); int x = position.x; int y = position.y; for (uint i = 0; i < textToDraw.size(); i++) { Common::Rect textureRect = getFontCharacterRect(textToDraw[i]); int w = textureRect.width(); int h = textureRect.height(); Graphics::BlitTransform transform(x, y); transform.sourceRectangle(textureRect.left, textureRect.top, w, h); transform.flip(true, false); Graphics::tglBlit(glFont->getBlitTexture(), transform); x += textureRect.width() - 3; } tglDisable(TGL_TEXTURE_2D); tglDisable(TGL_BLEND); tglDepthMask(TGL_TRUE); }
Common::String SciEngine::unwrapFilename(const Common::String &name) const { Common::String prefix = getFilePrefix() + "-"; if (name.hasPrefix(prefix.c_str())) return Common::String(name.c_str() + prefix.size()); return name; }
bool Quetzal::save(Common::WriteStream *svf, Processor *proc, const Common::String &desc) { Processor &p = *proc; uint ifzslen = 0, cmemlen = 0, stkslen = 0, descLen = 0; uint pc; zword i, j, n; zword nvars, nargs, nstk; zbyte var; long cmempos, stkspos; int c; // Set a temporary memory stream for writing out the data. This is needed, since we need to // do some seeking within it at the end to fill out totals before properly writing it all out Common::MemoryWriteStreamDynamic saveData(DisposeAfterUse::YES); _out = &saveData; // Write `IFZS' header. write_chnk(ID_FORM, 0); write_long(ID_IFZS); // Write `IFhd' chunk pc = p.getPC(); write_chnk(ID_IFhd, 13); write_word(p.h_release); for (i = H_SERIAL; i<H_SERIAL + 6; ++i) write_byte(p[i]); write_word(p.h_checksum); write_long(pc << 8); // Includes pad // Write 'ANNO' chunk descLen = desc.size() + 1; write_chnk(ID_ANNO, descLen); saveData.write(desc.c_str(), desc.size()); write_byte(0); if ((desc.size() % 2) == 0) { write_byte(0); ++descLen; } // Write `CMem' chunk. cmempos = saveData.pos(); write_chnk(ID_CMem, 0); _storyFile->seek(0); // j holds current run length. for (i = 0, j = 0, cmemlen = 0; i < p.h_dynamic_size; ++i) { c = _storyFile->readByte(); c ^= p[i]; if (c == 0) { // It's a run of equal bytes ++j; } else { // Write out any run there may be. if (j > 0) { for (; j > 0x100; j -= 0x100) { write_run(0xFF); cmemlen += 2; } write_run(j - 1); cmemlen += 2; j = 0; } // Any runs are now written. Write this (nonzero) byte write_byte((zbyte)c); ++cmemlen; } } // Reached end of dynamic memory. We ignore any unwritten run there may be at this point. if (cmemlen & 1) // Chunk length must be even. write_byte(0); // Write `Stks' chunk. You are not expected to understand this. ;) stkspos = saveData.pos(); write_chnk(ID_Stks, 0); // We construct a list of frame indices, most recent first, in `frames'. // These indices are the offsets into the `stack' array of the word before // the first word pushed in each frame. frames[0] = p._sp - p._stack; // The frame we'd get by doing a call now. for (i = p._fp - p._stack + 4, n = 0; i < STACK_SIZE + 4; i = p._stack[i - 3] + 5) frames[++n] = i; // All versions other than V6 can use evaluation stack outside a function // context. We write a faked stack frame (most fields zero) to cater for this. if (p.h_version != V6) { for (i = 0; i < 6; ++i) write_byte(0); nstk = STACK_SIZE - frames[n]; write_word(nstk); for (j = STACK_SIZE - 1; j >= frames[n]; --j) write_word(p._stack[j]); stkslen = 8 + 2 * nstk; } // Write out the rest of the stack frames. for (i = n; i > 0; --i) { zword *pf = p._stack + frames[i] - 4; // Points to call frame nvars = (pf[0] & 0x0F00) >> 8; nargs = pf[0] & 0x00FF; nstk = frames[i] - frames[i - 1] - nvars - 4; pc = ((uint)pf[3] << 9) | pf[2]; // Check type of call switch (pf[0] & 0xF000) { case 0x0000: // Function var = p[pc]; pc = ((pc + 1) << 8) | nvars; break; case 0x1000: // Procedure var = 0; pc = (pc << 8) | 0x10 | nvars; // Set procedure flag break; default: p.runtimeError(ERR_SAVE_IN_INTER); return 0; } if (nargs != 0) nargs = (1 << nargs) - 1; // Make args into bitmap // Write the main part of the frame... write_long(pc); write_byte(var); write_byte(nargs); write_word(nstk); // Write the variables and eval stack for (j = 0, --pf; j<nvars + nstk; ++j, --pf) write_word(*pf); // Calculate length written thus far stkslen += 8 + 2 * (nvars + nstk); } // Fill in variable chunk lengths ifzslen = 4 * 8 + 4 + 14 + cmemlen + stkslen + descLen; if (cmemlen & 1) ++ifzslen; saveData.seek(4); saveData.writeUint32BE(ifzslen); saveData.seek(cmempos + 4); saveData.writeUint32BE(cmemlen); saveData.seek(stkspos + 4); saveData.writeUint32BE(stkslen); // Write the save data out svf->write(saveData.getData(), saveData.size()); // After all that, still nothing went wrong! return true; }
/** * Save game to supplied slot */ bool FileManager::saveGame(const int16 slot, const Common::String &descrip) { debugC(1, kDebugFile, "saveGame(%d, %s)", slot, descrip.c_str()); int16 savegameId; Common::String savegameDescription; if (slot == -1) { GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true); savegameId = dialog->runModalWithCurrentTarget(); savegameDescription = dialog->getResultString(); delete dialog; } else { savegameId = slot; if (!descrip.empty()) { savegameDescription = descrip; } else { savegameDescription = Common::String::format("Quick save #%d", slot); } } if (savegameId < 0) // dialog aborted return false; Common::String savegameFile = _vm->getSavegameFilename(savegameId); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::OutSaveFile *out = saveMan->openForSaving(savegameFile); if (!out) { warning("Can't create file '%s', game not saved", savegameFile.c_str()); return false; } // Write version. We can't restore from obsolete versions out->writeByte(kSavegameVersion); if (savegameDescription == "") { savegameDescription = "Untitled savegame"; } out->writeSint16BE(savegameDescription.size() + 1); out->write(savegameDescription.c_str(), savegameDescription.size() + 1); Graphics::saveThumbnail(*out); TimeDate curTime; _vm->_system->getTimeAndDate(curTime); uint32 saveDate = (curTime.tm_mday & 0xFF) << 24 | ((curTime.tm_mon + 1) & 0xFF) << 16 | ((curTime.tm_year + 1900) & 0xFFFF); uint16 saveTime = (curTime.tm_hour & 0xFF) << 8 | ((curTime.tm_min) & 0xFF); out->writeUint32BE(saveDate); out->writeUint16BE(saveTime); _vm->_object->saveObjects(out); const Status &gameStatus = _vm->getGameStatus(); // Save whether hero image is swapped out->writeByte(_vm->_heroImage); // Save score out->writeSint16BE(_vm->getScore()); // Save story mode out->writeByte((gameStatus._storyModeFl) ? 1 : 0); // Save jumpexit mode out->writeByte((_vm->_mouse->getJumpExitFl()) ? 1 : 0); // Save gameover status out->writeByte((gameStatus._gameOverFl) ? 1 : 0); // Save screen states for (int i = 0; i < _vm->_numStates; i++) out->writeByte(_vm->_screenStates[i]); _vm->_scheduler->saveSchedulerData(out); // Save palette table _vm->_screen->savePal(out); // Save maze status out->writeByte((_vm->_maze._enabledFl) ? 1 : 0); out->writeByte(_vm->_maze._size); out->writeSint16BE(_vm->_maze._x1); out->writeSint16BE(_vm->_maze._y1); out->writeSint16BE(_vm->_maze._x2); out->writeSint16BE(_vm->_maze._y2); out->writeSint16BE(_vm->_maze._x3); out->writeSint16BE(_vm->_maze._x4); out->writeByte(_vm->_maze._firstScreenIndex); out->writeByte((byte)_vm->getGameStatus()._viewState); out->finalize(); delete out; return true; }
reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text)); // The object in the text selector of the item can be either a raw string // or a Str object. In the latter case, we need to access the object's data // selector to get the raw string. if (_segMan->isHeapObject(stringObject)) stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); Common::String text = _segMan->getString(stringObject); // HACK: The character offsets of the up and down arrow buttons are off by one // in GK1, for some unknown reason. Fix them here. if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) { text.setChar(text[0] + 1, 0); } GuiResourceId fontId = readSelectorValue(_segMan, textObject, SELECTOR(font)); GfxFont *font = _cache->getFont(fontId); bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed)); int16 alignment = readSelectorValue(_segMan, textObject, SELECTOR(mode)); uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject); uint16 width = nsRect.width() + 1; uint16 height = nsRect.height() + 1; // Limit rectangle dimensions, if requested if (maxWidth > 0) width = maxWidth; if (maxHeight > 0) height = maxHeight; // Upscale the coordinates/width if the fonts are already upscaled if (_screen->fontIsUpscaled()) { width = width * _screen->getDisplayWidth() / _screen->getWidth(); height = height * _screen->getDisplayHeight() / _screen->getHeight(); } int entrySize = width * height + BITMAP_HEADER_SIZE; reg_t memoryId = NULL_REG; if (prevHunk.isNull()) { memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); } else { memoryId = prevHunk; } byte *memoryPtr = _segMan->getHunkPointer(memoryId); if (prevHunk.isNull()) memset(memoryPtr, 0, BITMAP_HEADER_SIZE); byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; memset(bitmap, backColor, width * height); // Save totalWidth, totalHeight WRITE_LE_UINT16(memoryPtr, width); WRITE_LE_UINT16(memoryPtr + 2, height); int16 charCount = 0; uint16 curX = 0, curY = 0; const char *txt = text.c_str(); int16 textWidth, textHeight, totalHeight = 0, offsetX = 0, offsetY = 0; uint16 start = 0; // Calculate total text height while (*txt) { charCount = GetLongest(txt, width, font); if (charCount == 0) break; Width(txt, 0, (int16)strlen(txt), fontId, textWidth, textHeight, true); totalHeight += textHeight; txt += charCount; while (*txt == ' ') txt++; // skip over breaking spaces } txt = text.c_str(); // Draw text in buffer while (*txt) { charCount = GetLongest(txt, width, font); if (charCount == 0) break; Width(txt, start, charCount, fontId, textWidth, textHeight, true); switch (alignment) { case SCI_TEXT32_ALIGNMENT_RIGHT: offsetX = width - textWidth; break; case SCI_TEXT32_ALIGNMENT_CENTER: // Center text both horizontally and vertically offsetX = (width - textWidth) / 2; offsetY = (height - totalHeight) / 2; break; case SCI_TEXT32_ALIGNMENT_LEFT: offsetX = 0; break; default: warning("Invalid alignment %d used in TextBox()", alignment); } for (int i = 0; i < charCount; i++) { unsigned char curChar = txt[i]; font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height); curX += font->getCharWidth(curChar); } curX = 0; curY += font->getHeight(); txt += charCount; while (*txt == ' ') txt++; // skip over breaking spaces } return memoryId; }
/** * Loads and draws the chosen page of the help. * @remarks Originally called 'getme' */ void Help::switchPage(byte which) { // Help icons are 80x20. _highlightWas = 177; // Forget where the highlight was. Common::File file; if (!file.open("help.avd")) error("AVALANCHE: Help: File not found: help.avd"); file.seek(which * 2); uint16 offset = file.readUint16LE(); file.seek(offset); Common::String title = getLine(file); _vm->_graphics->drawFilledRectangle(Common::Rect(0, 0, 640, 200), kColorBlue); _vm->_graphics->drawFilledRectangle(Common::Rect(8, 40, 450, 200), kColorWhite); byte index = file.readByte(); _vm->_graphics->helpDrawButton(-177, index); // Plot the title: _vm->_graphics->drawNormalText(title, _vm->_font, 8, 629 - 8 * title.size(), 26, kColorBlack); _vm->_graphics->drawNormalText(title, _vm->_font, 8, 630 - 8 * title.size(), 25, kColorCyan); _vm->_graphics->helpDrawBigText("help!", 549, 1, kColorBlack); _vm->_graphics->helpDrawBigText("help!", 550, 0, kColorCyan); byte y = 0; do { Common::String line = getLine(file); if (!line.empty()) { if (line.compareTo(Common::String('!')) == 0) // End of the help text is signalled with a '!'. break; if (line[0] == '\\') { line.deleteChar(0); _vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorRed); } else _vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorBlack); } y++; } while (true); // We are now at the end of the text. Next we must read the icons: y = 0; _buttonNum = 0; while (!file.eos()) { int trigger = file.readByte(); if (trigger == 177) break; switch (trigger) { case 254: // Escape trigger = 27; break; case 214: // PageUp trigger = 280; break; case 216: // PageDown trigger = 281; break; default: // A - Z // The characters are stored in the file in uppercase, but we need the lowercase versions for KeyCode: trigger = tolower(trigger); break; } _buttons[y]._trigger = Common::KeyCode(trigger); index = file.readByte(); if (_buttons[y]._trigger != Common::KEYCODE_INVALID) _vm->_graphics->helpDrawButton(13 + (y + 1) * 27, index); _buttons[y]._whither = file.readByte(); // This is the position to jump to. Common::String text = ""; switch (_buttons[y]._trigger) { case Common::KEYCODE_ESCAPE: text = Common::String("Esc"); break; case Common::KEYCODE_PAGEUP: text = Common::String(24); break; case Common::KEYCODE_PAGEDOWN: text = Common::String(25); break; default: text = Common::String(toupper(_buttons[y]._trigger)); break; } _vm->_graphics->helpDrawBigText(text, 589 - (text.size() * 8), 18 + (y + 1) * 27, kColorBlack); _vm->_graphics->helpDrawBigText(text, 590 - (text.size() * 8), 17 + (y + 1) * 27, kColorCyan); y++; _buttonNum++; } _vm->_graphics->refreshScreen(); file.close(); }
void GfxControls32::kernelTexteditChange(reg_t controlObject) { SciEvent curEvent; uint16 maxChars = 40; //readSelectorValue(_segMan, controlObject, SELECTOR(max)); // TODO reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text)); GfxFont *font = _cache->getFont(readSelectorValue(_segMan, controlObject, SELECTOR(font))); Common::String text; uint16 textSize; bool textChanged = false; bool textAddChar = false; Common::Rect rect; if (textReference.isNull()) error("kEditControl called on object that doesn't have a text reference"); text = _segMan->getString(textReference); // TODO: Finish this warning("kEditText ('%s')", text.c_str()); return; uint16 cursorPos = 0; //uint16 oldCursorPos = cursorPos; bool captureEvents = true; EventManager* eventMan = g_sci->getEventManager(); while (captureEvents) { curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); if (curEvent.type == SCI_EVENT_NONE) { eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event } else { textSize = text.size(); switch (curEvent.type) { case SCI_EVENT_MOUSE_PRESS: // TODO: Implement mouse support for cursor change break; case SCI_EVENT_KEYBOARD: switch (curEvent.character) { case SCI_KEY_BACKSPACE: if (cursorPos > 0) { cursorPos--; text.deleteChar(cursorPos); textChanged = true; } eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; case SCI_KEY_DELETE: if (cursorPos < textSize) { text.deleteChar(cursorPos); textChanged = true; } eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; case SCI_KEY_HOME: // HOME cursorPos = 0; textChanged = true; eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; case SCI_KEY_END: // END cursorPos = textSize; textChanged = true; eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; case SCI_KEY_LEFT: // LEFT if (cursorPos > 0) { cursorPos--; textChanged = true; } eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; case SCI_KEY_RIGHT: // RIGHT if (cursorPos + 1 <= textSize) { cursorPos++; textChanged = true; } eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; case 3: // returned in SCI1 late and newer when Control - C is pressed if (curEvent.modifiers & SCI_KEYMOD_CTRL) { // Control-C erases the whole line cursorPos = 0; text.clear(); textChanged = true; } eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; case SCI_KEY_UP: case SCI_KEY_DOWN: case SCI_KEY_ENTER: case SCI_KEY_ESC: case SCI_KEY_TAB: case SCI_KEY_SHIFT_TAB: captureEvents = false; break; default: if ((curEvent.modifiers & SCI_KEYMOD_CTRL) && curEvent.character == 'c') { // Control-C in earlier SCI games (SCI0 - SCI1 middle) // Control-C erases the whole line cursorPos = 0; text.clear(); textChanged = true; } else if (curEvent.character > 31 && curEvent.character < 256 && textSize < maxChars) { // insert pressed character textAddChar = true; textChanged = true; } eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event break; } break; } } if (textChanged) { rect = g_sci->_gfxCompare->getNSRect(controlObject); if (textAddChar) { const char *textPtr = text.c_str(); // We check if we are really able to add the new char uint16 textWidth = 0; while (*textPtr) textWidth += font->getCharWidth((byte)*textPtr++); textWidth += font->getCharWidth(curEvent.character); // Does it fit? if (textWidth >= rect.width()) { return; } text.insertChar(curEvent.character, cursorPos++); // Note: the following checkAltInput call might make the text // too wide to fit, but SSCI fails to check that too. } reg_t hunkId = readSelector(_segMan, controlObject, SELECTOR(bitmap)); Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(controlObject); //texteditCursorErase(); // TODO: Cursor // Write back string _segMan->strcpy(textReference, text.c_str()); // Modify the buffer and show it warning("kernelTexteditChange"); #if 0 _text->createTextBitmap(controlObject, 0, 0, hunkId); _text->drawTextBitmap(0, 0, nsRect, controlObject); //texteditCursorDraw(rect, text.c_str(), cursorPos); // TODO: Cursor g_system->updateScreen(); #endif } else { // TODO: Cursor /* if (g_system->getMillis() >= _texteditBlinkTime) { _paint16->invertRect(_texteditCursorRect); _paint16->bitsShow(_texteditCursorRect); _texteditCursorVisible = !_texteditCursorVisible; texteditSetBlinkTime(); } */ } textAddChar = false; textChanged = false; g_sci->sleep(10); } // while }
Common::String HiRes4Engine_Atari::formatVerbError(const Common::String &verb) const { Common::String err = _strings.verbError; for (uint i = 0; i < verb.size(); ++i) err.setChar(verb[i], i + 8); return err; }
static uint find_in_str(const Common::String &str, char c, uint pos = 0) { while (pos < str.size() && str[pos] != c) ++pos; return pos; }
void SystemClass::dump(Common::WriteStream *stream) { Common::String str; str = Common::String::format("%03d %c %-20s instances: %d\n", _iD, _persistent ? 'p' : ' ', _name.c_str(), getNumInstances()); stream->write(str.c_str(), str.size()); }
void ComposerEngine::loadLibrary(uint id) { if (getGameType() == GType_ComposerV1 && !_libraries.empty()) { // kill the previous page, starting with any scripts running on it for (Common::List<OldScript *>::iterator i = _oldScripts.begin(); i != _oldScripts.end(); i++) delete *i; _oldScripts.clear(); Library *library = &_libraries.front(); unloadLibrary(library->_id); } Common::String filename; if (getGameType() == GType_ComposerV1) { if (!id || _bookGroup.empty()) filename = getStringFromConfig("Common", "StartPage"); else filename = getStringFromConfig(_bookGroup, Common::String::format("%d", id)); filename = mangleFilename(filename); // bookGroup is the basename of the path. // TODO: tidy this up. _bookGroup.clear(); for (uint i = 0; i < filename.size(); i++) { if (filename[i] == '~' || filename[i] == '/' || filename[i] == ':') continue; for (uint j = 0; j < filename.size(); j++) { if (filename[j] == '/') { _bookGroup.clear(); continue; } if (filename[j] == '.') break; _bookGroup += filename[j]; } break; } } else { if (!id) id = atoi(getStringFromConfig("Common", "StartUp").c_str()); filename = getFilename("Libs", id); } Library library; library._id = id; library._archive = new ComposerArchive(); if (!library._archive->openFile(filename)) error("failed to open '%s'", filename.c_str()); _libraries.push_front(library); Library &newLib = _libraries.front(); Common::Array<uint16> buttonResources = library._archive->getResourceIDList(ID_BUTN); for (uint i = 0; i < buttonResources.size(); i++) { uint16 buttonId = buttonResources[i]; Common::SeekableReadStream *stream = library._archive->getResource(ID_BUTN, buttonId); Button button(stream, buttonId, getGameType()); bool inserted = false; for (Common::List<Button>::iterator b = newLib._buttons.begin(); b != newLib._buttons.end(); b++) { if (button._zorder < b->_zorder) continue; newLib._buttons.insert(b, button); inserted = true; break; } if (!inserted) newLib._buttons.push_back(button); } Common::Array<uint16> ambientResources = library._archive->getResourceIDList(ID_AMBI); for (uint i = 0; i < ambientResources.size(); i++) { Common::SeekableReadStream *stream = library._archive->getResource(ID_AMBI, ambientResources[i]); Button button(stream); newLib._buttons.insert(newLib._buttons.begin(), button); } Common::Array<uint16> accelResources = library._archive->getResourceIDList(ID_ACEL); for (uint i = 0; i < accelResources.size(); i++) { Common::SeekableReadStream *stream = library._archive->getResource(ID_ACEL, accelResources[i]); KeyboardHandler handler; handler.keyId = stream->readUint16LE(); handler.modifierId = stream->readUint16LE(); handler.scriptId = stream->readUint16LE(); newLib._keyboardHandlers.push_back(handler); } Common::Array<uint16> randResources = library._archive->getResourceIDList(ID_RAND); for (uint i = 0; i < randResources.size(); i++) { Common::SeekableReadStream *stream = library._archive->getResource(ID_RAND, randResources[i]); Common::Array<RandomEvent> &events = _randomEvents[randResources[i]]; uint16 count = stream->readUint16LE(); for (uint j = 0; j < count; j++) { RandomEvent random; random.scriptId = stream->readUint16LE(); random.weight = stream->readUint16LE(); events.push_back(random); } delete stream; } // add background sprite, if it exists if (hasResource(ID_BMAP, 1000)) setBackground(1000); // TODO: better CTBL logic loadCTBL(1000, 100); // Run the startup script. runScript(1000, 0, 0, 0); _mouseEnabled = true; onMouseMove(_lastMousePos); runEvent(kEventLoad, id, 0, 0); }
void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, int row = 0, int pos = 0) { static const char *Comd[] = { "Name", "Type", "Phase", "East", "Left", "Right", "Top", "Bottom", "Seq", "Near", "Take", "Portable", "Transparent", NULL }; static const char *Type[] = { "DEAD", "AUTO", "WALK", "NEWTON", "LISSAJOUS", "FLY", NULL }; int shpcnt = 0; int type = 0; // DEAD bool east = false; bool port = false; bool tran = false; int i, lcnt = 0; char tmpStr[kLineMax + 1]; Common::String line; mergeExt(tmpStr, fname, kSprExt); if (_resman->exist(tmpStr)) { // sprite description file exist EncryptedStream sprf(this, tmpStr); if (sprf.err()) error("Bad SPR [%s]", tmpStr); uint16 len; for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) { len = line.size(); lcnt++; strcpy(tmpStr, line.c_str()); if (len == 0 || *tmpStr == '.') continue; if ((i = takeEnum(Comd, strtok(tmpStr, " =\t"))) < 0) error("Bad line %d [%s]", lcnt, fname); switch (i) { case 0 : // Name - will be taken in Expand routine break; case 1 : // Type if ((type = takeEnum(Type, strtok(NULL, " \t,;/"))) < 0) error("Bad line %d [%s]", lcnt, fname); break; case 2 : // Phase shpcnt++; break; case 3 : // East east = (atoi(strtok(NULL, " \t,;/")) != 0); break; case 11 : // Portable port = (atoi(strtok(NULL, " \t,;/")) != 0); break; case 12 : // Transparent tran = (atoi(strtok(NULL, " \t,;/")) != 0); break; } } if (! shpcnt) error("No shapes [%s]", fname); } else { // no sprite description: mono-shaped sprite with only .BMP file ++shpcnt; } // make sprite of choosen type switch (type) { case 1: // AUTO _sprite = new Sprite(this, NULL); if (_sprite) { _sprite->gotoxy(col, row); } break; case 2: { // WALK Walk *w = new Walk(this, NULL); if (w && ref == 1) { w->gotoxy(col, row); if (_hero) error("2nd HERO [%s]", fname); _hero = w; } _sprite = w; break; } case 3: // NEWTON case 4: // LISSAJOUS error("Bad type [%s]", fname); break; case 5: { // FLY Fly *f = new Fly(this, NULL); _sprite = f; break; } default: // DEAD _sprite = new Sprite(this, NULL); if (_sprite) _sprite->gotoxy(col, row); break; } if (_sprite) { _sprite->_ref = ref; _sprite->_scene = scene; _sprite->_z = pos; _sprite->_flags._east = east; _sprite->_flags._port = port; _sprite->_flags._tran = tran; _sprite->_flags._kill = true; _sprite->_flags._bDel = true; // Extract the filename, without the extension strcpy(_sprite->_file, fname); char *p = strchr(_sprite->_file, '.'); if (p) *p = '\0'; _sprite->_shpCnt = shpcnt; _vga->_spareQ->append(_sprite); } }
bool Sword2Engine::initStartMenu() { // Print out a list of all the start points available. // There should be a linc produced file called startup.txt. // This file should contain ascii numbers of all the resource game // objects that are screen managers. // We query each in turn and setup an array of start structures. // If the file doesn't exist then we say so and return a 0. Common::File fp; // ok, load in the master screen manager file _totalStartups = 0; _totalScreenManagers = 0; if (!fp.open("startup.inf")) { warning("Cannot open startup.inf - the debugger won't have a start menu"); return false; } // The startup.inf file which contains a list of all the files. Now // extract the filenames int start_ids[MAX_starts]; int lineno = 0; while (!fp.eos() && !fp.err()) { Common::String line = fp.readLine(); // Skip empty lines or, more likely, the end of the stream. if (line.size() == 0) continue; char *errptr; int id; lineno++; id = strtol(line.c_str(), &errptr, 10); if (*errptr) { warning("startup.inf:%d: Invalid string '%s'", lineno, line.c_str()); continue; } if (!_resman->checkValid(id)) { warning("startup.inf:%d: Invalid resource %d", lineno, id); continue; } if (_resman->fetchType(id) != SCREEN_MANAGER) { warning("startup.inf:%d: '%s' (%d) is not a screen manager", lineno, _resman->fetchName(id), id); continue; } start_ids[_totalScreenManagers] = id; if (++_totalScreenManagers >= MAX_starts) { warning("Too many entries in startup.inf"); break; } } // An I/O error before EOS? That's bad, but this is not a vital file. if (fp.err() && !fp.eos()) warning("I/O error while reading startup.inf"); fp.close(); // Using this method the Gode generated resource.inf must have #0d0a // on the last entry debug(1, "%d screen manager objects", _totalScreenManagers); // Open each object and make a query call. The object must fill in a // startup structure. It may fill in several if it wishes - for // instance a startup could be set for later in the game where // specific vars are set for (uint i = 0; i < _totalScreenManagers; i++) { _startRes = start_ids[i]; debug(2, "Querying screen manager %d", _startRes); // Open each one and run through the interpreter. Script 0 is // the query request script. We have already made reasonably // sure the resource is ok. _logic->runResScript(_startRes, 0); } return 1; }
void CGEEngine::loadScript(const char *fname) { EncryptedStream scrf(this, fname); if (scrf.err()) return; bool ok = true; int lcnt = 0; char tmpStr[kLineMax+1]; Common::String line; for (line = scrf.readLine(); !scrf.eos(); line = scrf.readLine()) { char *p; lcnt++; strcpy(tmpStr, line.c_str()); if ((line.size() == 0) || (*tmpStr == '.')) continue; ok = false; // not OK if break // sprite ident number if ((p = strtok(tmpStr, " \t\n")) == NULL) break; int SpI = atoi(p); // sprite file name char *SpN; if ((SpN = strtok(NULL, " ,;/\t\n")) == NULL) break; // sprite scene if ((p = strtok(NULL, " ,;/\t\n")) == NULL) break; int SpA = atoi(p); // sprite column if ((p = strtok(NULL, " ,;/\t\n")) == NULL) break; int SpX = atoi(p); // sprite row if ((p = strtok(NULL, " ,;/\t\n")) == NULL) break; int SpY = atoi(p); // sprite Z pos if ((p = strtok(NULL, " ,;/\t\n")) == NULL) break; int SpZ = atoi(p); // sprite life if ((p = strtok(NULL, " ,;/\t\n")) == NULL) break; bool BkG = atoi(p) == 0; ok = true; // no break: OK _sprite = NULL; loadSprite(SpN, SpI, SpA, SpX, SpY, SpZ); if (_sprite && BkG) _sprite->_flags._back = true; } if (!ok) error("Bad INI line %d [%s]", lcnt, fname); }